Initial revision
authorMarc Fiuczynski <mef@cs.princeton.edu>
Mon, 19 Jul 2004 17:08:09 +0000 (17:08 +0000)
committerMarc Fiuczynski <mef@cs.princeton.edu>
Mon, 19 Jul 2004 17:08:09 +0000 (17:08 +0000)
226 files changed:
arch/arm/boot/bootp/initrd.S [new file with mode: 0644]
arch/arm/boot/bootp/kernel.S [new file with mode: 0644]
arch/arm/boot/compressed/piggy.S [new file with mode: 0644]
arch/arm/mach-sa1100/collie.c [new file with mode: 0644]
arch/mips/configs/ocelot_g_defconfig [new file with mode: 0644]
arch/mips/pci/fixup-jaguar.c [new file with mode: 0644]
arch/mips/pci/fixup-ocelot-c.c [new file with mode: 0644]
arch/mips/pci/fixup-ocelot-g.c [new file with mode: 0644]
arch/mips/pci/fixup-tb0219.c [new file with mode: 0644]
arch/mips/pci/ops-marvell.c [new file with mode: 0644]
arch/mips/pci/ops-titan-ht.c [new file with mode: 0644]
arch/mips/pci/ops-vr41xx.c [new file with mode: 0644]
arch/mips/pmc-sierra/yosemite/dbg_io.c [new file with mode: 0644]
arch/mips/pmc-sierra/yosemite/py-console.c [new file with mode: 0644]
arch/ppc/configs/ads8272_defconfig [new file with mode: 0644]
arch/ppc/lib/rheap.c [new file with mode: 0644]
arch/ppc/platforms/85xx/sbc8560.c [new file with mode: 0644]
arch/ppc/platforms/85xx/sbc8560.h [new file with mode: 0644]
arch/ppc/platforms/85xx/sbc85xx.c [new file with mode: 0644]
arch/ppc/syslib/cpm2_common.c [new file with mode: 0644]
arch/ppc/syslib/m8260_pci_erratum9.c [new file with mode: 0644]
arch/sh/boards/renesas/systemh/Makefile [new file with mode: 0644]
arch/sh/boards/se/7300/Makefile [new file with mode: 0644]
arch/sh/cchips/voyagergx/Makefile [new file with mode: 0644]
arch/sh/cchips/voyagergx/consistent.c [new file with mode: 0644]
arch/sh/configs/rts7751r2d_defconfig [new file with mode: 0644]
arch/sh/kernel/cpu/adc.c [new file with mode: 0644]
arch/sh64/boot/Makefile [new file with mode: 0644]
arch/sh64/boot/compressed/Makefile [new file with mode: 0644]
arch/sh64/boot/compressed/cache.c [new file with mode: 0644]
arch/sh64/boot/compressed/head.S [new file with mode: 0644]
arch/sh64/boot/compressed/install.sh [new file with mode: 0644]
arch/sh64/configs/cayman_defconfig [new file with mode: 0644]
arch/sh64/defconfig [new file with mode: 0644]
arch/sh64/kernel/Makefile [new file with mode: 0644]
arch/sh64/kernel/asm-offsets.c [new file with mode: 0644]
arch/sh64/kernel/early_printk.c [new file with mode: 0644]
arch/sh64/kernel/fpu.c [new file with mode: 0644]
arch/sh64/kernel/init_task.c [new file with mode: 0644]
arch/sh64/kernel/pci-dma.c [new file with mode: 0644]
arch/sh64/kernel/pci_sh5.h [new file with mode: 0644]
arch/sh64/kernel/semaphore.c [new file with mode: 0644]
arch/sh64/kernel/switchto.S [new file with mode: 0644]
arch/sh64/kernel/syscalls.S [new file with mode: 0644]
arch/sh64/kernel/traps.c [new file with mode: 0644]
arch/sh64/kernel/unwind.c [new file with mode: 0644]
arch/sh64/lib/Makefile [new file with mode: 0644]
arch/sh64/lib/copy_user_memcpy.S [new file with mode: 0644]
arch/sh64/lib/page_clear.S [new file with mode: 0644]
arch/sh64/lib/page_copy.S [new file with mode: 0644]
arch/sh64/lib/panic.c [new file with mode: 0644]
arch/sh64/mach-cayman/Makefile [new file with mode: 0644]
arch/sh64/mach-harp/Makefile [new file with mode: 0644]
arch/sh64/mach-romram/Makefile [new file with mode: 0644]
arch/sh64/mach-sim/Makefile [new file with mode: 0644]
arch/sh64/mm/Makefile [new file with mode: 0644]
arch/sh64/mm/tlb.c [new file with mode: 0644]
arch/sh64/mm/tlbmiss.c [new file with mode: 0644]
arch/sh64/oprofile/Kconfig [new file with mode: 0644]
arch/sh64/oprofile/Makefile [new file with mode: 0644]
crypto/mpi/Makefile [new file with mode: 0644]
crypto/mpi/generic_mpi-asm-defs.h [new file with mode: 0644]
crypto/mpi/generic_mpih-add1.c [new file with mode: 0644]
crypto/mpi/generic_mpih-lshift.c [new file with mode: 0644]
crypto/mpi/generic_mpih-mul1.c [new file with mode: 0644]
crypto/mpi/generic_mpih-mul2.c [new file with mode: 0644]
crypto/mpi/generic_mpih-mul3.c [new file with mode: 0644]
crypto/mpi/generic_mpih-rshift.c [new file with mode: 0644]
crypto/mpi/generic_mpih-sub1.c [new file with mode: 0644]
crypto/mpi/generic_udiv-w-sdiv.c [new file with mode: 0644]
crypto/mpi/longlong.h [new file with mode: 0644]
crypto/mpi/mpi-add.c [new file with mode: 0644]
crypto/mpi/mpi-bit.c [new file with mode: 0644]
crypto/mpi/mpi-cmp.c [new file with mode: 0644]
crypto/mpi/mpi-div.c [new file with mode: 0644]
crypto/mpi/mpi-gcd.c [new file with mode: 0644]
crypto/mpi/mpi-inline.c [new file with mode: 0644]
crypto/mpi/mpi-inline.h [new file with mode: 0644]
crypto/mpi/mpi-internal.h [new file with mode: 0644]
crypto/mpi/mpi-inv.c [new file with mode: 0644]
crypto/mpi/mpi-mpow.c [new file with mode: 0644]
crypto/mpi/mpi-mul.c [new file with mode: 0644]
crypto/mpi/mpi-pow.c [new file with mode: 0644]
crypto/mpi/mpi-scan.c [new file with mode: 0644]
crypto/mpi/mpicoder.c [new file with mode: 0644]
crypto/mpi/mpih-cmp.c [new file with mode: 0644]
crypto/mpi/mpih-div.c [new file with mode: 0644]
crypto/mpi/mpih-mul.c [new file with mode: 0644]
crypto/mpi/mpiutil.c [new file with mode: 0644]
crypto/signature/Makefile [new file with mode: 0644]
crypto/signature/dsa.c [new file with mode: 0644]
crypto/signature/key.h [new file with mode: 0644]
crypto/signature/ksign-keyring.c [new file with mode: 0644]
crypto/signature/ksign-parse.c [new file with mode: 0644]
crypto/signature/ksign-publickey.c [new file with mode: 0644]
crypto/signature/ksign.c [new file with mode: 0644]
crypto/signature/local.h [new file with mode: 0644]
drivers/char/lcd.h [new file with mode: 0644]
drivers/firmware/pcdp.c [new file with mode: 0644]
drivers/firmware/pcdp.h [new file with mode: 0644]
drivers/media/video/ovcamchip/ov6x20.c [new file with mode: 0644]
drivers/media/video/ovcamchip/ov6x30.c [new file with mode: 0644]
drivers/media/video/ovcamchip/ov76be.c [new file with mode: 0644]
drivers/media/video/ovcamchip/ov7x10.c [new file with mode: 0644]
drivers/media/video/ovcamchip/ov7x20.c [new file with mode: 0644]
drivers/net/fec_8xx/Kconfig [new file with mode: 0644]
drivers/net/fec_8xx/Makefile [new file with mode: 0644]
drivers/net/fec_8xx/fec_8xx.h [new file with mode: 0644]
drivers/net/netdump.c [new file with mode: 0644]
drivers/net/netdump.h [new file with mode: 0644]
drivers/pcmcia/pd6729.c [new file with mode: 0644]
drivers/pcmcia/pd6729.h [new file with mode: 0644]
drivers/s390/net/ctcdbug.c [new file with mode: 0644]
drivers/s390/net/ctcdbug.h [new file with mode: 0644]
drivers/scsi/fdomain.h [new file with mode: 0644]
drivers/scsi/sata_nv.c [new file with mode: 0644]
drivers/serial/cpm_uart/Makefile [new file with mode: 0644]
drivers/serial/cpm_uart/cpm_uart_core.c [new file with mode: 0644]
drivers/serial/cpm_uart/cpm_uart_cpm1.c [new file with mode: 0644]
drivers/serial/cpm_uart/cpm_uart_cpm1.h [new file with mode: 0644]
drivers/serial/cpm_uart/cpm_uart_cpm2.c [new file with mode: 0644]
drivers/serial/cpm_uart/cpm_uart_cpm2.h [new file with mode: 0644]
drivers/w1/Kconfig [new file with mode: 0644]
drivers/w1/matrox_w1.c [new file with mode: 0644]
drivers/w1/w1.c [new file with mode: 0644]
drivers/w1/w1_int.c [new file with mode: 0644]
drivers/w1/w1_int.h [new file with mode: 0644]
drivers/w1/w1_io.c [new file with mode: 0644]
drivers/w1/w1_log.h [new file with mode: 0644]
fs/ntfs/collate.c [new file with mode: 0644]
include/asm-alpha/setup.h [new file with mode: 0644]
include/asm-generic/netdump.h [new file with mode: 0644]
include/asm-i386/netdump.h [new file with mode: 0644]
include/asm-ia64/netdump.h [new file with mode: 0644]
include/asm-ia64/setup.h [new file with mode: 0644]
include/asm-mips/gt64240.h [new file with mode: 0644]
include/asm-ppc/cpm2.h [new file with mode: 0644]
include/asm-ppc/immap_cpm2.h [new file with mode: 0644]
include/asm-ppc/m8260_pci.h [new file with mode: 0644]
include/asm-ppc64/netdump.h [new file with mode: 0644]
include/asm-s390/netdump.h [new file with mode: 0644]
include/asm-sh/adc.h [new file with mode: 0644]
include/asm-sh/cpu-sh3/adc.h [new file with mode: 0644]
include/asm-sh64/a.out.h [new file with mode: 0644]
include/asm-sh64/atomic.h [new file with mode: 0644]
include/asm-sh64/bugs.h [new file with mode: 0644]
include/asm-sh64/cache.h [new file with mode: 0644]
include/asm-sh64/cayman.h [new file with mode: 0644]
include/asm-sh64/cpumask.h [new file with mode: 0644]
include/asm-sh64/current.h [new file with mode: 0644]
include/asm-sh64/delay.h [new file with mode: 0644]
include/asm-sh64/div64.h [new file with mode: 0644]
include/asm-sh64/dma.h [new file with mode: 0644]
include/asm-sh64/elf.h [new file with mode: 0644]
include/asm-sh64/errno.h [new file with mode: 0644]
include/asm-sh64/fcntl.h [new file with mode: 0644]
include/asm-sh64/hardware.h [new file with mode: 0644]
include/asm-sh64/ioctl.h [new file with mode: 0644]
include/asm-sh64/ioctls.h [new file with mode: 0644]
include/asm-sh64/ipc.h [new file with mode: 0644]
include/asm-sh64/ipcbuf.h [new file with mode: 0644]
include/asm-sh64/kmap_types.h [new file with mode: 0644]
include/asm-sh64/linkage.h [new file with mode: 0644]
include/asm-sh64/local.h [new file with mode: 0644]
include/asm-sh64/mc146818rtc.h [new file with mode: 0644]
include/asm-sh64/mman.h [new file with mode: 0644]
include/asm-sh64/mmu.h [new file with mode: 0644]
include/asm-sh64/module.h [new file with mode: 0644]
include/asm-sh64/msgbuf.h [new file with mode: 0644]
include/asm-sh64/namei.h [new file with mode: 0644]
include/asm-sh64/pci.h [new file with mode: 0644]
include/asm-sh64/percpu.h [new file with mode: 0644]
include/asm-sh64/posix_types.h [new file with mode: 0644]
include/asm-sh64/registers.h [new file with mode: 0644]
include/asm-sh64/resource.h [new file with mode: 0644]
include/asm-sh64/scatterlist.h [new file with mode: 0644]
include/asm-sh64/sections.h [new file with mode: 0644]
include/asm-sh64/segment.h [new file with mode: 0644]
include/asm-sh64/semaphore-helper.h [new file with mode: 0644]
include/asm-sh64/semaphore.h [new file with mode: 0644]
include/asm-sh64/sembuf.h [new file with mode: 0644]
include/asm-sh64/shmbuf.h [new file with mode: 0644]
include/asm-sh64/sigcontext.h [new file with mode: 0644]
include/asm-sh64/siginfo.h [new file with mode: 0644]
include/asm-sh64/smp.h [new file with mode: 0644]
include/asm-sh64/socket.h [new file with mode: 0644]
include/asm-sh64/sockios.h [new file with mode: 0644]
include/asm-sh64/spinlock.h [new file with mode: 0644]
include/asm-sh64/stat.h [new file with mode: 0644]
include/asm-sh64/statfs.h [new file with mode: 0644]
include/asm-sh64/string.h [new file with mode: 0644]
include/asm-sh64/termbits.h [new file with mode: 0644]
include/asm-sh64/termios.h [new file with mode: 0644]
include/asm-sh64/thread_info.h [new file with mode: 0644]
include/asm-sh64/tlb.h [new file with mode: 0644]
include/asm-sh64/tlbflush.h [new file with mode: 0644]
include/asm-sh64/topology.h [new file with mode: 0644]
include/asm-sh64/types.h [new file with mode: 0644]
include/asm-sh64/uaccess.h [new file with mode: 0644]
include/asm-sh64/ucontext.h [new file with mode: 0644]
include/asm-sh64/unaligned.h [new file with mode: 0644]
include/asm-sparc64/cmt.h [new file with mode: 0644]
include/asm-um/setup.h [new file with mode: 0644]
include/asm-v850/setup.h [new file with mode: 0644]
include/asm-x86_64/netdump.h [new file with mode: 0644]
include/linux/crc-ccitt.h [new file with mode: 0644]
include/linux/crypto/ksign.h [new file with mode: 0644]
include/linux/crypto/mpi.h [new file with mode: 0644]
include/linux/ds1286.h [new file with mode: 0644]
include/linux/netfilter_ipv4/ipt_addrtype.h [new file with mode: 0644]
include/linux/netfilter_ipv4/ipt_realm.h [new file with mode: 0644]
kernel/module-verify.c [new file with mode: 0644]
kernel/module-verify.h [new file with mode: 0644]
net/bluetooth/hidp/Makefile [new file with mode: 0644]
net/bluetooth/hidp/core.c [new file with mode: 0644]
net/bluetooth/hidp/hidp.h [new file with mode: 0644]
net/ipv4/xfrm4_output.c [new file with mode: 0644]
net/ipv6/xfrm6_tunnel.c [new file with mode: 0644]
net/sched/sch_netem.c [new file with mode: 0644]
scripts/modsign/Makefile [new file with mode: 0644]
scripts/modsign/mod-extract.c [new file with mode: 0644]
scripts/modsign/mod-extract.sh [new file with mode: 0644]
scripts/modsign/modsign.sh [new file with mode: 0644]
scripts/package/Makefile [new file with mode: 0644]
scripts/package/builddeb [new file with mode: 0644]
scripts/package/mkspec [new file with mode: 0644]

diff --git a/arch/arm/boot/bootp/initrd.S b/arch/arm/boot/bootp/initrd.S
new file mode 100644 (file)
index 0000000..d81ea18
--- /dev/null
@@ -0,0 +1,6 @@
+       .type   initrd_start,#object
+       .globl  initrd_start
+initrd_start:
+       .incbin INITRD
+       .globl  initrd_end
+initrd_end:
diff --git a/arch/arm/boot/bootp/kernel.S b/arch/arm/boot/bootp/kernel.S
new file mode 100644 (file)
index 0000000..b87a25c
--- /dev/null
@@ -0,0 +1,6 @@
+       .globl  kernel_start
+kernel_start:
+       .incbin "arch/arm/boot/zImage"
+       .globl  kernel_end
+kernel_end:
+       .align  2
diff --git a/arch/arm/boot/compressed/piggy.S b/arch/arm/boot/compressed/piggy.S
new file mode 100644 (file)
index 0000000..54c9518
--- /dev/null
@@ -0,0 +1,6 @@
+       .section .piggydata,#alloc
+       .globl  input_data
+input_data:
+       .incbin "arch/arm/boot/compressed/piggy.gz"
+       .globl  input_data_end
+input_data_end:
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
new file mode 100644 (file)
index 0000000..dcbb3c7
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * linux/arch/arm/mach-sa1100/collie.c
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * This file contains all Collie-specific tweaks.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ChangeLog:
+ *  03-06-2004 John Lenz <jelenz@wisc.edu>
+ *  06-04-2002 Chris Larson <kergoth@digitalnemesis.net>
+ *  04-16-2001 Lineo Japan,Inc. ...
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/timer.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/arch/collie.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/serial_sa1100.h>
+
+#include <asm/hardware/locomo.h>
+
+#include "generic.h"
+
+static void __init scoop_init(void)
+{
+
+#define        COLLIE_SCP_INIT_DATA(adr,dat)   (((adr)<<16)|(dat))
+#define        COLLIE_SCP_INIT_DATA_END        ((unsigned long)-1)
+       static const unsigned long scp_init[] = {
+               COLLIE_SCP_INIT_DATA(COLLIE_SCP_MCR, 0x0140),   // 00
+               COLLIE_SCP_INIT_DATA(COLLIE_SCP_MCR, 0x0100),
+               COLLIE_SCP_INIT_DATA(COLLIE_SCP_CDR, 0x0000),   // 04
+               COLLIE_SCP_INIT_DATA(COLLIE_SCP_CPR, 0x0000),   // 0C
+               COLLIE_SCP_INIT_DATA(COLLIE_SCP_CCR, 0x0000),   // 10
+               COLLIE_SCP_INIT_DATA(COLLIE_SCP_IMR, 0x0000),   // 18
+               COLLIE_SCP_INIT_DATA(COLLIE_SCP_IRM, 0x00FF),   // 14
+               COLLIE_SCP_INIT_DATA(COLLIE_SCP_ISR, 0x0000),   // 1C
+               COLLIE_SCP_INIT_DATA(COLLIE_SCP_IRM, 0x0000),
+               COLLIE_SCP_INIT_DATA(COLLIE_SCP_GPCR, COLLIE_SCP_IO_DIR),       // 20
+               COLLIE_SCP_INIT_DATA(COLLIE_SCP_GPWR, COLLIE_SCP_IO_OUT),       // 24
+               COLLIE_SCP_INIT_DATA_END
+       };
+       int i;
+       for (i = 0; scp_init[i] != COLLIE_SCP_INIT_DATA_END; i++) {
+               int adr = scp_init[i] >> 16;
+               COLLIE_SCP_REG(adr) = scp_init[i] & 0xFFFF;
+       }
+
+}
+
+static struct resource locomo_resources[] = {
+       [0] = {
+               .start          = 0x40000000,
+               .end            = 0x40001fff,
+               .flags          = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start          = IRQ_GPIO25,
+               .end            = IRQ_GPIO25,
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device locomo_device = {
+       .name           = "locomo",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(locomo_resources),
+       .resource       = locomo_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+       &locomo_device,
+};
+
+static void __init collie_init(void)
+{
+       int ret = 0;
+
+       /* cpu initialize */
+       GAFR = ( GPIO_SSP_TXD | \
+                GPIO_SSP_SCLK | GPIO_SSP_SFRM | GPIO_SSP_CLK | GPIO_TIC_ACK | \
+                GPIO_32_768kHz );
+
+       GPDR = ( GPIO_LDD8 | GPIO_LDD9 | GPIO_LDD10 | GPIO_LDD11 | GPIO_LDD12 | \
+                GPIO_LDD13 | GPIO_LDD14 | GPIO_LDD15 | GPIO_SSP_TXD | \
+                GPIO_SSP_SCLK | GPIO_SSP_SFRM | GPIO_SDLC_SCLK | \
+                GPIO_SDLC_AAF | GPIO_UART_SCLK1 | GPIO_32_768kHz );
+       GPLR = GPIO_GPIO18;
+
+       // PPC pin setting
+       PPDR = ( PPC_LDD0 | PPC_LDD1 | PPC_LDD2 | PPC_LDD3 | PPC_LDD4 | PPC_LDD5 | \
+                PPC_LDD6 | PPC_LDD7 | PPC_L_PCLK | PPC_L_LCLK | PPC_L_FCLK | PPC_L_BIAS | \
+                PPC_TXD1 | PPC_TXD2 | PPC_RXD2 | PPC_TXD3 | PPC_TXD4 | PPC_SCLK | PPC_SFRM );
+
+       PSDR = ( PPC_RXD1 | PPC_RXD2 | PPC_RXD3 | PPC_RXD4 );
+
+       GAFR |= GPIO_32_768kHz;
+       GPDR |= GPIO_32_768kHz;
+       TUCR  = TUCR_32_768kHz;
+
+       scoop_init();
+
+       ret = platform_add_devices(devices, ARRAY_SIZE(devices));
+       if (ret) {
+               printk(KERN_WARNING "collie: Unable to register LoCoMo device\n");
+       }
+}
+
+static struct map_desc collie_io_desc[] __initdata = {
+       /* virtual     physical    length      type */
+       {0xe8000000, 0x00000000, 0x02000000, MT_DEVICE},        /* 32M main flash (cs0) */
+       {0xea000000, 0x08000000, 0x02000000, MT_DEVICE},        /* 32M boot flash (cs1) */
+       {0xf0000000, 0x40000000, 0x01000000, MT_DEVICE},        /* 16M LOCOMO  & SCOOP (cs4) */
+};
+
+static void __init collie_map_io(void)
+{
+       sa1100_map_io();
+       iotable_init(collie_io_desc, ARRAY_SIZE(collie_io_desc));
+}
+
+MACHINE_START(COLLIE, "Sharp-Collie")
+       BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+       MAPIO(collie_map_io)
+       INITIRQ(sa1100_init_irq)
+       INIT_MACHINE(collie_init)
+MACHINE_END
diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/ocelot_g_defconfig
new file mode 100644 (file)
index 0000000..fa25841
--- /dev/null
@@ -0,0 +1,592 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+CONFIG_MIPS64=y
+CONFIG_64BIT=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Machine selection
+#
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MOMENCO_OCELOT is not set
+CONFIG_MOMENCO_OCELOT_G=y
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_NEC_OSPREY is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_SB1xxx_SOC is not set
+# CONFIG_SNI_RM200_PCI is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_DMA_NONCOHERENT=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_CPU_RM7K=y
+CONFIG_PCI_MARVELL=y
+CONFIG_SWAP_IO_SPACE=y
+# CONFIG_SYSCLK_75 is not set
+# CONFIG_SYSCLK_83 is not set
+CONFIG_SYSCLK_100=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+# CONFIG_FB is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_MIPS64 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+CONFIG_CPU_RM7000=y
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_BOARD_SCACHE=y
+CONFIG_RM7000_CPU_SCACHE=y
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_LLDSCD=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_MMU=y
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
+CONFIG_BINFMT_ELF32=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_NETLINK_DEV=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_GALILEO_64240_ETH=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC16=y
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/mips/pci/fixup-jaguar.c b/arch/mips/pci/fixup-jaguar.c
new file mode 100644 (file)
index 0000000..fa78b9b
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Marvell MV64340 interrupt fixup code.
+ *
+ * Marvell wants an NDA for their docs so this was written without
+ * documentation.  You've been warned.
+ *
+ * Copyright (C) 2004 Ralf Baechle
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/mipsregs.h>
+#include <asm/pci_channel.h>
+
+/*
+ * WARNING: Example of how _NOT_ to do it.
+ */
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       int bus = dev->bus->number;
+
+       if (bus == 0 && slot == 1)
+               return 3;       /* PCI-X A */
+       if (bus == 0 && slot == 2)
+               return 4;       /* PCI-X B */
+       if (bus == 1 && slot == 1)
+               return 5;       /* PCI A */
+       if (bus == 1 && slot == 2)
+               return 6;       /* PCI B */
+
+return 0;
+       panic("Whooops in pcibios_map_irq");
+}
+
+struct pci_fixup pcibios_fixups[] = {
+       {0}
+};
diff --git a/arch/mips/pci/fixup-ocelot-c.c b/arch/mips/pci/fixup-ocelot-c.c
new file mode 100644 (file)
index 0000000..0cc86ec
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2002 Momentum Computer Inc.
+ * Author: Matthew Dharm <mdharm@momenco.com>
+ *
+ * Based on work for the Linux port to the Ocelot board, which is
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * arch/mips/momentum/ocelot_g/pci.c
+ *     Board-specific PCI routines for mv64340 controller.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       int bus = dev->bus->number;
+
+       if (bus == 0 && slot == 1)
+               return 2;       /* PCI-X A */
+       if (bus == 1 && slot == 1)
+               return 12;      /* PCI-X B */
+       if (bus == 1 && slot == 2)
+               return 4;       /* PCI B */
+
+return 0;
+       panic("Whooops in pcibios_map_irq");
+}
+
+struct pci_fixup pcibios_fixups[] = {
+       {0}
+};
diff --git a/arch/mips/pci/fixup-ocelot-g.c b/arch/mips/pci/fixup-ocelot-g.c
new file mode 100644 (file)
index 0000000..9a2cc85
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 2004 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       int bus = dev->bus->number;
+
+       if (bus == 0 && slot == 1)      /* Intel 82543 Gigabit MAC */
+               return 2;               /* irq_nr is 2 for INT0 */
+
+       if (bus == 0 && slot == 2)      /* Intel 82543 Gigabit MAC */
+               return 3;               /* irq_nr is 3 for INT1 */
+
+       if (bus == 1 && slot == 3)      /* Intel 21555 bridge */
+               return 5;               /* irq_nr is 8 for INT6 */
+
+       if (bus == 1 && slot == 4)      /* PMC Slot */
+               return 9;               /* irq_nr is 9 for INT7 */
+
+       return -1;
+}
+
+struct pci_fixup pcibios_fixups[] = {
+       {0}
+};
diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c
new file mode 100644 (file)
index 0000000..ca4d99f
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  fixup-tb0219.c, The TANBAC TB0219 specific PCI fixups.
+ *
+ *  Copyright (C) 2003  Megasolution Inc. <matsu@megasolution.jp>
+ *  Copyright (C) 2004  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/vr41xx/tb0219.h>
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       int irq = -1;
+
+       switch (slot) {
+       case 12:
+               vr41xx_set_irq_trigger(TB0219_PCI_SLOT1_PIN,
+                                      TRIGGER_LEVEL,
+                                      SIGNAL_THROUGH);
+               vr41xx_set_irq_level(TB0219_PCI_SLOT1_PIN,
+                                    LEVEL_LOW);
+               irq = TB0219_PCI_SLOT1_IRQ;
+               break;
+       case 13:
+               vr41xx_set_irq_trigger(TB0219_PCI_SLOT2_PIN,
+                                      TRIGGER_LEVEL,
+                                      SIGNAL_THROUGH);
+               vr41xx_set_irq_level(TB0219_PCI_SLOT2_PIN,
+                                    LEVEL_LOW);
+               irq = TB0219_PCI_SLOT2_IRQ;
+               break;
+       case 14:
+               vr41xx_set_irq_trigger(TB0219_PCI_SLOT3_PIN,
+                                      TRIGGER_LEVEL,
+                                      SIGNAL_THROUGH);
+               vr41xx_set_irq_level(TB0219_PCI_SLOT3_PIN,
+                                    LEVEL_LOW);
+               irq = TB0219_PCI_SLOT3_IRQ;
+               break;
+       default:
+               break;
+       }
+
+       return irq;
+}
+
+struct pci_fixup pcibios_fixups[] __initdata = {
+       {       .pass = 0,      },
+};
diff --git a/arch/mips/pci/ops-marvell.c b/arch/mips/pci/ops-marvell.c
new file mode 100644 (file)
index 0000000..1ac5c59
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include <asm/marvell.h>
+
+static int mv_read_config(struct pci_bus *bus, unsigned int devfn,
+       int where, int size, u32 * val)
+{
+       struct mv_pci_controller *mvbc = bus->sysdata;
+       unsigned long address_reg, data_reg;
+       u32 address;
+
+       address_reg = mvbc->config_addr;
+       data_reg = mvbc->config_vreg;
+
+       /* Accessing device 31 crashes those Marvells.  Since years.
+          Will they ever make sane controllers ... */
+       if (PCI_SLOT(devfn) == 31)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       address = (bus->number << 16) | (devfn << 8) |
+                 (where & 0xfc) | 0x80000000;
+
+       /* start the configuration cycle */
+       MV_WRITE(address_reg, address);
+
+       switch (size) {
+       case 1:
+               *val = MV_READ_8(data_reg + (where & 0x3));
+               break;
+
+       case 2:
+               *val = MV_READ_16(data_reg + (where & 0x3));
+               break;
+
+       case 4:
+               *val = MV_READ(data_reg);
+               break;
+       }
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int mv_write_config(struct pci_bus *bus, unsigned int devfn,
+       int where, int size, u32 val)
+{
+       struct mv_pci_controller *mvbc = bus->sysdata;
+       unsigned long address_reg, data_reg;
+       u32 address;
+
+       address_reg = mvbc->config_addr;
+       data_reg = mvbc->config_vreg;
+
+       /* Accessing device 31 crashes those Marvells.  Since years.
+          Will they ever make sane controllers ... */
+       if (PCI_SLOT(devfn) == 31)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       address = (bus->number << 16) | (devfn << 8) |
+                 (where & 0xfc) | 0x80000000;
+
+       /* start the configuration cycle */
+       MV_WRITE(address_reg, address);
+
+       switch (size) {
+       case 1:
+               MV_WRITE_8(data_reg + (where & 0x3), val);
+               break;
+
+       case 2:
+               MV_WRITE_16(data_reg + (where & 0x3), val);
+               break;
+
+       case 4:
+               MV_WRITE(data_reg, val);
+               break;
+       }
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops mv_pci_ops = {
+       .read   = mv_read_config,
+       .write  = mv_write_config
+};
diff --git a/arch/mips/pci/ops-titan-ht.c b/arch/mips/pci/ops-titan-ht.c
new file mode 100644 (file)
index 0000000..46c636c
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+
+#include <asm/titan_dep.h>
+
+static int titan_ht_config_read_dword(struct pci_bus *bus, unsigned int devfn,
+       int offset, u32 * val)
+{
+       volatile uint32_t address;
+       int busno;
+
+       busno = bus->number;
+
+       address = (busno << 16) | (devfn << 8) | (offset & 0xfc) | 0x80000000;
+       if (busno != 0)
+               address |= 1;
+
+       /*
+        * RM9000 HT Errata: Issue back to back HT config
+        * transcations. Issue a BIU sync before and
+        * after the HT cycle
+        */
+
+       *(volatile int32_t *) 0xfb0000f0 |= 0x2;
+
+       udelay(30);
+
+       *(volatile int32_t *) 0xfb0006f8 = address;
+       *(val) = *(volatile int32_t *) 0xfb0006fc;
+
+       udelay(30);
+
+       * (volatile int32_t *) 0xfb0000f0 |= 0x2;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int titan_ht_config_read(struct pci_bus *bus, unsigned int devfn,
+       int offset, int size, u32 * val)
+{
+       uint32_t dword;
+
+       titan_ht_config_read_dword(bus, devfn, offset, &dword);
+
+       dword >>= ((offset & 3) << 3);
+       dword &= (0xffffffffU >> ((4 - size) << 8));
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static inline int titan_ht_config_write_dword(struct pci_bus *bus,
+       unsigned int devfn, int offset, u32 val)
+{
+       volatile uint32_t address;
+       int busno;
+
+       busno = bus->number;
+
+       address = (busno << 16) | (devfn << 8) | (offset & 0xfc) | 0x80000000;
+       if (busno != 0)
+               address |= 1;
+
+       *(volatile int32_t *) 0xfb0000f0 |= 0x2;
+
+       udelay(30);
+
+       *(volatile int32_t *) 0xfb0006f8 = address;
+       *(volatile int32_t *) 0xfb0006fc = val;
+
+       udelay(30);
+
+       *(volatile int32_t *) 0xfb0000f0 |= 0x2;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int titan_ht_config_write(struct pci_bus *bus, unsigned int devfn,
+       int offset, int size, u32 val)
+{
+       uint32_t val1, val2, mask;
+
+       titan_ht_config_read_dword(bus, devfn, offset, &val2);
+
+       val1 = val << ((offset & 3) << 3);
+       mask = ~(0xffffffffU >> ((4 - size) << 8));
+       val2 &= ~(mask << ((offset & 3) << 8));
+
+       titan_ht_config_write_dword(bus, devfn, offset, val1 | val2);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops titan_ht_pci_ops = {
+       .read   = titan_ht_config_read,
+       .write  = titan_ht_config_write,
+};
diff --git a/arch/mips/pci/ops-vr41xx.c b/arch/mips/pci/ops-vr41xx.c
new file mode 100644 (file)
index 0000000..4465460
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ *  ops-vr41xx.c, PCI configuration routines for the PCIU of NEC VR4100 series.
+ *
+ *  Copyright (C) 2001-2003 MontaVista Software Inc.
+ *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
+ *  Copyright (C) 2004  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/*
+ * Changes:
+ *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  - New creation, NEC VR4122 and VR4131 are supported.
+ */
+#include <linux/pci.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+
+#define PCICONFDREG    KSEG1ADDR(0x0f000c14)
+#define PCICONFAREG    KSEG1ADDR(0x0f000c18)
+
+static inline int set_pci_configuration_address(unsigned char number,
+                                                unsigned int devfn, int where)
+{
+       if (number == 0) {
+               /*
+                * Type 0 configuration
+                */
+               if (PCI_SLOT(devfn) < 11 || where > 0xff)
+                       return -EINVAL;
+
+               writel((1U << PCI_SLOT(devfn)) | (PCI_FUNC(devfn) << 8) |
+                      (where & 0xfc), PCICONFAREG);
+       } else {
+               /*
+                * Type 1 configuration
+                */
+               if (where > 0xff)
+                       return -EINVAL;
+
+               writel(((uint32_t)number << 16) | ((devfn & 0xff) << 8) |
+                      (where & 0xfc) | 1U, PCICONFAREG);
+       }
+
+       return 0;
+}
+
+static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where,
+                           int size, uint32_t *val)
+{
+       uint32_t data;
+
+       *val = 0xffffffffU;
+       if (set_pci_configuration_address(bus->number, devfn, where) < 0)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       data = readl(PCICONFDREG);
+
+       switch (size) {
+       case 1:
+               *val = (data >> ((where & 3) << 3)) & 0xffU;
+               break;
+       case 2:
+               *val = (data >> ((where & 2) << 3)) & 0xffffU;
+               break;
+       case 4:
+               *val = data;
+               break;
+       default:
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where,
+                            int size, uint32_t val)
+{
+       uint32_t data;
+       int shift;
+
+       if (set_pci_configuration_address(bus->number, devfn, where) < 0)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       data = readl(PCICONFDREG);
+
+       switch (size) {
+       case 1:
+               shift = (where & 3) << 3;
+               data &= ~(0xffU << shift);
+               data |= ((val & 0xffU) << shift);
+               break;
+       case 2:
+               shift = (where & 2) << 3;
+               data &= ~(0xffffU << shift);
+               data |= ((val & 0xffffU) << shift);
+               break;
+       case 4:
+               data = val;
+               break;
+       default:
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+
+       writel(data, PCICONFDREG);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops vr41xx_pci_ops = {
+       .read   = pci_config_read,
+       .write  = pci_config_write,
+};
diff --git a/arch/mips/pmc-sierra/yosemite/dbg_io.c b/arch/mips/pmc-sierra/yosemite/dbg_io.c
new file mode 100644 (file)
index 0000000..1ff8d95
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2003 PMC-Sierra
+ * Author: Manish Lachwani (lachwani@pmc-sierra.com)
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Support for KGDB for the Yosemite board. We make use of single serial
+ * port to be used for KGDB as well as console. The second serial port
+ * seems to be having a problem. Single IRQ is allocated for both the
+ * ports. Hence, the interrupt routing code needs to figure out whether
+ * the interrupt came from channel A or B.
+ */
+
+#include <linux/config.h>
+
+#if defined(CONFIG_KGDB)
+#include <asm/serial.h>
+
+/*
+ * Baud rate, Parity, Data and Stop bit settings for the
+ * serial port on the Yosemite. Note that the Early printk
+ * patch has been added. So, we should be all set to go
+ */
+#define        YOSEMITE_BAUD_2400      2400
+#define        YOSEMITE_BAUD_4800      4800
+#define        YOSEMITE_BAUD_9600      9600
+#define        YOSEMITE_BAUD_19200     19200
+#define        YOSEMITE_BAUD_38400     38400
+#define        YOSEMITE_BAUD_57600     57600
+#define        YOSEMITE_BAUD_115200    115200
+
+#define        YOSEMITE_PARITY_NONE    0
+#define        YOSEMITE_PARITY_ODD     0x08
+#define        YOSEMITE_PARITY_EVEN    0x18
+#define        YOSEMITE_PARITY_MARK    0x28
+#define        YOSEMITE_PARITY_SPACE   0x38
+
+#define        YOSEMITE_DATA_5BIT      0x0
+#define        YOSEMITE_DATA_6BIT      0x1
+#define        YOSEMITE_DATA_7BIT      0x2
+#define        YOSEMITE_DATA_8BIT      0x3
+
+#define        YOSEMITE_STOP_1BIT      0x0
+#define        YOSEMITE_STOP_2BIT      0x4
+
+/* This is crucial */
+#define        SERIAL_REG_OFS          0x1
+
+#define        SERIAL_RCV_BUFFER       0x0
+#define        SERIAL_TRANS_HOLD       0x0
+#define        SERIAL_SEND_BUFFER      0x0
+#define        SERIAL_INTR_ENABLE      (1 * SERIAL_REG_OFS)
+#define        SERIAL_INTR_ID          (2 * SERIAL_REG_OFS)
+#define        SERIAL_DATA_FORMAT      (3 * SERIAL_REG_OFS)
+#define        SERIAL_LINE_CONTROL     (3 * SERIAL_REG_OFS)
+#define        SERIAL_MODEM_CONTROL    (4 * SERIAL_REG_OFS)
+#define        SERIAL_RS232_OUTPUT     (4 * SERIAL_REG_OFS)
+#define        SERIAL_LINE_STATUS      (5 * SERIAL_REG_OFS)
+#define        SERIAL_MODEM_STATUS     (6 * SERIAL_REG_OFS)
+#define        SERIAL_RS232_INPUT      (6 * SERIAL_REG_OFS)
+#define        SERIAL_SCRATCH_PAD      (7 * SERIAL_REG_OFS)
+
+#define        SERIAL_DIVISOR_LSB      (0 * SERIAL_REG_OFS)
+#define        SERIAL_DIVISOR_MSB      (1 * SERIAL_REG_OFS)
+
+/*
+ * Functions to READ and WRITE to serial port 0
+ */
+#define        SERIAL_READ(ofs)                (*((volatile unsigned char*)    \
+                                       (TITAN_SERIAL_BASE + ofs)))
+
+#define        SERIAL_WRITE(ofs, val)          ((*((volatile unsigned char*)   \
+                                       (TITAN_SERIAL_BASE + ofs))) = val)
+
+/*
+ * Functions to READ and WRITE to serial port 1
+ */
+#define        SERIAL_READ_1(ofs)              (*((volatile unsigned char*)    \
+                                       (TITAN_SERIAL_BASE_1 + ofs)
+
+#define        SERIAL_WRITE_1(ofs, val)        ((*((volatile unsigned char*)   \
+                                       (TITAN_SERIAL_BASE_1 + ofs))) = val)
+
+/*
+ * Second serial port initialization
+ */
+void init_second_port(void)
+{
+       /* Disable Interrupts */
+       SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x0);
+       SERIAL_WRITE_1(SERIAL_INTR_ENABLE, 0x0);
+
+       {
+               unsigned int divisor;
+
+               SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x80);
+               divisor = TITAN_SERIAL_BASE_BAUD / YOSEMITE_BAUD_115200;
+               SERIAL_WRITE_1(SERIAL_DIVISOR_LSB, divisor & 0xff);
+
+               SERIAL_WRITE_1(SERIAL_DIVISOR_MSB,
+                              (divisor & 0xff00) >> 8);
+               SERIAL_WRITE_1(SERIAL_LINE_CONTROL, 0x0);
+       }
+
+       SERIAL_WRITE_1(SERIAL_DATA_FORMAT, YOSEMITE_DATA_8BIT |
+                      YOSEMITE_PARITY_NONE | YOSEMITE_STOP_1BIT);
+
+       /* Enable Interrupts */
+       SERIAL_WRITE_1(SERIAL_INTR_ENABLE, 0xf);
+}
+
+/* Initialize the serial port for KGDB debugging */
+void debugInit(unsigned int baud, unsigned char data, unsigned char parity,
+              unsigned char stop)
+{
+       /* Disable Interrupts */
+       SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x0);
+       SERIAL_WRITE(SERIAL_INTR_ENABLE, 0x0);
+
+       {
+               unsigned int divisor;
+
+               SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x80);
+
+               divisor = TITAN_SERIAL_BASE_BAUD / baud;
+               SERIAL_WRITE(SERIAL_DIVISOR_LSB, divisor & 0xff);
+
+               SERIAL_WRITE(SERIAL_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+               SERIAL_WRITE(SERIAL_LINE_CONTROL, 0x0);
+       }
+
+       SERIAL_WRITE(SERIAL_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized = 0;
+
+unsigned char getDebugChar(void)
+{
+       if (!remoteDebugInitialized) {
+               remoteDebugInitialized = 1;
+               debugInit(YOSEMITE_BAUD_115200,
+                         YOSEMITE_DATA_8BIT,
+                         YOSEMITE_PARITY_NONE, YOSEMITE_STOP_1BIT);
+       }
+
+       while ((SERIAL_READ(SERIAL_LINE_STATUS) & 0x1) == 0);
+       return SERIAL_READ(SERIAL_RCV_BUFFER);
+}
+
+int putDebugChar(unsigned char byte)
+{
+       if (!remoteDebugInitialized) {
+               remoteDebugInitialized = 1;
+               debugInit(YOSEMITE_BAUD_115200,
+                         YOSEMITE_DATA_8BIT,
+                         YOSEMITE_PARITY_NONE, YOSEMITE_STOP_1BIT);
+       }
+
+       while ((SERIAL_READ(SERIAL_LINE_STATUS) & 0x20) == 0);
+       SERIAL_WRITE(SERIAL_SEND_BUFFER, byte);
+
+       return 1;
+}
+#endif
diff --git a/arch/mips/pmc-sierra/yosemite/py-console.c b/arch/mips/pmc-sierra/yosemite/py-console.c
new file mode 100644 (file)
index 0000000..22c336f
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001, 2002, 2004 Ralf Baechle
+ */
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/termios.h>
+#include <linux/sched.h>
+#include <linux/tty.h>
+
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <asm/serial.h>
+#include <asm/io.h>
+
+/* SUPERIO uart register map */
+struct yo_uartregs {
+       union {
+               volatile u8     rbr;    /* read only, DLAB == 0 */
+               volatile u8     thr;    /* write only, DLAB == 0 */
+               volatile u8     dll;    /* DLAB == 1 */
+       } u1;
+       union {
+               volatile u8     ier;    /* DLAB == 0 */
+               volatile u8     dlm;    /* DLAB == 1 */
+       } u2;
+       union {
+               volatile u8     iir;    /* read only */
+               volatile u8     fcr;    /* write only */
+       } u3;
+       volatile u8     iu_lcr;
+       volatile u8     iu_mcr;
+       volatile u8     iu_lsr;
+       volatile u8     iu_msr;
+       volatile u8     iu_scr;
+} yo_uregs_t;
+
+#define iu_rbr u1.rbr
+#define iu_thr u1.thr
+#define iu_dll u1.dll
+#define iu_ier u2.ier
+#define iu_dlm u2.dlm
+#define iu_iir u3.iir
+#define iu_fcr u3.fcr
+
+extern unsigned long uart_base;
+
+#define IO_BASE_64     0x9000000000000000ULL
+
+static unsigned char readb_outer_space(unsigned long phys)
+{
+       unsigned long long vaddr = IO_BASE_64 | phys;
+       unsigned char res;
+       unsigned int sr;
+
+       sr = read_c0_status();
+       write_c0_status((sr | ST0_KX) & ~ ST0_IE);
+       __asm__("sll    $0, $0, 2\n");
+       __asm__("sll    $0, $0, 2\n");
+       __asm__("sll    $0, $0, 2\n");
+       __asm__("sll    $0, $0, 2\n");
+
+       __asm__ __volatile__ (
+       "       .set    mips3           \n"
+       "       ld      %0, (%0)        \n"
+       "       lbu     %0, (%0)        \n"
+       "       .set    mips0           \n"
+       : "=r" (res)
+       : "0" (&vaddr));
+
+       write_c0_status(sr);
+       __asm__("sll    $0, $0, 2\n");
+       __asm__("sll    $0, $0, 2\n");
+       __asm__("sll    $0, $0, 2\n");
+       __asm__("sll    $0, $0, 2\n");
+
+       return res;
+}
+
+static void writeb_outer_space(unsigned long phys, unsigned char c)
+{
+       unsigned long long vaddr = IO_BASE_64 | phys;
+       unsigned long tmp;
+       unsigned int sr;
+
+       sr = read_c0_status();
+       write_c0_status((sr | ST0_KX) & ~ ST0_IE);
+       __asm__("sll    $0, $0, 2\n");
+       __asm__("sll    $0, $0, 2\n");
+       __asm__("sll    $0, $0, 2\n");
+       __asm__("sll    $0, $0, 2\n");
+
+       __asm__ __volatile__ (
+       "       .set    mips3           \n"
+       "       ld      %0, (%1)        \n"
+       "       sb      %2, (%0)        \n"
+       "       .set    mips0           \n"
+       : "=r" (tmp)
+       : "r" (&vaddr), "r" (c));
+
+       write_c0_status(sr);
+       __asm__("sll    $0, $0, 2\n");
+       __asm__("sll    $0, $0, 2\n");
+       __asm__("sll    $0, $0, 2\n");
+       __asm__("sll    $0, $0, 2\n");
+}
+
+static inline struct yo_uartregs *console_uart(void)
+{
+       return (struct yo_uartregs *) (uart_base + 8);
+}
+
+void prom_putchar(char c)
+{
+       unsigned long lsr = 0xfd000008UL + offsetof(struct yo_uartregs, iu_lsr);
+       unsigned long thr = 0xfd000008UL + offsetof(struct yo_uartregs, iu_thr);
+
+       while ((readb_outer_space(lsr) & 0x20) == 0);
+       writeb_outer_space(thr, c);
+}
+
+char __init prom_getchar(void)
+{
+       return 0;
+}
diff --git a/arch/ppc/configs/ads8272_defconfig b/arch/ppc/configs/ads8272_defconfig
new file mode 100644 (file)
index 0000000..709a180
--- /dev/null
@@ -0,0 +1,583 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_EMBEDDEDBOOT=y
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_WILLOW is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_EV64260 is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX6 is not set
+# CONFIG_TQM8260 is not set
+CONFIG_ADS8272=y
+CONFIG_PQ2ADS=y
+CONFIG_8260=y
+CONFIG_8272=y
+CONFIG_CPM2=y
+# CONFIG_PC_KEYBOARD is not set
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_OAKNET is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_NEC98_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+# CONFIG_SCC_ENET is not set
+CONFIG_FEC_ENET=y
+# CONFIG_USE_MDIO is not set
+
+#
+# CPM2 Options
+#
+CONFIG_SCC_CONSOLE=y
+CONFIG_FCC1_ENET=y
+# CONFIG_FCC2_ENET is not set
+# CONFIG_FCC3_ENET is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_KGDB_CONSOLE is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/lib/rheap.c b/arch/ppc/lib/rheap.c
new file mode 100644 (file)
index 0000000..4d938a0
--- /dev/null
@@ -0,0 +1,692 @@
+/*
+ * arch/ppc/syslib/rheap.c
+ *
+ * A Remote Heap.  Remote means that we don't touch the memory that the
+ * heap points to. Normal heap implementations use the memory they manage
+ * to place their list. We cannot do that because the memory we manage may
+ * have special properties, for example it is uncachable or of different
+ * endianess.
+ *
+ * Author: Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2004 (c) INTRACOM S.A. Greece. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <asm/rheap.h>
+
+/*
+ * Fixup a list_head, needed when copying lists.  If the pointers fall
+ * between s and e, apply the delta.  This assumes that
+ * sizeof(struct list_head *) == sizeof(unsigned long *).
+ */
+static inline void fixup(unsigned long s, unsigned long e, int d,
+                        struct list_head *l)
+{
+       unsigned long *pp;
+
+       pp = (unsigned long *)&l->next;
+       if (*pp >= s && *pp < e)
+               *pp += d;
+
+       pp = (unsigned long *)&l->prev;
+       if (*pp >= s && *pp < e)
+               *pp += d;
+}
+
+/* Grow the allocated blocks */
+static int grow(rh_info_t * info, int max_blocks)
+{
+       rh_block_t *block, *blk;
+       int i, new_blocks;
+       int delta;
+       unsigned long blks, blke;
+
+       if (max_blocks <= info->max_blocks)
+               return -EINVAL;
+
+       new_blocks = max_blocks - info->max_blocks;
+
+       block = kmalloc(sizeof(rh_block_t) * max_blocks, GFP_KERNEL);
+       if (block == NULL)
+               return -ENOMEM;
+
+       if (info->max_blocks > 0) {
+
+               /* copy old block area */
+               memcpy(block, info->block,
+                      sizeof(rh_block_t) * info->max_blocks);
+
+               delta = (char *)block - (char *)info->block;
+
+               /* and fixup list pointers */
+               blks = (unsigned long)info->block;
+               blke = (unsigned long)(info->block + info->max_blocks);
+
+               for (i = 0, blk = block; i < info->max_blocks; i++, blk++)
+                       fixup(blks, blke, delta, &blk->list);
+
+               fixup(blks, blke, delta, &info->empty_list);
+               fixup(blks, blke, delta, &info->free_list);
+               fixup(blks, blke, delta, &info->taken_list);
+
+               /* free the old allocated memory */
+               if ((info->flags & RHIF_STATIC_BLOCK) == 0)
+                       kfree(info->block);
+       }
+
+       info->block = block;
+       info->empty_slots += new_blocks;
+       info->max_blocks = max_blocks;
+       info->flags &= ~RHIF_STATIC_BLOCK;
+
+       /* add all new blocks to the free list */
+       for (i = 0, blk = block + info->max_blocks; i < new_blocks; i++, blk++)
+               list_add(&blk->list, &info->empty_list);
+
+       return 0;
+}
+
+/*
+ * Assure at least the required amount of empty slots.  If this function
+ * causes a grow in the block area then all pointers kept to the block
+ * area are invalid!
+ */
+static int assure_empty(rh_info_t * info, int slots)
+{
+       int max_blocks;
+
+       /* This function is not meant to be used to grow uncontrollably */
+       if (slots >= 4)
+               return -EINVAL;
+
+       /* Enough space */
+       if (info->empty_slots >= slots)
+               return 0;
+
+       /* Next 16 sized block */
+       max_blocks = ((info->max_blocks + slots) + 15) & ~15;
+
+       return grow(info, max_blocks);
+}
+
+static rh_block_t *get_slot(rh_info_t * info)
+{
+       rh_block_t *blk;
+
+       /* If no more free slots, and failure to extend. */
+       /* XXX: You should have called assure_empty before */
+       if (info->empty_slots == 0) {
+               printk(KERN_ERR "rh: out of slots; crash is imminent.\n");
+               return NULL;
+       }
+
+       /* Get empty slot to use */
+       blk = list_entry(info->empty_list.next, rh_block_t, list);
+       list_del_init(&blk->list);
+       info->empty_slots--;
+
+       /* Initialize */
+       blk->start = NULL;
+       blk->size = 0;
+       blk->owner = NULL;
+
+       return blk;
+}
+
+static inline void release_slot(rh_info_t * info, rh_block_t * blk)
+{
+       list_add(&blk->list, &info->empty_list);
+       info->empty_slots++;
+}
+
+static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
+{
+       rh_block_t *blk;
+       rh_block_t *before;
+       rh_block_t *after;
+       rh_block_t *next;
+       int size;
+       unsigned long s, e, bs, be;
+       struct list_head *l;
+
+       /* We assume that they are aligned properly */
+       size = blkn->size;
+       s = (unsigned long)blkn->start;
+       e = s + size;
+
+       /* Find the blocks immediately before and after the given one
+        * (if any) */
+       before = NULL;
+       after = NULL;
+       next = NULL;
+
+       list_for_each(l, &info->free_list) {
+               blk = list_entry(l, rh_block_t, list);
+
+               bs = (unsigned long)blk->start;
+               be = bs + blk->size;
+
+               if (next == NULL && s >= bs)
+                       next = blk;
+
+               if (be == s)
+                       before = blk;
+
+               if (e == bs)
+                       after = blk;
+
+               /* If both are not null, break now */
+               if (before != NULL && after != NULL)
+                       break;
+       }
+
+       /* Now check if they are really adjacent */
+       if (before != NULL && s != (unsigned long)before->start + before->size)
+               before = NULL;
+
+       if (after != NULL && e != (unsigned long)after->start)
+               after = NULL;
+
+       /* No coalescing; list insert and return */
+       if (before == NULL && after == NULL) {
+
+               if (next != NULL)
+                       list_add(&blkn->list, &next->list);
+               else
+                       list_add(&blkn->list, &info->free_list);
+
+               return;
+       }
+
+       /* We don't need it anymore */
+       release_slot(info, blkn);
+
+       /* Grow the before block */
+       if (before != NULL && after == NULL) {
+               before->size += size;
+               return;
+       }
+
+       /* Grow the after block backwards */
+       if (before == NULL && after != NULL) {
+               (int8_t *) after->start -= size;
+               after->size += size;
+               return;
+       }
+
+       /* Grow the before block, and release the after block */
+       before->size += size + after->size;
+       list_del(&after->list);
+       release_slot(info, after);
+}
+
+static void attach_taken_block(rh_info_t * info, rh_block_t * blkn)
+{
+       rh_block_t *blk;
+       struct list_head *l;
+
+       /* Find the block immediately before the given one (if any) */
+       list_for_each(l, &info->taken_list) {
+               blk = list_entry(l, rh_block_t, list);
+               if (blk->start > blkn->start) {
+                       list_add_tail(&blkn->list, &blk->list);
+                       return;
+               }
+       }
+
+       list_add_tail(&blkn->list, &info->taken_list);
+}
+
+/*
+ * Create a remote heap dynamically.  Note that no memory for the blocks
+ * are allocated.  It will upon the first allocation
+ */
+rh_info_t *rh_create(unsigned int alignment)
+{
+       rh_info_t *info;
+
+       /* Alignment must be a power of two */
+       if ((alignment & (alignment - 1)) != 0)
+               return NULL;
+
+       info = kmalloc(sizeof(*info), GFP_KERNEL);
+       if (info == NULL)
+               return NULL;
+
+       info->alignment = alignment;
+
+       /* Initially everything as empty */
+       info->block = NULL;
+       info->max_blocks = 0;
+       info->empty_slots = 0;
+       info->flags = 0;
+
+       INIT_LIST_HEAD(&info->empty_list);
+       INIT_LIST_HEAD(&info->free_list);
+       INIT_LIST_HEAD(&info->taken_list);
+
+       return info;
+}
+
+/*
+ * Destroy a dynamically created remote heap.  Deallocate only if the areas
+ * are not static
+ */
+void rh_destroy(rh_info_t * info)
+{
+       if ((info->flags & RHIF_STATIC_BLOCK) == 0 && info->block != NULL)
+               kfree(info->block);
+
+       if ((info->flags & RHIF_STATIC_INFO) == 0)
+               kfree(info);
+}
+
+/*
+ * Initialize in place a remote heap info block.  This is needed to support
+ * operation very early in the startup of the kernel, when it is not yet safe
+ * to call kmalloc.
+ */
+void rh_init(rh_info_t * info, unsigned int alignment, int max_blocks,
+            rh_block_t * block)
+{
+       int i;
+       rh_block_t *blk;
+
+       /* Alignment must be a power of two */
+       if ((alignment & (alignment - 1)) != 0)
+               return;
+
+       info->alignment = alignment;
+
+       /* Initially everything as empty */
+       info->block = block;
+       info->max_blocks = max_blocks;
+       info->empty_slots = max_blocks;
+       info->flags = RHIF_STATIC_INFO | RHIF_STATIC_BLOCK;
+
+       INIT_LIST_HEAD(&info->empty_list);
+       INIT_LIST_HEAD(&info->free_list);
+       INIT_LIST_HEAD(&info->taken_list);
+
+       /* Add all new blocks to the free list */
+       for (i = 0, blk = block; i < max_blocks; i++, blk++)
+               list_add(&blk->list, &info->empty_list);
+}
+
+/* Attach a free memory region, coalesces regions if adjuscent */
+int rh_attach_region(rh_info_t * info, void *start, int size)
+{
+       rh_block_t *blk;
+       unsigned long s, e, m;
+       int r;
+
+       /* The region must be aligned */
+       s = (unsigned long)start;
+       e = s + size;
+       m = info->alignment - 1;
+
+       /* Round start up */
+       s = (s + m) & ~m;
+
+       /* Round end down */
+       e = e & ~m;
+
+       /* Take final values */
+       start = (void *)s;
+       size = (int)(e - s);
+
+       /* Grow the blocks, if needed */
+       r = assure_empty(info, 1);
+       if (r < 0)
+               return r;
+
+       blk = get_slot(info);
+       blk->start = start;
+       blk->size = size;
+       blk->owner = NULL;
+
+       attach_free_block(info, blk);
+
+       return 0;
+}
+
+/* Detatch given address range, splits free block if needed. */
+void *rh_detach_region(rh_info_t * info, void *start, int size)
+{
+       struct list_head *l;
+       rh_block_t *blk, *newblk;
+       unsigned long s, e, m, bs, be;
+
+       /* Validate size */
+       if (size <= 0)
+               return NULL;
+
+       /* The region must be aligned */
+       s = (unsigned long)start;
+       e = s + size;
+       m = info->alignment - 1;
+
+       /* Round start up */
+       s = (s + m) & ~m;
+
+       /* Round end down */
+       e = e & ~m;
+
+       if (assure_empty(info, 1) < 0)
+               return NULL;
+
+       blk = NULL;
+       list_for_each(l, &info->free_list) {
+               blk = list_entry(l, rh_block_t, list);
+               /* The range must lie entirely inside one free block */
+               bs = (unsigned long)blk->start;
+               be = (unsigned long)blk->start + blk->size;
+               if (s >= bs && e <= be)
+                       break;
+               blk = NULL;
+       }
+
+       if (blk == NULL)
+               return NULL;
+
+       /* Perfect fit */
+       if (bs == s && be == e) {
+               /* Delete from free list, release slot */
+               list_del(&blk->list);
+               release_slot(info, blk);
+               return (void *)s;
+       }
+
+       /* blk still in free list, with updated start and/or size */
+       if (bs == s || be == e) {
+               if (bs == s)
+                       (int8_t *) blk->start += size;
+               blk->size -= size;
+
+       } else {
+               /* The front free fragment */
+               blk->size = s - bs;
+
+               /* the back free fragment */
+               newblk = get_slot(info);
+               newblk->start = (void *)e;
+               newblk->size = be - e;
+
+               list_add(&newblk->list, &blk->list);
+       }
+
+       return (void *)s;
+}
+
+void *rh_alloc(rh_info_t * info, int size, const char *owner)
+{
+       struct list_head *l;
+       rh_block_t *blk;
+       rh_block_t *newblk;
+       void *start;
+
+       /* Validate size */
+       if (size <= 0)
+               return NULL;
+
+       /* Align to configured alignment */
+       size = (size + (info->alignment - 1)) & ~(info->alignment - 1);
+
+       if (assure_empty(info, 1) < 0)
+               return NULL;
+
+       blk = NULL;
+       list_for_each(l, &info->free_list) {
+               blk = list_entry(l, rh_block_t, list);
+               if (size <= blk->size)
+                       break;
+               blk = NULL;
+       }
+
+       if (blk == NULL)
+               return NULL;
+
+       /* Just fits */
+       if (blk->size == size) {
+               /* Move from free list to taken list */
+               list_del(&blk->list);
+               blk->owner = owner;
+               start = blk->start;
+
+               attach_taken_block(info, blk);
+
+               return start;
+       }
+
+       newblk = get_slot(info);
+       newblk->start = blk->start;
+       newblk->size = size;
+       newblk->owner = owner;
+
+       /* blk still in free list, with updated start, size */
+       (int8_t *) blk->start += size;
+       blk->size -= size;
+
+       start = newblk->start;
+
+       attach_taken_block(info, newblk);
+
+       return start;
+}
+
+/* allocate at precisely the given address */
+void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
+{
+       struct list_head *l;
+       rh_block_t *blk, *newblk1, *newblk2;
+       unsigned long s, e, m, bs, be;
+
+       /* Validate size */
+       if (size <= 0)
+               return NULL;
+
+       /* The region must be aligned */
+       s = (unsigned long)start;
+       e = s + size;
+       m = info->alignment - 1;
+
+       /* Round start up */
+       s = (s + m) & ~m;
+
+       /* Round end down */
+       e = e & ~m;
+
+       if (assure_empty(info, 2) < 0)
+               return NULL;
+
+       blk = NULL;
+       list_for_each(l, &info->free_list) {
+               blk = list_entry(l, rh_block_t, list);
+               /* The range must lie entirely inside one free block */
+               bs = (unsigned long)blk->start;
+               be = (unsigned long)blk->start + blk->size;
+               if (s >= bs && e <= be)
+                       break;
+       }
+
+       if (blk == NULL)
+               return NULL;
+
+       /* Perfect fit */
+       if (bs == s && be == e) {
+               /* Move from free list to taken list */
+               list_del(&blk->list);
+               blk->owner = owner;
+
+               start = blk->start;
+               attach_taken_block(info, blk);
+
+               return start;
+
+       }
+
+       /* blk still in free list, with updated start and/or size */
+       if (bs == s || be == e) {
+               if (bs == s)
+                       (int8_t *) blk->start += size;
+               blk->size -= size;
+
+       } else {
+               /* The front free fragment */
+               blk->size = s - bs;
+
+               /* The back free fragment */
+               newblk2 = get_slot(info);
+               newblk2->start = (void *)e;
+               newblk2->size = be - e;
+
+               list_add(&newblk2->list, &blk->list);
+       }
+
+       newblk1 = get_slot(info);
+       newblk1->start = (void *)s;
+       newblk1->size = e - s;
+       newblk1->owner = owner;
+
+       start = newblk1->start;
+       attach_taken_block(info, newblk1);
+
+       return start;
+}
+
+int rh_free(rh_info_t * info, void *start)
+{
+       rh_block_t *blk, *blk2;
+       struct list_head *l;
+       int size;
+
+       /* Linear search for block */
+       blk = NULL;
+       list_for_each(l, &info->taken_list) {
+               blk2 = list_entry(l, rh_block_t, list);
+               if (start < blk2->start)
+                       break;
+               blk = blk2;
+       }
+
+       if (blk == NULL || start > (blk->start + blk->size))
+               return -EINVAL;
+
+       /* Remove from taken list */
+       list_del(&blk->list);
+
+       /* Get size of freed block */
+       size = blk->size;
+       attach_free_block(info, blk);
+
+       return size;
+}
+
+int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats)
+{
+       rh_block_t *blk;
+       struct list_head *l;
+       struct list_head *h;
+       int nr;
+
+       switch (what) {
+
+       case RHGS_FREE:
+               h = &info->free_list;
+               break;
+
+       case RHGS_TAKEN:
+               h = &info->taken_list;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       /* Linear search for block */
+       nr = 0;
+       list_for_each(l, h) {
+               blk = list_entry(l, rh_block_t, list);
+               if (stats != NULL && nr < max_stats) {
+                       stats->start = blk->start;
+                       stats->size = blk->size;
+                       stats->owner = blk->owner;
+                       stats++;
+               }
+               nr++;
+       }
+
+       return nr;
+}
+
+int rh_set_owner(rh_info_t * info, void *start, const char *owner)
+{
+       rh_block_t *blk, *blk2;
+       struct list_head *l;
+       int size;
+
+       /* Linear search for block */
+       blk = NULL;
+       list_for_each(l, &info->taken_list) {
+               blk2 = list_entry(l, rh_block_t, list);
+               if (start < blk2->start)
+                       break;
+               blk = blk2;
+       }
+
+       if (blk == NULL || start > (blk->start + blk->size))
+               return -EINVAL;
+
+       blk->owner = owner;
+
+       return size;
+}
+
+void rh_dump(rh_info_t * info)
+{
+       static rh_stats_t st[32];       /* XXX maximum 32 blocks */
+       int maxnr;
+       int i, nr;
+
+       maxnr = sizeof(st) / sizeof(st[0]);
+
+       printk(KERN_INFO
+              "info @0x%p (%d slots empty / %d max)\n",
+              info, info->empty_slots, info->max_blocks);
+
+       printk(KERN_INFO "  Free:\n");
+       nr = rh_get_stats(info, RHGS_FREE, maxnr, st);
+       if (nr > maxnr)
+               nr = maxnr;
+       for (i = 0; i < nr; i++)
+               printk(KERN_INFO
+                      "    0x%p-0x%p (%u)\n",
+                      st[i].start, (int8_t *) st[i].start + st[i].size,
+                      st[i].size);
+       printk(KERN_INFO "\n");
+
+       printk(KERN_INFO "  Taken:\n");
+       nr = rh_get_stats(info, RHGS_TAKEN, maxnr, st);
+       if (nr > maxnr)
+               nr = maxnr;
+       for (i = 0; i < nr; i++)
+               printk(KERN_INFO
+                      "    0x%p-0x%p (%u) %s\n",
+                      st[i].start, (int8_t *) st[i].start + st[i].size,
+                      st[i].size, st[i].owner != NULL ? st[i].owner : "");
+       printk(KERN_INFO "\n");
+}
+
+void rh_dump_blk(rh_info_t * info, rh_block_t * blk)
+{
+       printk(KERN_INFO
+              "blk @0x%p: 0x%p-0x%p (%u)\n",
+              blk, blk->start, (int8_t *) blk->start + blk->size, blk->size);
+}
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c
new file mode 100644 (file)
index 0000000..c32d662
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * arch/ppc/platforms/85xx/sbc8560.c
+ * 
+ * Wind River SBC8560 board specific routines
+ * 
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2004 Freescale Semiconductor Inc.
+ * 
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h> /* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/kgdb.h>
+#include <asm/ocp.h>
+#include <mm/mmu_decl.h>
+
+#include <syslib/ppc85xx_common.h>
+#include <syslib/ppc85xx_setup.h>
+
+struct ocp_gfar_data mpc85xx_tsec1_def = {
+       .interruptTransmit = MPC85xx_IRQ_TSEC1_TX,
+       .interruptError = MPC85xx_IRQ_TSEC1_ERROR,
+       .interruptReceive = MPC85xx_IRQ_TSEC1_RX,
+       .interruptPHY = MPC85xx_IRQ_EXT6,
+       .flags = (GFAR_HAS_GIGABIT | GFAR_HAS_MULTI_INTR | GFAR_HAS_PHY_INTR),
+       .phyid = 25,
+       .phyregidx = 0,
+};
+
+struct ocp_gfar_data mpc85xx_tsec2_def = {
+       .interruptTransmit = MPC85xx_IRQ_TSEC2_TX,
+       .interruptError = MPC85xx_IRQ_TSEC2_ERROR,
+       .interruptReceive = MPC85xx_IRQ_TSEC2_RX,
+       .interruptPHY = MPC85xx_IRQ_EXT7,
+       .flags = (GFAR_HAS_GIGABIT | GFAR_HAS_MULTI_INTR | GFAR_HAS_PHY_INTR),
+       .phyid = 26,
+       .phyregidx = 0,
+};
+
+struct ocp_fs_i2c_data mpc85xx_i2c1_def = {
+       .flags = FS_I2C_SEPARATE_DFSRR,
+};
+
+
+#ifdef CONFIG_SERIAL_8250
+static void __init
+sbc8560_early_serial_map(void)
+{
+        struct uart_port uart_req;
+        /* Setup serial port access */
+        memset(&uart_req, 0, sizeof (uart_req));
+       uart_req.irq = MPC85xx_IRQ_EXT9;
+       uart_req.flags = STD_COM_FLAGS;
+       uart_req.uartclk = BASE_BAUD * 16;
+        uart_req.iotype = SERIAL_IO_MEM;
+        uart_req.mapbase = UARTA_ADDR;
+        uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART0_SIZE);
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+        gen550_init(0, &uart_req);
+#endif
+        if (early_serial_setup(&uart_req) != 0)
+                printk("Early serial init of port 0 failed\n");
+        /* Assume early_serial_setup() doesn't modify uart_req */
+       uart_req.line = 1;
+        uart_req.mapbase = UARTB_ADDR;
+        uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART1_SIZE);
+       uart_req.irq = MPC85xx_IRQ_EXT10;
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+        gen550_init(1, &uart_req);
+#endif
+        if (early_serial_setup(&uart_req) != 0)
+                printk("Early serial init of port 1 failed\n");
+}
+#endif
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init
+sbc8560_setup_arch(void)
+{
+       struct ocp_def *def;
+       struct ocp_gfar_data *einfo;
+       bd_t *binfo = (bd_t *) __res;
+       unsigned int freq;
+
+       /* get the core frequency */
+       freq = binfo->bi_intfreq;
+
+       if (ppc_md.progress)
+               ppc_md.progress("sbc8560_setup_arch()", 0);
+
+       /* Set loops_per_jiffy to a half-way reasonable value,
+          for use until calibrate_delay gets called. */
+       loops_per_jiffy = freq / HZ;
+
+#ifdef CONFIG_PCI
+       /* setup PCI host bridges */
+       mpc85xx_setup_hose();
+#endif
+#ifdef CONFIG_DUMMY_CONSOLE
+       conswitchp = &dummy_con;
+#endif
+#ifdef CONFIG_SERIAL_8250
+       sbc8560_early_serial_map();
+#endif
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+       /* Invalidate the entry we stole earlier the serial ports
+        * should be properly mapped */ 
+       invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+#endif
+
+       /* Set up MAC addresses for the Ethernet devices */
+       def = ocp_get_one_device(OCP_VENDOR_FREESCALE, OCP_FUNC_GFAR, 0);
+       if (def) {
+               einfo = (struct ocp_gfar_data *) def->additions;
+               memcpy(einfo->mac_addr, binfo->bi_enetaddr, 6);
+       }
+
+       def = ocp_get_one_device(OCP_VENDOR_FREESCALE, OCP_FUNC_GFAR, 1);
+       if (def) {
+               einfo = (struct ocp_gfar_data *) def->additions;
+               memcpy(einfo->mac_addr, binfo->bi_enet1addr, 6);
+       }
+
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (initrd_start)
+               ROOT_DEV = Root_RAM0;
+       else
+#endif
+#ifdef  CONFIG_ROOT_NFS
+               ROOT_DEV = Root_NFS;
+#else
+               ROOT_DEV = Root_HDA1;
+#endif
+
+       ocp_for_each_device(mpc85xx_update_paddr_ocp, &(binfo->bi_immr_base));
+}
+
+/* ************************************************************************ */
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+             unsigned long r6, unsigned long r7)
+{
+       /* parse_bootinfo must always be called first */
+       parse_bootinfo(find_bootinfo());
+
+       /*
+        * If we were passed in a board information, copy it into the
+        * residual data area.
+        */
+       if (r3) {
+               memcpy((void *) __res, (void *) (r3 + KERNELBASE),
+                      sizeof (bd_t));
+       }
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+       /* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
+       settlbcam(NUM_TLBCAMS - 1, UARTA_ADDR,
+                 UARTA_ADDR, 0x1000, _PAGE_IO, 0);
+#endif
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+       /*
+        * If the init RAM disk has been configured in, and there's a valid
+        * starting address for it, set it up.
+        */
+       if (r4) {
+               initrd_start = r4 + KERNELBASE;
+               initrd_end = r5 + KERNELBASE;
+       }
+#endif                         /* CONFIG_BLK_DEV_INITRD */
+
+       /* Copy the kernel command line arguments to a safe place. */
+
+       if (r6) {
+               *(char *) (r7 + KERNELBASE) = 0;
+               strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+       }
+
+       /* setup the PowerPC module struct */
+       ppc_md.setup_arch = sbc8560_setup_arch;
+       ppc_md.show_cpuinfo = sbc8560_show_cpuinfo;
+
+       ppc_md.init_IRQ = sbc8560_init_IRQ;
+       ppc_md.get_irq = openpic_get_irq;
+
+       ppc_md.restart = mpc85xx_restart;
+       ppc_md.power_off = mpc85xx_power_off;
+       ppc_md.halt = mpc85xx_halt;
+
+       ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
+
+       ppc_md.time_init = NULL;
+       ppc_md.set_rtc_time = NULL;
+       ppc_md.get_rtc_time = NULL;
+       ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
+
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+       ppc_md.progress = gen550_progress;
+#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+
+       if (ppc_md.progress)
+               ppc_md.progress("sbc8560_init(): exit", 0);
+}
diff --git a/arch/ppc/platforms/85xx/sbc8560.h b/arch/ppc/platforms/85xx/sbc8560.h
new file mode 100644 (file)
index 0000000..5c86187
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * arch/ppc/platforms/85xx/sbc8560.h
+ *
+ * Wind River SBC8560 board definitions
+ *
+ * Copyright 2003 Motorola Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+#ifndef __MACH_SBC8560_H__
+#define __MACH_SBC8560_H__
+#include <linux/config.h>
+#include <linux/serial.h>
+#include <platforms/85xx/sbc85xx.h>
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE  64
+#else
+#define RS_TABLE_SIZE  2
+#endif
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD ( 1843200 / 16 )
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#endif
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, UARTA_ADDR, MPC85xx_IRQ_EXT9, STD_COM_FLAGS, /* ttyS0 */ \
+                iomem_base: (u8 *)UARTA_ADDR,                       \
+                io_type: SERIAL_IO_MEM },                                 \
+        { 0, BASE_BAUD, UARTB_ADDR, MPC85xx_IRQ_EXT10, STD_COM_FLAGS, /* ttyS1 */ \
+                iomem_base: (u8 *)UARTB_ADDR,                       \
+                io_type: SERIAL_IO_MEM },
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
+#endif /* __MACH_SBC8560_H__ */
diff --git a/arch/ppc/platforms/85xx/sbc85xx.c b/arch/ppc/platforms/85xx/sbc85xx.c
new file mode 100644 (file)
index 0000000..a7a33fd
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * arch/ppc/platform/85xx/sbc85xx.c
+ * 
+ * WindRiver PowerQUICC III SBC85xx board common routines
+ *
+ * Copyright 2002, 2003 Motorola Inc.
+ * Copyright 2004 Red Hat, Inc.
+ * 
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/serial.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/ocp.h>
+
+#include <mm/mmu_decl.h>
+
+#include <platforms/85xx/sbc85xx.h>
+
+unsigned char __res[sizeof (bd_t)];
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+unsigned long pci_dram_offset = 0;
+#endif
+
+extern unsigned long total_memory;     /* in mm/init */
+
+/* Internal interrupts are all Level Sensitive, and Positive Polarity */
+
+static u_char sbc8560_openpic_initsenses[] __initdata = {
+       (IRQ_POLARITY_POSITIVE),        /* Internal  0: L2 Cache */
+       (IRQ_POLARITY_POSITIVE),        /* Internal  1: ECM */
+       (IRQ_POLARITY_POSITIVE),        /* Internal  2: DDR DRAM */
+       (IRQ_POLARITY_POSITIVE),        /* Internal  3: LBIU */
+       (IRQ_POLARITY_POSITIVE),        /* Internal  4: DMA 0 */
+       (IRQ_POLARITY_POSITIVE),        /* Internal  5: DMA 1 */
+       (IRQ_POLARITY_POSITIVE),        /* Internal  6: DMA 2 */
+       (IRQ_POLARITY_POSITIVE),        /* Internal  7: DMA 3 */
+       (IRQ_POLARITY_POSITIVE),        /* Internal  8: PCI/PCI-X */
+       (IRQ_POLARITY_POSITIVE),        /* Internal  9: RIO Inbound Port Write Error */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 10: RIO Doorbell Inbound */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 11: RIO Outbound Message */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 12: RIO Inbound Message */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 13: TSEC 0 Transmit */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 14: TSEC 0 Receive */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 15: Unused */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 16: Unused */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 17: Unused */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 18: TSEC 0 Receive/Transmit Error */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 19: TSEC 1 Transmit */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 20: TSEC 1 Receive */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 21: Unused */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 22: Unused */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 23: Unused */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 24: TSEC 1 Receive/Transmit Error */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 25: Fast Ethernet */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 26: DUART */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 27: I2C */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 28: Performance Monitor */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 29: Unused */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 30: CPM */
+       (IRQ_POLARITY_POSITIVE),        /* Internal 31: Unused */
+       0x0,                            /* External  0: */
+       0x0,                            /* External  1: */
+#if defined(CONFIG_PCI)
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 2: PCI slot 0 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 3: PCI slot 1 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 4: PCI slot 2 */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 5: PCI slot 3 */
+#else
+       0x0,                            /* External  2: */
+       0x0,                            /* External  3: */
+       0x0,                            /* External  4: */
+       0x0,                            /* External  5: */
+#endif
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 6: PHY */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 7: PHY */
+       0x0,                            /* External  8: */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* External 9: PHY */
+       (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),      /* External 10: PHY */
+       0x0,                            /* External 11: */
+};
+
+/* ************************************************************************ */
+int
+sbc8560_show_cpuinfo(struct seq_file *m)
+{
+       uint pvid, svid, phid1;
+       uint memsize = total_memory;
+       bd_t *binfo = (bd_t *) __res;
+       unsigned int freq;
+
+       /* get the core frequency */
+       freq = binfo->bi_intfreq;
+
+       pvid = mfspr(PVR);
+       svid = mfspr(SVR);
+
+       seq_printf(m, "Vendor\t\t: Wind River\n");
+
+       switch (svid & 0xffff0000) {
+       case SVR_8540:
+               seq_printf(m, "Machine\t\t: hhmmm, this board isn't made yet!\n");
+               break;
+       case SVR_8560:
+               seq_printf(m, "Machine\t\t: SBC8560\n");
+               break;
+       default:
+               seq_printf(m, "Machine\t\t: unknown\n");
+               break;
+       }
+       seq_printf(m, "bus freq\t: %u.%.6u MHz\n", freq / 1000000,
+                  freq % 1000000);
+       seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+       seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+       /* Display cpu Pll setting */
+       phid1 = mfspr(HID1);
+       seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+       /* Display the amount of memory */
+       seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+
+       return 0;
+}
+
+void __init
+sbc8560_init_IRQ(void)
+{
+       bd_t *binfo = (bd_t *) __res;
+       /* Determine the Physical Address of the OpenPIC regs */
+       phys_addr_t OpenPIC_PAddr =
+           binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
+       OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE);
+       OpenPIC_InitSenses = sbc8560_openpic_initsenses;
+       OpenPIC_NumInitSenses = sizeof (sbc8560_openpic_initsenses);
+
+       /* Skip reserved space and internal sources */
+       openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
+       /* Map PIC IRQs 0-11 */
+       openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+
+       /* we let openpic interrupts starting from an offset, to 
+        * leave space for cascading interrupts underneath.
+        */
+       openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
+
+       return;
+}
+
+/*
+ * interrupt routing
+ */
+
+#ifdef CONFIG_PCI
+int mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel,
+                   unsigned char pin)
+{
+       static char pci_irq_table[][4] =
+           /*
+            *      PCI IDSEL/INTPIN->INTLINE
+            *        A      B      C      D
+            */
+       {
+               {PIRQA, PIRQB, PIRQC, PIRQD},
+               {PIRQD, PIRQA, PIRQB, PIRQC},
+               {PIRQC, PIRQD, PIRQA, PIRQB},
+               {PIRQB, PIRQC, PIRQD, PIRQA},
+       };
+
+       const long min_idsel = 12, max_idsel = 15, irqs_per_slot = 4;
+       return PCI_IRQ_TABLE_LOOKUP;
+}
+
+int mpc85xx_exclude_device(u_char bus, u_char devfn)
+{
+       if (bus == 0 && PCI_SLOT(devfn) == 0)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       else
+               return PCIBIOS_SUCCESSFUL;
+}
+#endif /* CONFIG_PCI */
diff --git a/arch/ppc/syslib/cpm2_common.c b/arch/ppc/syslib/cpm2_common.c
new file mode 100644 (file)
index 0000000..5ca6d4c
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * General Purpose functions for the global management of the
+ * 8260 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
+ *     2.3.99 Updates
+ *
+ * In addition to the individual control of the communication
+ * channels, there are a few functions that globally affect the
+ * communication processor.
+ *
+ * Buffer descriptors must be allocated from the dual ported memory
+ * space.  The allocator for that is here.  When the communication
+ * process is reset, we reclaim the memory available.  There is
+ * currently no deallocator for this memory.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <asm/irq.h>
+#include <asm/mpc8260.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/immap_cpm2.h>
+#include <asm/cpm2.h>
+#include <asm/rheap.h>
+
+static void cpm2_dpinit(void);
+cpm_cpm2_t     *cpmp;          /* Pointer to comm processor space */
+
+/* We allocate this here because it is used almost exclusively for
+ * the communication processor devices.
+ */
+cpm2_map_t *cpm2_immr;
+
+void
+cpm2_reset(void)
+{
+       cpm2_immr = (cpm2_map_t *)CPM_MAP_ADDR;
+
+       /* Reclaim the DP memory for our use.
+        */
+       cpm2_dpinit();
+
+       /* Tell everyone where the comm processor resides.
+        */
+       cpmp = &cpm2_immr->im_cpm;
+}
+
+/* Set a baud rate generator.  This needs lots of work.  There are
+ * eight BRGs, which can be connected to the CPM channels or output
+ * as clocks.  The BRGs are in two different block of internal
+ * memory mapped space.
+ * The baud rate clock is the system clock divided by something.
+ * It was set up long ago during the initial boot phase and is
+ * is given to us.
+ * Baud rate clocks are zero-based in the driver code (as that maps
+ * to port numbers).  Documentation uses 1-based numbering.
+ */
+#define BRG_INT_CLK    (((bd_t *)__res)->bi_brgfreq)
+#define BRG_UART_CLK   (BRG_INT_CLK/16)
+
+/* This function is used by UARTS, or anything else that uses a 16x
+ * oversampled clock.
+ */
+void
+cpm2_setbrg(uint brg, uint rate)
+{
+       volatile uint   *bp;
+
+       /* This is good enough to get SMCs running.....
+       */
+       if (brg < 4) {
+               bp = (uint *)&cpm2_immr->im_brgc1;
+       }
+       else {
+               bp = (uint *)&cpm2_immr->im_brgc5;
+               brg -= 4;
+       }
+       bp += brg;
+       *bp = ((BRG_UART_CLK / rate) << 1) | CPM_BRG_EN;
+}
+
+/* This function is used to set high speed synchronous baud rate
+ * clocks.
+ */
+void
+cpm2_fastbrg(uint brg, uint rate, int div16)
+{
+       volatile uint   *bp;
+
+       if (brg < 4) {
+               bp = (uint *)&cpm2_immr->im_brgc1;
+       }
+       else {
+               bp = (uint *)&cpm2_immr->im_brgc5;
+               brg -= 4;
+       }
+       bp += brg;
+       *bp = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
+       if (div16)
+               *bp |= CPM_BRG_DIV16;
+}
+
+/*
+ * dpalloc / dpfree bits.
+ */
+static spinlock_t cpm_dpmem_lock;
+/* 16 blocks should be enough to satisfy all requests
+ * until the memory subsystem goes up... */
+static rh_block_t cpm_boot_dpmem_rh_block[16];
+static rh_info_t cpm_dpmem_info;
+
+static void cpm2_dpinit(void)
+{
+       void *dprambase = &((cpm2_map_t *)CPM_MAP_ADDR)->im_dprambase;
+
+       spin_lock_init(&cpm_dpmem_lock);
+
+       /* initialize the info header */
+       rh_init(&cpm_dpmem_info, 1,
+                       sizeof(cpm_boot_dpmem_rh_block) /
+                       sizeof(cpm_boot_dpmem_rh_block[0]),
+                       cpm_boot_dpmem_rh_block);
+
+       /* Attach the usable dpmem area */
+       /* XXX: This is actually crap. CPM_DATAONLY_BASE and
+        * CPM_DATAONLY_SIZE is only a subset of the available dpram. It
+        * varies with the processor and the microcode patches activated.
+        * But the following should be at least safe.
+        */
+       rh_attach_region(&cpm_dpmem_info, dprambase + CPM_DATAONLY_BASE,
+                       CPM_DATAONLY_SIZE);
+}
+
+/* This function used to return an index into the DPRAM area.
+ * Now it returns the actuall physical address of that area.
+ * use cpm2_dpram_offset() to get the index
+ */
+void *cpm2_dpalloc(uint size, uint align)
+{
+       void *start;
+       unsigned long flags;
+
+       spin_lock_irqsave(&cpm_dpmem_lock, flags);
+       cpm_dpmem_info.alignment = align;
+       start = rh_alloc(&cpm_dpmem_info, size, "commproc");
+       spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+       return start;
+}
+EXPORT_SYMBOL(cpm2_dpalloc);
+
+int cpm2_dpfree(void *addr)
+{
+       int ret;
+       unsigned long flags;
+
+       spin_lock_irqsave(&cpm_dpmem_lock, flags);
+       ret = rh_free(&cpm_dpmem_info, addr);
+       spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(cpm2_dpfree);
+
+/* not sure if this is ever needed */
+void *cpm2_dpalloc_fixed(void *addr, uint size, uint align)
+{
+       void *start;
+       unsigned long flags;
+
+       spin_lock_irqsave(&cpm_dpmem_lock, flags);
+       cpm_dpmem_info.alignment = align;
+       start = rh_alloc_fixed(&cpm_dpmem_info, addr, size, "commproc");
+       spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+       return start;
+}
+EXPORT_SYMBOL(cpm2_dpalloc_fixed);
+
+void cpm2_dpdump(void)
+{
+       rh_dump(&cpm_dpmem_info);
+}
+EXPORT_SYMBOL(cpm2_dpdump);
+
+uint cpm2_dpram_offset(void *addr)
+{
+       return (uint)((u_char *)addr -
+                       ((uint)((cpm2_map_t *)CPM_MAP_ADDR)->im_dprambase));
+}
+EXPORT_SYMBOL(cpm2_dpram_offset);
+
+void *cpm2_dpram_addr(int offset)
+{
+       return (void *)&((cpm2_map_t *)CPM_MAP_ADDR)->im_dprambase[offset];
+}
+EXPORT_SYMBOL(cpm2_dpram_addr);
diff --git a/arch/ppc/syslib/m8260_pci_erratum9.c b/arch/ppc/syslib/m8260_pci_erratum9.c
new file mode 100644 (file)
index 0000000..ae76a1b
--- /dev/null
@@ -0,0 +1,474 @@
+/*
+ * arch/ppc/platforms/mpc8260_pci9.c
+ *
+ * Workaround for device erratum PCI 9.
+ * See Motorola's "XPC826xA Family Device Errata Reference."
+ * The erratum applies to all 8260 family Hip4 processors.  It is scheduled 
+ * to be fixed in HiP4 Rev C.  Erratum PCI 9 states that a simultaneous PCI 
+ * inbound write transaction and PCI outbound read transaction can result in a 
+ * bus deadlock.  The suggested workaround is to use the IDMA controller to 
+ * perform all reads from PCI configuration, memory, and I/O space.
+ *
+ * Author:  andy_lowe@mvista.com
+ *
+ * 2003 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/byteorder.h>
+#include <asm/mpc8260.h>
+#include <asm/immap_cpm2.h>
+#include <asm/cpm2.h>
+
+#include "m8260_pci.h"
+
+#ifdef CONFIG_8260_PCI9
+/*#include <asm/mpc8260_pci9.h>*/ /* included in asm/io.h */
+
+#define IDMA_XFER_BUF_SIZE 64  /* size of the IDMA transfer buffer */
+
+/* define a structure for the IDMA dpram usage */
+typedef struct idma_dpram_s {
+       idma_t pram;                            /* IDMA parameter RAM */
+       u_char xfer_buf[IDMA_XFER_BUF_SIZE];    /* IDMA transfer buffer */
+       idma_bd_t bd;                           /* buffer descriptor */
+} idma_dpram_t;
+
+/* define offsets relative to start of IDMA dpram */
+#define IDMA_XFER_BUF_OFFSET (sizeof(idma_t))
+#define IDMA_BD_OFFSET (sizeof(idma_t) + IDMA_XFER_BUF_SIZE)
+
+/* define globals */
+static volatile idma_dpram_t *idma_dpram;
+
+/* Exactly one of CONFIG_8260_PCI9_IDMAn must be defined, 
+ * where n is 1, 2, 3, or 4.  This selects the IDMA channel used for 
+ * the PCI9 workaround.
+ */
+#ifdef CONFIG_8260_PCI9_IDMA1
+#define IDMA_CHAN 0
+#define PROFF_IDMA PROFF_IDMA1_BASE
+#define IDMA_PAGE CPM_CR_IDMA1_PAGE
+#define IDMA_SBLOCK CPM_CR_IDMA1_SBLOCK
+#endif
+#ifdef CONFIG_8260_PCI9_IDMA2
+#define IDMA_CHAN 1
+#define PROFF_IDMA PROFF_IDMA2_BASE
+#define IDMA_PAGE CPM_CR_IDMA2_PAGE
+#define IDMA_SBLOCK CPM_CR_IDMA2_SBLOCK
+#endif
+#ifdef CONFIG_8260_PCI9_IDMA3
+#define IDMA_CHAN 2
+#define PROFF_IDMA PROFF_IDMA3_BASE
+#define IDMA_PAGE CPM_CR_IDMA3_PAGE
+#define IDMA_SBLOCK CPM_CR_IDMA3_SBLOCK
+#endif
+#ifdef CONFIG_8260_PCI9_IDMA4
+#define IDMA_CHAN 3
+#define PROFF_IDMA PROFF_IDMA4_BASE
+#define IDMA_PAGE CPM_CR_IDMA4_PAGE
+#define IDMA_SBLOCK CPM_CR_IDMA4_SBLOCK
+#endif
+
+void idma_pci9_init(void)
+{
+       uint dpram_offset;
+       volatile idma_t *pram;
+       volatile im_idma_t *idma_reg;
+       volatile cpm2_map_t *immap = cpm2_immr;
+
+       /* allocate IDMA dpram */
+       dpram_offset = cpm2_dpalloc(sizeof(idma_dpram_t), 64);
+       idma_dpram = 
+               (volatile idma_dpram_t *)&immap->im_dprambase[dpram_offset];
+
+       /* initialize the IDMA parameter RAM */
+       memset((void *)idma_dpram, 0, sizeof(idma_dpram_t));
+       pram = &idma_dpram->pram;
+       pram->ibase = dpram_offset + IDMA_BD_OFFSET;
+       pram->dpr_buf = dpram_offset + IDMA_XFER_BUF_OFFSET;
+       pram->ss_max = 32;
+       pram->dts = 32;
+
+       /* initialize the IDMA_BASE pointer to the IDMA parameter RAM */
+       *((ushort *) &immap->im_dprambase[PROFF_IDMA]) = dpram_offset;
+
+       /* initialize the IDMA registers */
+       idma_reg = (volatile im_idma_t *) &immap->im_sdma.sdma_idsr1;
+       idma_reg[IDMA_CHAN].idmr = 0;           /* mask all IDMA interrupts */
+       idma_reg[IDMA_CHAN].idsr = 0xff;        /* clear all event flags */
+
+       printk("<4>Using IDMA%d for MPC8260 device erratum PCI 9 workaround\n",
+               IDMA_CHAN + 1);
+
+       return;
+}
+
+/* Use the IDMA controller to transfer data from I/O memory to local RAM.
+ * The src address must be a physical address suitable for use by the DMA 
+ * controller with no translation.  The dst address must be a kernel virtual 
+ * address.  The dst address is translated to a physical address via 
+ * virt_to_phys().
+ * The sinc argument specifies whether or not the source address is incremented
+ * by the DMA controller.  The source address is incremented if and only if sinc
+ * is non-zero.  The destination address is always incremented since the 
+ * destination is always host RAM.
+ */
+static void 
+idma_pci9_read(u8 *dst, u8 *src, int bytes, int unit_size, int sinc)
+{
+       unsigned long flags;
+       volatile idma_t *pram = &idma_dpram->pram;
+       volatile idma_bd_t *bd = &idma_dpram->bd;
+       volatile cpm2_map_t *immap = cpm2_immr;
+
+       local_irq_save(flags);
+
+       /* initialize IDMA parameter RAM for this transfer */
+       if (sinc)
+               pram->dcm = IDMA_DCM_DMA_WRAP_64 | IDMA_DCM_SINC
+                         | IDMA_DCM_DINC | IDMA_DCM_SD_MEM2MEM;
+       else
+               pram->dcm = IDMA_DCM_DMA_WRAP_64 | IDMA_DCM_DINC 
+                         | IDMA_DCM_SD_MEM2MEM;
+       pram->ibdptr = pram->ibase;
+       pram->sts = unit_size;
+       pram->istate = 0;
+
+       /* initialize the buffer descriptor */
+       bd->dst = virt_to_phys(dst);
+       bd->src = (uint) src;
+       bd->len = bytes;
+       bd->flags = IDMA_BD_V | IDMA_BD_W | IDMA_BD_I | IDMA_BD_L | IDMA_BD_DGBL
+                 | IDMA_BD_DBO_BE | IDMA_BD_SBO_BE | IDMA_BD_SDTB;
+
+       /* issue the START_IDMA command to the CP */
+       while (immap->im_cpm.cp_cpcr & CPM_CR_FLG);
+       immap->im_cpm.cp_cpcr = mk_cr_cmd(IDMA_PAGE, IDMA_SBLOCK, 0,
+                                        CPM_CR_START_IDMA) | CPM_CR_FLG;
+       while (immap->im_cpm.cp_cpcr & CPM_CR_FLG);
+
+       /* wait for transfer to complete */
+       while(bd->flags & IDMA_BD_V);
+
+       local_irq_restore(flags);
+
+       return;
+}
+
+/* Use the IDMA controller to transfer data from I/O memory to local RAM.
+ * The dst address must be a physical address suitable for use by the DMA 
+ * controller with no translation.  The src address must be a kernel virtual 
+ * address.  The src address is translated to a physical address via 
+ * virt_to_phys().
+ * The dinc argument specifies whether or not the dest address is incremented
+ * by the DMA controller.  The source address is incremented if and only if sinc
+ * is non-zero.  The source address is always incremented since the 
+ * source is always host RAM.
+ */
+static void 
+idma_pci9_write(u8 *dst, u8 *src, int bytes, int unit_size, int dinc)
+{
+       unsigned long flags;
+       volatile idma_t *pram = &idma_dpram->pram;
+       volatile idma_bd_t *bd = &idma_dpram->bd;
+       volatile cpm2_map_t *immap = cpm2_immr;
+
+       local_irq_save(flags);
+
+       /* initialize IDMA parameter RAM for this transfer */
+       if (dinc)
+               pram->dcm = IDMA_DCM_DMA_WRAP_64 | IDMA_DCM_SINC
+                         | IDMA_DCM_DINC | IDMA_DCM_SD_MEM2MEM;
+       else
+               pram->dcm = IDMA_DCM_DMA_WRAP_64 | IDMA_DCM_SINC 
+                         | IDMA_DCM_SD_MEM2MEM;
+       pram->ibdptr = pram->ibase;
+       pram->sts = unit_size;
+       pram->istate = 0;
+
+       /* initialize the buffer descriptor */
+       bd->dst = (uint) dst;
+       bd->src = virt_to_phys(src);
+       bd->len = bytes;
+       bd->flags = IDMA_BD_V | IDMA_BD_W | IDMA_BD_I | IDMA_BD_L | IDMA_BD_DGBL
+                 | IDMA_BD_DBO_BE | IDMA_BD_SBO_BE | IDMA_BD_SDTB;
+
+       /* issue the START_IDMA command to the CP */
+       while (immap->im_cpm.cp_cpcr & CPM_CR_FLG);
+       immap->im_cpm.cp_cpcr = mk_cr_cmd(IDMA_PAGE, IDMA_SBLOCK, 0,
+                                        CPM_CR_START_IDMA) | CPM_CR_FLG;
+       while (immap->im_cpm.cp_cpcr & CPM_CR_FLG);
+
+       /* wait for transfer to complete */
+       while(bd->flags & IDMA_BD_V);
+
+       local_irq_restore(flags);
+
+       return;
+}
+
+/* Same as idma_pci9_read, but 16-bit little-endian byte swapping is performed
+ * if the unit_size is 2, and 32-bit little-endian byte swapping is performed if
+ * the unit_size is 4.
+ */
+static void 
+idma_pci9_read_le(u8 *dst, u8 *src, int bytes, int unit_size, int sinc)
+{
+       int i;
+       u8 *p;
+
+       idma_pci9_read(dst, src, bytes, unit_size, sinc);
+       switch(unit_size) {
+               case 2:
+                       for (i = 0, p = dst; i < bytes; i += 2, p += 2)
+                               swab16s((u16 *) p);
+                       break;
+               case 4:
+                       for (i = 0, p = dst; i < bytes; i += 4, p += 4)
+                               swab32s((u32 *) p);
+                       break;
+               default:
+                       break;
+       }
+}
+EXPORT_SYMBOL(idma_pci9_init);
+EXPORT_SYMBOL(idma_pci9_read);
+EXPORT_SYMBOL(idma_pci9_read_le);
+
+static inline int is_pci_mem(unsigned long addr)
+{
+       if (addr >= MPC826x_PCI_LOWER_MMIO &&
+           addr <= MPC826x_PCI_UPPER_MMIO)
+               return 1;
+       if (addr >= MPC826x_PCI_LOWER_MEM &&
+           addr <= MPC826x_PCI_UPPER_MEM)
+               return 1;
+       return 0;
+}
+
+#define is_pci_mem(pa) ( (pa > 0x80000000) && (pa < 0xc0000000))
+int readb(volatile unsigned char *addr)
+{
+       u8 val;
+       unsigned long pa = iopa((unsigned long) addr);
+
+       if (!is_pci_mem(pa))
+               return in_8(addr);
+
+       idma_pci9_read((u8 *)&val, (u8 *)pa, sizeof(val), sizeof(val), 0);
+       return val;
+}
+
+int readw(volatile unsigned short *addr)
+{
+       u16 val;
+       unsigned long pa = iopa((unsigned long) addr);
+
+       if (!is_pci_mem(pa))
+               return in_le16(addr);
+
+       idma_pci9_read((u8 *)&val, (u8 *)pa, sizeof(val), sizeof(val), 0);
+       return swab16(val);
+}
+
+unsigned readl(volatile unsigned *addr)
+{
+       u32 val;
+       unsigned long pa = iopa((unsigned long) addr);
+
+       if (!is_pci_mem(pa))
+               return in_le32(addr);
+
+       idma_pci9_read((u8 *)&val, (u8 *)pa, sizeof(val), sizeof(val), 0);
+       return swab32(val);
+}
+
+int inb(unsigned port)
+{
+       u8 val;
+       u8 *addr = (u8 *)(port + _IO_BASE);
+
+       idma_pci9_read((u8 *)&val, (u8 *)addr, sizeof(val), sizeof(val), 0);
+       return val;
+}
+
+int inw(unsigned port)
+{
+       u16 val;
+       u8 *addr = (u8 *)(port + _IO_BASE);
+
+       idma_pci9_read((u8 *)&val, (u8 *)addr, sizeof(val), sizeof(val), 0);
+       return swab16(val);
+}
+
+unsigned inl(unsigned port)
+{
+       u32 val;
+       u8 *addr = (u8 *)(port + _IO_BASE);
+
+       idma_pci9_read((u8 *)&val, (u8 *)addr, sizeof(val), sizeof(val), 0);
+       return swab32(val);
+}
+
+void insb(unsigned port, void *buf, int ns)
+{
+       u8 *addr = (u8 *)(port + _IO_BASE);
+
+       idma_pci9_read((u8 *)buf, (u8 *)addr, ns*sizeof(u8), sizeof(u8), 0);
+}
+
+void insw(unsigned port, void *buf, int ns)
+{
+       u8 *addr = (u8 *)(port + _IO_BASE);
+
+       idma_pci9_read((u8 *)buf, (u8 *)addr, ns*sizeof(u16), sizeof(u16), 0);
+}
+
+void insl(unsigned port, void *buf, int nl)
+{
+       u8 *addr = (u8 *)(port + _IO_BASE);
+
+       idma_pci9_read((u8 *)buf, (u8 *)addr, nl*sizeof(u32), sizeof(u32), 0);
+}
+
+void insw_ns(unsigned port, void *buf, int ns)
+{
+       u8 *addr = (u8 *)(port + _IO_BASE);
+
+       idma_pci9_read((u8 *)buf, (u8 *)addr, ns*sizeof(u16), sizeof(u16), 0);
+}
+
+void insl_ns(unsigned port, void *buf, int nl)
+{
+       u8 *addr = (u8 *)(port + _IO_BASE);
+
+       idma_pci9_read((u8 *)buf, (u8 *)addr, nl*sizeof(u32), sizeof(u32), 0);
+}
+
+void *memcpy_fromio(void *dest, unsigned long src, size_t count)
+{
+       unsigned long pa = iopa((unsigned long) src);
+
+       if (is_pci_mem(pa))
+               idma_pci9_read((u8 *)dest, (u8 *)pa, count, 32, 1);
+       else
+               memcpy(dest, (void *)src, count);
+       return dest;
+}
+
+EXPORT_SYMBOL(readb);
+EXPORT_SYMBOL(readw);
+EXPORT_SYMBOL(readl);
+EXPORT_SYMBOL(inb);
+EXPORT_SYMBOL(inw);
+EXPORT_SYMBOL(inl);
+EXPORT_SYMBOL(insb);
+EXPORT_SYMBOL(insw);
+EXPORT_SYMBOL(insl);
+EXPORT_SYMBOL(insw_ns);
+EXPORT_SYMBOL(insl_ns);
+EXPORT_SYMBOL(memcpy_fromio);
+
+#endif /* ifdef CONFIG_8260_PCI9 */
+
+/* Indirect PCI routines adapted from arch/ppc/kernel/indirect_pci.c.
+ * Copyright (C) 1998 Gabriel Paubert.
+ */
+#ifndef CONFIG_8260_PCI9
+#define cfg_read(val, addr, type, op)  *val = op((type)(addr))
+#else
+#define cfg_read(val, addr, type, op) \
+       idma_pci9_read_le((u8*)(val),(u8*)(addr),sizeof(*(val)),sizeof(*(val)),0)
+#endif
+
+#define cfg_write(val, addr, type, op) op((type *)(addr), (val))
+
+static int indirect_write_config(struct pci_bus *pbus, unsigned int devfn, int where,
+                        int size, u32 value)
+{
+       struct pci_controller *hose = pbus->sysdata;
+       u8 cfg_type = 0;
+       if (ppc_md.pci_exclude_device)
+               if (ppc_md.pci_exclude_device(pbus->number, devfn))
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+
+       if (hose->set_cfg_type)
+               if (pbus->number != hose->first_busno)
+                       cfg_type = 1;
+
+       out_be32(hose->cfg_addr,
+                (((where & 0xfc) | cfg_type) << 24) | (devfn << 16)
+                | ((pbus->number - hose->bus_offset) << 8) | 0x80);
+
+       switch (size)
+       {
+               case 1:
+                       cfg_write(value, hose->cfg_data + (where & 3), u8, out_8);
+                       break;
+               case 2:
+                       cfg_write(value, hose->cfg_data + (where & 2), u16, out_le16);
+                       break;
+               case 4:
+                       cfg_write(value, hose->cfg_data + (where & 0), u32, out_le32);
+                       break;
+       }               
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int indirect_read_config(struct pci_bus *pbus, unsigned int devfn, int where,
+                        int size, u32 *value)
+{
+       struct pci_controller *hose = pbus->sysdata;
+       u8 cfg_type = 0;
+       if (ppc_md.pci_exclude_device)
+               if (ppc_md.pci_exclude_device(pbus->number, devfn))
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+
+       if (hose->set_cfg_type)
+               if (pbus->number != hose->first_busno)
+                       cfg_type = 1;
+
+       out_be32(hose->cfg_addr,
+                (((where & 0xfc) | cfg_type) << 24) | (devfn << 16)
+                | ((pbus->number - hose->bus_offset) << 8) | 0x80);
+
+       switch (size)
+       {
+               case 1:
+                       cfg_read(value, hose->cfg_data + (where & 3), u8 *, in_8);
+                       break;
+               case 2:
+                       cfg_read(value, hose->cfg_data + (where & 2), u16 *, in_le16);
+                       break;
+               case 4:
+                       cfg_read(value, hose->cfg_data + (where & 0), u32 *, in_le32);
+                       break;
+       }               
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops indirect_pci_ops =
+{
+       .read = indirect_read_config,
+       .write = indirect_write_config,
+};
+
+void
+setup_m8260_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
+{
+       hose->ops = &indirect_pci_ops;
+       hose->cfg_addr = (unsigned int *) ioremap(cfg_addr, 4);
+       hose->cfg_data = (unsigned char *) ioremap(cfg_data, 4);
+}
diff --git a/arch/sh/boards/renesas/systemh/Makefile b/arch/sh/boards/renesas/systemh/Makefile
new file mode 100644 (file)
index 0000000..2cc6a23
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Makefile for the SystemH specific parts of the kernel
+#
+
+obj-y   := setup.o irq.o io.o
+
+# XXX: This wants to be consolidated in arch/sh/drivers/pci, and more
+# importantly, with the generic sh7751_pcic_init() code. For now, we'll
+# just abuse the hell out of kbuild, because we can..
+
+obj-$(CONFIG_PCI) += pci.o
+pci-y := ../../se/7751/pci.o
+
diff --git a/arch/sh/boards/se/7300/Makefile b/arch/sh/boards/se/7300/Makefile
new file mode 100644 (file)
index 0000000..0fbd4f4
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the 7300 SolutionEngine specific parts of the kernel
+#
+
+obj-y   := setup.o io.o irq.o
+
+obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/cchips/voyagergx/Makefile b/arch/sh/cchips/voyagergx/Makefile
new file mode 100644 (file)
index 0000000..085de72
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for VoyagerGX
+#
+
+obj-y  := irq.o setup.o
+
+obj-$(CONFIG_USB_OHCI_HCD)     += consistent.o
+
diff --git a/arch/sh/cchips/voyagergx/consistent.c b/arch/sh/cchips/voyagergx/consistent.c
new file mode 100644 (file)
index 0000000..95a309d
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * arch/sh/cchips/voyagergx/consistent.c
+ *
+ * Copyright (C) 2004  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <asm/io.h>
+#include <asm/bus-sh.h>
+
+struct voya_alloc_entry {
+       struct list_head list;
+       unsigned long ofs;
+       unsigned long len;
+};
+
+static spinlock_t voya_list_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(voya_alloc_list);
+
+#define OHCI_SRAM_START        0xb0000000
+#define OHCI_HCCA_SIZE 0x100
+#define OHCI_SRAM_SIZE 0x10000
+
+void *voyagergx_consistent_alloc(struct device *dev, size_t size,
+                                dma_addr_t *handle, int flag)
+{
+       struct list_head *list = &voya_alloc_list;
+       struct voya_alloc_entry *entry;
+       struct sh_dev *shdev = to_sh_dev(dev);
+       unsigned long start, end;
+       unsigned long flags;
+
+       /*
+        * The SM501 contains an integrated 8051 with its own SRAM.
+        * Devices within the cchip can all hook into the 8051 SRAM.
+        * We presently use this for the OHCI.
+        *
+        * Everything else goes through consistent_alloc().
+        */
+       if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] ||
+                  (dev->bus == &sh_bus_types[SH_BUS_VIRT] &&
+                   shdev->dev_id != SH_DEV_ID_USB_OHCI))
+               return consistent_alloc(flag, size, handle);
+
+       start = OHCI_SRAM_START + OHCI_HCCA_SIZE;
+
+       entry = kmalloc(sizeof(struct voya_alloc_entry), GFP_ATOMIC);
+       if (!entry)
+               return NULL;
+
+       entry->len = (size + 15) & ~15;
+
+       /*
+        * The basis for this allocator is dwmw2's malloc.. the
+        * Matrox allocator :-)
+        */
+       spin_lock_irqsave(&voya_list_lock, flags);
+       list_for_each(list, &voya_alloc_list) {
+               struct voya_alloc_entry *p;
+
+               p = list_entry(list, struct voya_alloc_entry, list);
+
+               if (p->ofs - start >= size)
+                       goto out;
+
+               start = p->ofs + p->len;
+       }
+
+       end  = start + (OHCI_SRAM_SIZE  - OHCI_HCCA_SIZE);
+       list = &voya_alloc_list;
+
+       if (end - start >= size) {
+out:
+               entry->ofs = start;
+               list_add_tail(&entry->list, list);
+               spin_unlock_irqrestore(&voya_list_lock, flags);
+
+               *handle = start;
+               return (void *)start;
+       }
+
+       kfree(entry);
+       spin_unlock_irqrestore(&voya_list_lock, flags);
+
+       return NULL;
+}
+
+void voyagergx_consistent_free(struct device *dev, size_t size,
+                              void *vaddr, dma_addr_t handle)
+{
+       struct voya_alloc_entry *entry;
+       struct sh_dev *shdev = to_sh_dev(dev);
+       unsigned long flags;
+
+       if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] ||
+                  (dev->bus == &sh_bus_types[SH_BUS_VIRT] &&
+                   shdev->dev_id != SH_DEV_ID_USB_OHCI)) {
+               consistent_free(vaddr, size);
+               return;
+       }
+
+       spin_lock_irqsave(&voya_list_lock, flags);
+       list_for_each_entry(entry, &voya_alloc_list, list) {
+               if (entry->ofs != handle)
+                       continue;
+
+               list_del(&entry->list);
+               kfree(entry);
+
+               break;
+       }
+       spin_unlock_irqrestore(&voya_list_lock, flags);
+}
+
+EXPORT_SYMBOL(voyagergx_consistent_alloc);
+EXPORT_SYMBOL(voyagergx_consistent_free);
+
diff --git a/arch/sh/configs/rts7751r2d_defconfig b/arch/sh/configs/rts7751r2d_defconfig
new file mode 100644 (file)
index 0000000..f9e1f7c
--- /dev/null
@@ -0,0 +1,809 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+CONFIG_SH_RTS7751R2D=y
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+CONFIG_CPU_SUBTYPE_SH7751=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+CONFIG_MMU=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="mem=64M console=ttySC0,115200 root=/dev/hda1"
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_MEMORY_SET=y
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_SH_RTC=y
+CONFIG_ZERO_PAGE_OFFSET=0x00010000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_PREEMPT is not set
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SH_STORE_QUEUES is not set
+# CONFIG_SMP is not set
+CONFIG_VOYAGERGX=y
+CONFIG_RTS7751R2D_REV11=y
+CONFIG_SH_PCLK_FREQ=60000000
+# CONFIG_CPU_FREQ is not set
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=8
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+# CONFIG_DMA_PAGE_OPS is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_ISA=y
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+CONFIG_PCI_DMA=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_NAMES=y
+CONFIG_HOTPLUG=y
+
+#
+# PCMCIA/CardBus support
+#
+CONFIG_PCMCIA=m
+CONFIG_YENTA=m
+CONFIG_CARDBUS=y
+# CONFIG_I82092 is not set
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_PROBE=y
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IPV6_SCTP__=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_ISA=y
+# CONFIG_E2100 is not set
+# CONFIG_EWRK3 is not set
+# CONFIG_EEXPRESS is not set
+# CONFIG_EEXPRESS_PRO is not set
+# CONFIG_HPLAN_PLUS is not set
+# CONFIG_HPLAN is not set
+# CONFIG_LP486E is not set
+# CONFIG_ETH16I is not set
+CONFIG_NE2000=m
+# CONFIG_ZNET is not set
+# CONFIG_SEEQ8005 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_ARLAN is not set
+# CONFIG_WAVELAN is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_AIRO is not set
+CONFIG_HERMES=m
+# CONFIG_PLX_HERMES is not set
+# CONFIG_TMD_HERMES is not set
+# CONFIG_PCI_HERMES is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_ATMEL is not set
+# CONFIG_PCMCIA_WL3501 is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN_BOOL is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL is not set
+CONFIG_SH_SCI=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_RTC_9701JE=y
+
+#
+# Unix 98 PTY support
+#
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_HEARTBEAT=y
+# CONFIG_PSMOUSE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_SH_SCI is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# I2C Algorithms
+#
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_EXPORTFS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=y
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_OSSEMUL is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ISA devices
+#
+# CONFIG_SND_AD1848 is not set
+# CONFIG_SND_CS4231 is not set
+# CONFIG_SND_CS4232 is not set
+# CONFIG_SND_CS4236 is not set
+# CONFIG_SND_ES1688 is not set
+# CONFIG_SND_ES18XX is not set
+# CONFIG_SND_GUSCLASSIC is not set
+# CONFIG_SND_GUSEXTREME is not set
+# CONFIG_SND_GUSMAX is not set
+# CONFIG_SND_INTERWAVE is not set
+# CONFIG_SND_INTERWAVE_STB is not set
+# CONFIG_SND_OPTI92X_AD1848 is not set
+# CONFIG_SND_OPTI92X_CS4231 is not set
+# CONFIG_SND_OPTI93X is not set
+# CONFIG_SND_SB8 is not set
+# CONFIG_SND_SB16 is not set
+# CONFIG_SND_SBAWE is not set
+# CONFIG_SND_WAVEFRONT is not set
+# CONFIG_SND_CMI8330 is not set
+# CONFIG_SND_OPL3SA2 is not set
+# CONFIG_SND_SGALAXY is not set
+# CONFIG_SND_SSCAPE is not set
+
+#
+# PCI devices
+#
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_TRIDENT is not set
+CONFIG_SND_YMFPCI=m
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VX222 is not set
+
+#
+# PCMCIA devices
+#
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_VXP440 is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_SOUND_BT878 is not set
+CONFIG_SOUND_CMPCI=m
+# CONFIG_SOUND_CMPCI_FM is not set
+# CONFIG_SOUND_CMPCI_MIDI is not set
+# CONFIG_SOUND_CMPCI_JOYSTICK is not set
+# CONFIG_SOUND_CMPCI_CM8738 is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_ALI5455 is not set
+# CONFIG_SOUND_FORTE is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_AD1980 is not set
+CONFIG_SOUND_VOYAGERGX=m
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_KGDB is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
diff --git a/arch/sh/kernel/cpu/adc.c b/arch/sh/kernel/cpu/adc.c
new file mode 100644 (file)
index 0000000..da3d687
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * linux/arch/sh/kernel/adc.c -- SH3 on-chip ADC support
+ *
+ *  Copyright (C) 2004  Andriy Skulysh <askulysh@image.kiev.ua>
+ */
+
+#include <linux/module.h>
+#include <asm/adc.h>
+#include <asm/io.h>
+
+
+int adc_single(unsigned int channel)
+{
+       int off;
+       unsigned char csr;
+
+       if (channel >= 8) return -1;
+
+       off = (channel & 0x03) << 2;
+
+       csr = ctrl_inb(ADCSR);
+       csr = channel | ADCSR_ADST | ADCSR_CKS;
+       ctrl_outb(csr, ADCSR);
+
+       do {
+               csr = ctrl_inb(ADCSR);
+       } while ((csr & ADCSR_ADF) == 0);
+
+       csr &= ~(ADCSR_ADF | ADCSR_ADST);
+       ctrl_outb(csr, ADCSR);
+
+       return (((ctrl_inb(ADDRAH + off) << 8) |
+               ctrl_inb(ADDRAL + off)) >> 6);
+}
+
+EXPORT_SYMBOL(adc_single);
diff --git a/arch/sh64/boot/Makefile b/arch/sh64/boot/Makefile
new file mode 100644 (file)
index 0000000..fb71087
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# arch/sh64/boot/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2002 Stuart Menefy
+#
+
+targets := zImage
+subdir- := compressed
+
+$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
+       $(call if_changed,objcopy)
+       @echo 'Kernel: $@ is ready'
+
+$(obj)/compressed/vmlinux: FORCE
+       $(Q)$(MAKE) $(build)=$(obj)/compressed $@
+
diff --git a/arch/sh64/boot/compressed/Makefile b/arch/sh64/boot/compressed/Makefile
new file mode 100644 (file)
index 0000000..3f6cbf0
--- /dev/null
@@ -0,0 +1,46 @@
+#
+# linux/arch/sh64/boot/compressed/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2002 Stuart Menefy
+# Copyright (C) 2004 Paul Mundt
+#
+# create a compressed vmlinux image from the original vmlinux
+#
+
+targets                := vmlinux vmlinux.bin vmlinux.bin.gz \
+                  head.o misc.o cache.o piggy.o vmlinux.lds.o
+
+EXTRA_AFLAGS   := -traditional
+
+OBJECTS                := $(obj)/head.o $(obj)/misc.o $(obj)/cache.o
+
+#
+# ZIMAGE_OFFSET is the load offset of the compression loader
+# (4M for the kernel plus 64K for this loader)
+#
+ZIMAGE_OFFSET = $(shell printf "0x%8x" $$[$(CONFIG_MEMORY_START)+0x400000+0x10000])
+
+LDFLAGS_vmlinux := -Ttext $(ZIMAGE_OFFSET) -e startup \
+                   -T $(obj)/../../kernel/vmlinux.lds.s \
+                   --no-warn-mismatch
+
+$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
+       $(call if_changed,ld)
+       @:
+
+$(obj)/vmlinux.bin: vmlinux FORCE
+       $(call if_changed,objcopy)
+
+$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+       $(call if_changed,gzip)
+
+LDFLAGS_piggy.o := -r --format binary --oformat elf32-sh64-linux -T
+OBJCOPYFLAGS += -R .empty_zero_page
+
+$(obj)/piggy.o: $(obj)/vmlinux.lds.s $(obj)/vmlinux.bin.gz FORCE
+       $(call if_changed,ld)
+
diff --git a/arch/sh64/boot/compressed/cache.c b/arch/sh64/boot/compressed/cache.c
new file mode 100644 (file)
index 0000000..7087073
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * arch/shmedia/boot/compressed/cache.c -- simple cache management functions
+ *
+ * Code extracted from sh-ipl+g, sh-stub.c, which has the copyright:
+ *
+ *   This is originally based on an m68k software stub written by Glenn
+ *   Engel at HP, but has changed quite a bit.
+ *
+ *   Modifications for the SH by Ben Lee and Steve Chamberlain
+ *
+****************************************************************************
+
+               THIS SOFTWARE IS NOT COPYRIGHTED
+
+   HP offers the following for use in the public domain.  HP makes no
+   warranty with regard to the software or it's performance and the
+   user accepts the software "AS IS" with all faults.
+
+   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+#define CACHE_ENABLE      0
+#define CACHE_DISABLE     1
+
+int cache_control(unsigned int command)
+{
+       volatile unsigned int *p = (volatile unsigned int *) 0x80000000;
+       int i;
+
+       for (i = 0; i < (32 * 1024); i += 32) {
+               (void *) *p;
+               p += (32 / sizeof (int));
+       }
+
+       return 0;
+}
diff --git a/arch/sh64/boot/compressed/head.S b/arch/sh64/boot/compressed/head.S
new file mode 100644 (file)
index 0000000..82040b1
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * arch/shmedia/boot/compressed/head.S
+ *
+ * Copied from
+ *   arch/shmedia/kernel/head.S
+ * which carried the copyright:
+ *   Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ * Modification for compressed loader:
+ *   Copyright (C) 2002 Stuart Menefy (stuart.menefy@st.com)
+ */
+
+#include <linux/linkage.h>
+#include <asm/registers.h>
+#include <asm/cache.h>
+#include <asm/mmu_context.h>
+
+/*
+ * Fixed TLB entries to identity map the beginning of RAM
+ */
+#define MMUIR_TEXT_H   0x0000000000000003 | CONFIG_MEMORY_START
+                       /* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */
+#define MMUIR_TEXT_L   0x000000000000009a | CONFIG_MEMORY_START
+                       /* 512 Mb, Cacheable (Write-back), execute, Not User, Ph. Add. */
+
+#define MMUDR_CACHED_H 0x0000000000000003 | CONFIG_MEMORY_START
+                       /* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */
+#define MMUDR_CACHED_L 0x000000000000015a | CONFIG_MEMORY_START
+                       /* 512 Mb, Cacheable (Write-back), read/write, Not User, Ph. Add. */
+
+#define        ICCR0_INIT_VAL  ICCR0_ON | ICCR0_ICI            /* ICE + ICI */
+#define        ICCR1_INIT_VAL  ICCR1_NOLOCK                    /* No locking */
+
+#if 1
+#define        OCCR0_INIT_VAL  OCCR0_ON | OCCR0_OCI | OCCR0_WB /* OCE + OCI + WB */
+#else
+#define        OCCR0_INIT_VAL  OCCR0_OFF
+#endif
+#define        OCCR1_INIT_VAL  OCCR1_NOLOCK                    /* No locking */
+
+       .text
+
+       .global startup
+startup:
+       /*
+        * Prevent speculative fetch on device memory due to
+        * uninitialized target registers.
+        * This must be executed before the first branch.
+        */
+       ptabs/u ZERO, tr0
+       ptabs/u ZERO, tr1
+       ptabs/u ZERO, tr2
+       ptabs/u ZERO, tr3
+       ptabs/u ZERO, tr4
+       ptabs/u ZERO, tr5
+       ptabs/u ZERO, tr6
+       ptabs/u ZERO, tr7
+       synci
+
+       /*
+        * Set initial TLB entries for cached and uncached regions.
+        * Note: PTA/BLINK is PIC code, PTABS/BLINK isn't !
+        */
+       /* Clear ITLBs */
+       pta     1f, tr1
+       movi    ITLB_FIXED, r21
+       movi    ITLB_LAST_VAR_UNRESTRICTED+TLB_STEP, r22
+1:     putcfg  r21, 0, ZERO            /* Clear MMUIR[n].PTEH.V */
+       addi    r21, TLB_STEP, r21
+        bne    r21, r22, tr1
+
+       /* Clear DTLBs */
+       pta     1f, tr1
+       movi    DTLB_FIXED, r21
+       movi    DTLB_LAST_VAR_UNRESTRICTED+TLB_STEP, r22
+1:     putcfg  r21, 0, ZERO            /* Clear MMUDR[n].PTEH.V */
+       addi    r21, TLB_STEP, r21
+        bne    r21, r22, tr1
+
+       /* Map one big (512Mb) page for ITLB */
+       movi    ITLB_FIXED, r21
+       movi    MMUIR_TEXT_L, r22       /* PTEL first */
+       putcfg  r21, 1, r22             /* Set MMUIR[0].PTEL */
+       movi    MMUIR_TEXT_H, r22       /* PTEH last */
+       putcfg  r21, 0, r22             /* Set MMUIR[0].PTEH */
+
+       /* Map one big CACHED (512Mb) page for DTLB */
+       movi    DTLB_FIXED, r21
+       movi    MMUDR_CACHED_L, r22     /* PTEL first */
+       putcfg  r21, 1, r22             /* Set MMUDR[0].PTEL */
+       movi    MMUDR_CACHED_H, r22     /* PTEH last */
+       putcfg  r21, 0, r22             /* Set MMUDR[0].PTEH */
+
+       /* ICache */
+       movi    ICCR_BASE, r21
+       movi    ICCR0_INIT_VAL, r22
+       movi    ICCR1_INIT_VAL, r23
+       putcfg  r21, ICCR_REG0, r22
+       putcfg  r21, ICCR_REG1, r23
+       synci
+
+       /* OCache */
+       movi    OCCR_BASE, r21
+       movi    OCCR0_INIT_VAL, r22
+       movi    OCCR1_INIT_VAL, r23
+       putcfg  r21, OCCR_REG0, r22
+       putcfg  r21, OCCR_REG1, r23
+       synco
+
+       /*
+        * Enable the MMU.
+        * From here-on code can be non-PIC.
+        */
+       movi    SR_HARMLESS | SR_ENABLE_MMU, r22
+       putcon  r22, SSR
+       movi    1f, r22
+       putcon  r22, SPC
+       synco
+       rte                             /* And now go into the hyperspace ... */
+1:                                     /* ... that's the next instruction ! */
+
+       /* Set initial stack pointer */
+       movi    datalabel stack_start, r0
+       ld.l    r0, 0, r15
+
+       /*
+        * Clear bss
+        */
+       pt      1f, tr1
+       movi    datalabel __bss_start, r22
+       movi    datalabel _end, r23
+1:     st.l    r22, 0, ZERO
+       addi    r22, 4, r22
+       bne     r22, r23, tr1
+
+       /*
+        * Decompress the kernel.
+        */
+       pt      decompress_kernel, tr0
+       blink   tr0, r18
+
+       /*
+        * Disable the MMU.
+        */
+       movi    SR_HARMLESS, r22
+       putcon  r22, SSR
+       movi    1f, r22
+       putcon  r22, SPC
+       synco
+       rte                             /* And now go into the hyperspace ... */
+1:                                     /* ... that's the next instruction ! */
+
+       /* Jump into the decompressed kernel */
+       movi    datalabel (CONFIG_MEMORY_START + 0x2000)+1, r19
+       ptabs   r19, tr0
+       blink   tr0, r18
+
+       /* Shouldn't return here, but just in case, loop forever */
+       pt      1f, tr0
+1:     blink   tr0, ZERO
diff --git a/arch/sh64/boot/compressed/install.sh b/arch/sh64/boot/compressed/install.sh
new file mode 100644 (file)
index 0000000..90589f0
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/sh
+#
+# arch/sh/boot/install.sh
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1995 by Linus Torvalds
+#
+# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
+# Adapted from code in arch/i386/boot/install.sh by Russell King
+# Adapted from code in arch/arm/boot/install.sh by Stuart Menefy
+#
+# "make install" script for sh architecture
+#
+# Arguments:
+#   $1 - kernel version
+#   $2 - kernel image file
+#   $3 - kernel map file
+#   $4 - default install path (blank if root directory)
+#
+
+# User may have a custom install script
+
+if [ -x /sbin/installkernel ]; then
+  exec /sbin/installkernel "$@"
+fi
+
+if [ "$2" = "zImage" ]; then
+# Compressed install
+  echo "Installing compressed kernel"
+  if [ -f $4/vmlinuz-$1 ]; then
+    mv $4/vmlinuz-$1 $4/vmlinuz.old
+  fi
+
+  if [ -f $4/System.map-$1 ]; then
+    mv $4/System.map-$1 $4/System.old
+  fi
+
+  cat $2 > $4/vmlinuz-$1
+  cp $3 $4/System.map-$1
+else
+# Normal install
+  echo "Installing normal kernel"
+  if [ -f $4/vmlinux-$1 ]; then
+    mv $4/vmlinux-$1 $4/vmlinux.old
+  fi
+
+  if [ -f $4/System.map ]; then
+    mv $4/System.map $4/System.old
+  fi
+
+  cat $2 > $4/vmlinux-$1
+  cp $3 $4/System.map
+fi
diff --git a/arch/sh64/configs/cayman_defconfig b/arch/sh64/configs/cayman_defconfig
new file mode 100644 (file)
index 0000000..6dd7cea
--- /dev/null
@@ -0,0 +1,660 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH64=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_LOG_BUF_SHIFT=14
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System type
+#
+# CONFIG_SH_GENERIC is not set
+# CONFIG_SH_SIMULATOR is not set
+CONFIG_SH_CAYMAN=y
+# CONFIG_SH_ROMRAM is not set
+# CONFIG_SH_HARP is not set
+
+#
+# Processor type and features
+#
+CONFIG_CPU_SH5=y
+CONFIG_CPU_SUBTYPE_SH5_101=y
+# CONFIG_CPU_SUBTYPE_SH5_103 is not set
+CONFIG_LITTLE_ENDIAN=y
+# CONFIG_BIG_ENDIAN is not set
+# CONFIG_SH64_FPU_DENORM_FLUSH is not set
+CONFIG_SH64_PGTABLE_2_LEVEL=y
+# CONFIG_SH64_PGTABLE_3_LEVEL is not set
+CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_512MB is not set
+CONFIG_SH64_USER_MISALIGNED_FIXUP=y
+
+#
+# Memory options
+#
+CONFIG_CACHED_MEMORY_OFFSET=0x20000000
+CONFIG_MEMORY_START=0x80000000
+CONFIG_MEMORY_SIZE_IN_MB=128
+
+#
+# Cache options
+#
+# CONFIG_DCACHE_DISABLED is not set
+CONFIG_DCACHE_WRITE_BACK=y
+# CONFIG_DCACHE_WRITE_THROUGH is not set
+# CONFIG_ICACHE_DISABLED is not set
+CONFIG_PCIDEVICE_MEMORY_START=C0000000
+CONFIG_DEVICE_MEMORY_START=E0000000
+CONFIG_FLASH_MEMORY_START=0x00000000
+CONFIG_PCI_BLOCK_START=0x40000000
+
+#
+# CPU Subtype specific options
+#
+CONFIG_SH64_ID2815_WORKAROUND=y
+
+#
+# Misc options
+#
+CONFIG_HEARTBEAT=y
+CONFIG_HDSP253_LED=y
+CONFIG_SH_DMA=y
+CONFIG_PREEMPT=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_SH_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_E1355 is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+CONFIG_FB_KYRO=y
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_PCI_CONSOLE=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_SUPERH_MONO is not set
+# CONFIG_LOGO_SUPERH_VGA16 is not set
+CONFIG_LOGO_SUPERH_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+CONFIG_MINIX_FS=y
+CONFIG_ROMFS_FS=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_DEBUG_KERNEL_WITH_GDB_STUB is not set
+# CONFIG_SH64_PROC_TLB is not set
+# CONFIG_SH64_PROC_ASIDS is not set
+CONFIG_SH64_SR_WATCH=y
+# CONFIG_SH_ALPHANUMERIC is not set
+# CONFIG_SH_NO_BSS_INIT is not set
+CONFIG_FRAME_POINTER=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh64/defconfig b/arch/sh64/defconfig
new file mode 100644 (file)
index 0000000..e6233e8
--- /dev/null
@@ -0,0 +1,668 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH64=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_LOG_BUF_SHIFT=14
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# System type
+#
+# CONFIG_SH_GENERIC is not set
+# CONFIG_SH_SIMULATOR is not set
+CONFIG_SH_CAYMAN=y
+# CONFIG_SH_ROMRAM is not set
+# CONFIG_SH_HARP is not set
+CONFIG_CPU_SH5=y
+CONFIG_CPU_SUBTYPE_SH5_101=y
+# CONFIG_CPU_SUBTYPE_SH5_103 is not set
+CONFIG_LITTLE_ENDIAN=y
+# CONFIG_BIG_ENDIAN is not set
+# CONFIG_SH64_FPU_DENORM_FLUSH is not set
+CONFIG_SH64_PGTABLE_2_LEVEL=y
+# CONFIG_SH64_PGTABLE_3_LEVEL is not set
+CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_512MB is not set
+CONFIG_SH64_USER_MISALIGNED_FIXUP=y
+
+#
+# Memory options
+#
+CONFIG_CACHED_MEMORY_OFFSET=0x20000000
+CONFIG_MEMORY_START=0x80000000
+CONFIG_MEMORY_SIZE_IN_MB=128
+
+#
+# Cache options
+#
+# CONFIG_DCACHE_DISABLED is not set
+CONFIG_DCACHE_WRITE_BACK=y
+# CONFIG_DCACHE_WRITE_THROUGH is not set
+# CONFIG_ICACHE_DISABLED is not set
+CONFIG_PCIDEVICE_MEMORY_START=C0000000
+CONFIG_DEVICE_MEMORY_START=E0000000
+CONFIG_FLASH_MEMORY_START=0x00000000
+CONFIG_PCI_BLOCK_START=0x40000000
+
+#
+# CPU Subtype specific options
+#
+CONFIG_SH64_ID2815_WORKAROUND=y
+
+#
+# Misc options
+#
+CONFIG_HEARTBEAT=y
+CONFIG_HDSP253_LED=y
+CONFIG_SH_DMA=y
+CONFIG_PREEMPT=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_QIC02_TAPE is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_SH_WDT is not set
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_E1355 is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+CONFIG_FB_KYRO=y
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_PCI_CONSOLE=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_SUPERH_MONO is not set
+# CONFIG_LOGO_SUPERH_VGA16 is not set
+CONFIG_LOGO_SUPERH_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+CONFIG_MINIX_FS=y
+CONFIG_ROMFS_FS=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_FAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+# CONFIG_OPROFILE is not set
+
+#
+# Kernel hacking
+#
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_DEBUG_KERNEL_WITH_GDB_STUB is not set
+# CONFIG_SH64_PROC_TLB is not set
+# CONFIG_SH64_PROC_ASIDS is not set
+CONFIG_SH64_SR_WATCH=y
+# CONFIG_SH_ALPHANUMERIC is not set
+# CONFIG_SH_NO_BSS_INIT is not set
+CONFIG_FRAME_POINTER=y
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh64/kernel/Makefile b/arch/sh64/kernel/Makefile
new file mode 100644 (file)
index 0000000..2f8d077
--- /dev/null
@@ -0,0 +1,38 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2000, 2001  Paolo Alberelli
+# Copyright (C) 2003  Paul Mundt
+#
+# Makefile for the Linux sh64 kernel.
+#
+# 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).
+#
+
+extra-y        := head.o init_task.o vmlinux.lds.s
+
+obj-y  := process.o signal.o entry.o traps.o irq.o irq_intc.o \
+          ptrace.o setup.o time.o sys_sh64.o semaphore.o sh_ksyms.o \
+          switchto.o syscalls.o
+
+obj-$(CONFIG_HEARTBEAT)                += led.o
+obj-$(CONFIG_SH_ALPHANUMERIC)  += alphanum.o
+obj-$(CONFIG_SH_DMA)           += dma.o
+obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
+obj-$(CONFIG_KALLSYMS)         += unwind.o
+obj-$(CONFIG_PCI)              += pci-dma.o pcibios.o
+
+ifeq ($(CONFIG_PCI),y)
+obj-$(CONFIG_CPU_SH5)          += pci_sh5.o
+endif
+
+ifndef CONFIG_NOFPU_SUPPORT
+obj-y                          += fpu.o
+endif
+
+USE_STANDARD_AS_RULE := true
+
diff --git a/arch/sh64/kernel/asm-offsets.c b/arch/sh64/kernel/asm-offsets.c
new file mode 100644 (file)
index 0000000..ca76537
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * This program is used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ */
+
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <asm/thread_info.h>
+
+#define DEFINE(sym, val) \
+        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
+int main(void)
+{
+       /* offsets into the thread_info struct */
+       DEFINE(TI_TASK,         offsetof(struct thread_info, task));
+       DEFINE(TI_EXEC_DOMAIN,  offsetof(struct thread_info, exec_domain));
+       DEFINE(TI_FLAGS,        offsetof(struct thread_info, flags));
+       DEFINE(TI_PRE_COUNT,    offsetof(struct thread_info, preempt_count));
+       DEFINE(TI_CPU,          offsetof(struct thread_info, cpu));
+       DEFINE(TI_ADDR_LIMIT,   offsetof(struct thread_info, addr_limit));
+       DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block));
+
+       return 0;
+}
diff --git a/arch/sh64/kernel/early_printk.c b/arch/sh64/kernel/early_printk.c
new file mode 100644 (file)
index 0000000..3d03ca7
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * arch/sh64/kernel/early_printk.c
+ *
+ * SH-5 Early SCIF console (cloned and hacked from sh implementation)
+ *
+ * Copyright (C) 2003, 2004  Paul Mundt <lethal@linux-sh.org>
+ * Copyright (C) 2002  M. R. Brown <mrbrown@0xd6.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/console.h>
+#include <linux/tty.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+extern void cpu_relax(void);
+
+#define SCIF_BASE_ADDR 0x01030000
+#define SCIF_ADDR_SH5  PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR
+
+/*
+ * Fixed virtual address where SCIF is mapped (should already be done
+ * in arch/sh64/kernel/head.S!).
+ */
+#define SCIF_REG       0xfa030000
+
+enum {
+       SCIF_SCSMR2     = SCIF_REG + 0x00,
+       SCIF_SCBRR2     = SCIF_REG + 0x04,
+       SCIF_SCSCR2     = SCIF_REG + 0x08,
+       SCIF_SCFTDR2    = SCIF_REG + 0x0c,
+       SCIF_SCFSR2     = SCIF_REG + 0x10,
+       SCIF_SCFRDR2    = SCIF_REG + 0x14,
+       SCIF_SCFCR2     = SCIF_REG + 0x18,
+       SCIF_SCFDR2     = SCIF_REG + 0x1c,
+       SCIF_SCSPTR2    = SCIF_REG + 0x20,
+       SCIF_SCLSR2     = SCIF_REG + 0x24,
+};
+
+static void sh_console_putc(int c)
+{
+       while (!(ctrl_inw(SCIF_SCFSR2) & 0x20))
+               cpu_relax();
+
+       ctrl_outb(c, SCIF_SCFTDR2);
+       ctrl_outw((ctrl_inw(SCIF_SCFSR2) & 0x9f), SCIF_SCFSR2);
+
+       if (c == '\n')
+               sh_console_putc('\r');
+}
+
+static void sh_console_flush(void)
+{
+       ctrl_outw((ctrl_inw(SCIF_SCFSR2) & 0xbf), SCIF_SCFSR2);
+
+       while (!(ctrl_inw(SCIF_SCFSR2) & 0x40))
+               cpu_relax();
+
+       ctrl_outw((ctrl_inw(SCIF_SCFSR2) & 0xbf), SCIF_SCFSR2);
+}
+
+static void sh_console_write(struct console *con, const char *s, unsigned count)
+{
+       while (count-- > 0)
+               sh_console_putc(*s++);
+
+       sh_console_flush();
+}
+
+static int __init sh_console_setup(struct console *con, char *options)
+{
+       con->cflag = CREAD | HUPCL | CLOCAL | B19200 | CS8;
+
+       return 0;
+}
+
+static struct console sh_console = {
+       .name           = "scifcon",
+       .write          = sh_console_write,
+       .setup          = sh_console_setup,
+       .flags          = CON_PRINTBUFFER,
+       .index          = -1,
+};
+
+void __init enable_early_printk(void)
+{
+       ctrl_outb(0x2a, SCIF_SCBRR2);   /* 19200bps */
+
+       ctrl_outw(0x04, SCIF_SCFCR2);   /* Reset TFRST */
+       ctrl_outw(0x10, SCIF_SCFCR2);   /* TTRG0=1 */
+
+       ctrl_outw(0, SCIF_SCSPTR2);
+       ctrl_outw(0x60, SCIF_SCFSR2);
+       ctrl_outw(0, SCIF_SCLSR2);
+       ctrl_outw(0x30, SCIF_SCSCR2);
+
+       register_console(&sh_console);
+}
+
+void disable_early_printk(void)
+{
+       unregister_console(&sh_console);
+}
+
diff --git a/arch/sh64/kernel/fpu.c b/arch/sh64/kernel/fpu.c
new file mode 100644 (file)
index 0000000..175c88a
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * arch/sh64/kernel/fpu.c
+ *
+ * Copyright (C) 2001  Manuela Cirronis, Paolo Alberelli
+ * Copyright (C) 2002  STMicroelectronics Limited
+ *   Author : Stuart Menefy
+ *
+ * Started from SH4 version:
+ *   Copyright (C) 1999, 2000  Kaz Kojima & Niibe Yutaka
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/processor.h>
+#include <asm/user.h>
+#include <asm/io.h>
+
+/*
+ * Initially load the FPU with signalling NANS.  This bit pattern
+ * has the property that no matter whether considered as single or as
+ * double precision, it still represents a signalling NAN.
+ */
+#define sNAN64         0xFFFFFFFFFFFFFFFFULL
+#define sNAN32         0xFFFFFFFFUL
+
+static union sh_fpu_union init_fpuregs = {
+       .hard = {
+         .fp_regs = { [0 ... 63] = sNAN32 },
+         .fpscr = FPSCR_INIT
+       }
+};
+
+inline void fpsave(struct sh_fpu_hard_struct *fpregs)
+{
+       asm volatile("fst.p     %0, (0*8), fp0\n\t"
+                    "fst.p     %0, (1*8), fp2\n\t"
+                    "fst.p     %0, (2*8), fp4\n\t"
+                    "fst.p     %0, (3*8), fp6\n\t"
+                    "fst.p     %0, (4*8), fp8\n\t"
+                    "fst.p     %0, (5*8), fp10\n\t"
+                    "fst.p     %0, (6*8), fp12\n\t"
+                    "fst.p     %0, (7*8), fp14\n\t"
+                    "fst.p     %0, (8*8), fp16\n\t"
+                    "fst.p     %0, (9*8), fp18\n\t"
+                    "fst.p     %0, (10*8), fp20\n\t"
+                    "fst.p     %0, (11*8), fp22\n\t"
+                    "fst.p     %0, (12*8), fp24\n\t"
+                    "fst.p     %0, (13*8), fp26\n\t"
+                    "fst.p     %0, (14*8), fp28\n\t"
+                    "fst.p     %0, (15*8), fp30\n\t"
+                    "fst.p     %0, (16*8), fp32\n\t"
+                    "fst.p     %0, (17*8), fp34\n\t"
+                    "fst.p     %0, (18*8), fp36\n\t"
+                    "fst.p     %0, (19*8), fp38\n\t"
+                    "fst.p     %0, (20*8), fp40\n\t"
+                    "fst.p     %0, (21*8), fp42\n\t"
+                    "fst.p     %0, (22*8), fp44\n\t"
+                    "fst.p     %0, (23*8), fp46\n\t"
+                    "fst.p     %0, (24*8), fp48\n\t"
+                    "fst.p     %0, (25*8), fp50\n\t"
+                    "fst.p     %0, (26*8), fp52\n\t"
+                    "fst.p     %0, (27*8), fp54\n\t"
+                    "fst.p     %0, (28*8), fp56\n\t"
+                    "fst.p     %0, (29*8), fp58\n\t"
+                    "fst.p     %0, (30*8), fp60\n\t"
+                    "fst.p     %0, (31*8), fp62\n\t"
+
+                    "fgetscr   fr63\n\t"
+                    "fst.s     %0, (32*8), fr63\n\t"
+               : /* no output */
+               : "r" (fpregs)
+               : "memory");
+}
+
+
+static inline void
+fpload(struct sh_fpu_hard_struct *fpregs)
+{
+       asm volatile("fld.p     %0, (0*8), fp0\n\t"
+                    "fld.p     %0, (1*8), fp2\n\t"
+                    "fld.p     %0, (2*8), fp4\n\t"
+                    "fld.p     %0, (3*8), fp6\n\t"
+                    "fld.p     %0, (4*8), fp8\n\t"
+                    "fld.p     %0, (5*8), fp10\n\t"
+                    "fld.p     %0, (6*8), fp12\n\t"
+                    "fld.p     %0, (7*8), fp14\n\t"
+                    "fld.p     %0, (8*8), fp16\n\t"
+                    "fld.p     %0, (9*8), fp18\n\t"
+                    "fld.p     %0, (10*8), fp20\n\t"
+                    "fld.p     %0, (11*8), fp22\n\t"
+                    "fld.p     %0, (12*8), fp24\n\t"
+                    "fld.p     %0, (13*8), fp26\n\t"
+                    "fld.p     %0, (14*8), fp28\n\t"
+                    "fld.p     %0, (15*8), fp30\n\t"
+                    "fld.p     %0, (16*8), fp32\n\t"
+                    "fld.p     %0, (17*8), fp34\n\t"
+                    "fld.p     %0, (18*8), fp36\n\t"
+                    "fld.p     %0, (19*8), fp38\n\t"
+                    "fld.p     %0, (20*8), fp40\n\t"
+                    "fld.p     %0, (21*8), fp42\n\t"
+                    "fld.p     %0, (22*8), fp44\n\t"
+                    "fld.p     %0, (23*8), fp46\n\t"
+                    "fld.p     %0, (24*8), fp48\n\t"
+                    "fld.p     %0, (25*8), fp50\n\t"
+                    "fld.p     %0, (26*8), fp52\n\t"
+                    "fld.p     %0, (27*8), fp54\n\t"
+                    "fld.p     %0, (28*8), fp56\n\t"
+                    "fld.p     %0, (29*8), fp58\n\t"
+                    "fld.p     %0, (30*8), fp60\n\t"
+
+                    "fld.s     %0, (32*8), fr63\n\t"
+                    "fputscr   fr63\n\t"
+
+                    "fld.p     %0, (31*8), fp62\n\t"
+               : /* no output */
+               : "r" (fpregs) );
+}
+
+void fpinit(struct sh_fpu_hard_struct *fpregs)
+{
+       *fpregs = init_fpuregs.hard;
+}
+
+asmlinkage void
+do_fpu_error(unsigned long ex, struct pt_regs *regs)
+{
+       struct task_struct *tsk = current;
+
+       regs->pc += 4;
+
+       tsk->thread.trap_no = 11;
+       tsk->thread.error_code = 0;
+       force_sig(SIGFPE, tsk);
+}
+
+
+asmlinkage void
+do_fpu_state_restore(unsigned long ex, struct pt_regs *regs)
+{
+       void die(const char *str, struct pt_regs *regs, long err);
+
+       if (! user_mode(regs))
+               die("FPU used in kernel", regs, ex);
+
+       regs->sr &= ~SR_FD;
+
+       if (last_task_used_math == current)
+               return;
+
+       grab_fpu();
+       if (last_task_used_math != NULL) {
+               /* Other processes fpu state, save away */
+               fpsave(&last_task_used_math->thread.fpu.hard);
+        }
+        last_task_used_math = current;
+        if (current->used_math) {
+                fpload(&current->thread.fpu.hard);
+        } else {
+               /* First time FPU user.  */
+               fpload(&init_fpuregs.hard);
+                current->used_math = 1;
+        }
+       release_fpu();
+}
+
diff --git a/arch/sh64/kernel/init_task.c b/arch/sh64/kernel/init_task.c
new file mode 100644 (file)
index 0000000..de2d07d
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * arch/sh64/kernel/init_task.c
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003  Paul Mundt
+ *
+ */
+#include <linux/rwsem.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/init_task.h>
+#include <linux/mqueue.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+struct mm_struct init_mm = INIT_MM(init_mm);
+
+struct pt_regs fake_swapper_regs;
+
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is THREAD_SIZE-byte aligned due
+ * to the way process stacks are handled. This is done by having a
+ * special "init_task" linker map entry..
+ */
+union thread_union init_thread_union
+       __attribute__((__section__(".data.init_task"))) =
+               { INIT_THREAD_INFO(init_task) };
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+
diff --git a/arch/sh64/kernel/pci-dma.c b/arch/sh64/kernel/pci-dma.c
new file mode 100644 (file)
index 0000000..a36c3d7
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
+ * Copyright (C) 2003 Paul Mundt (lethal@linux-sh.org)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Dynamic DMA mapping support.
+ */
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+void *consistent_alloc(struct pci_dev *hwdev, size_t size,
+                          dma_addr_t *dma_handle)
+{
+       void *ret;
+       int gfp = GFP_ATOMIC;
+        void *vp;
+
+       if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
+               gfp |= GFP_DMA;
+
+       ret = (void *)__get_free_pages(gfp, get_order(size));
+
+       /* now call our friend ioremap_nocache to give us an uncached area */
+        vp = ioremap_nocache(virt_to_phys(ret), size);
+
+       if (vp != NULL) {
+               memset(vp, 0, size);
+               *dma_handle = virt_to_bus(ret);
+               dma_cache_wback_inv((unsigned long)ret, size);
+       }
+
+       return vp;
+}
+
+void consistent_free(struct pci_dev *hwdev, size_t size,
+                        void *vaddr, dma_addr_t dma_handle)
+{
+       void *alloc;
+
+       alloc = bus_to_virt((unsigned long)dma_handle);
+       free_pages((unsigned long)alloc, get_order(size));
+
+       iounmap(vaddr);
+}
+
diff --git a/arch/sh64/kernel/pci_sh5.h b/arch/sh64/kernel/pci_sh5.h
new file mode 100644 (file)
index 0000000..8f21f5d
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Defintions for the SH5 PCI hardware.
+ */
+
+/* Product ID */
+#define PCISH5_PID             0x350d
+
+/* vendor ID */
+#define PCISH5_VID             0x1054
+
+/* Configuration types */
+#define ST_TYPE0                0x00    /* Configuration cycle type 0 */
+#define ST_TYPE1                0x01    /* Configuration cycle type 1 */
+
+/* VCR data */
+#define PCISH5_VCR_STATUS      0x00
+#define PCISH5_VCR_VERSION     0x08
+
+/*
+** ICR register offsets and bits
+*/
+#define PCISH5_ICR_CR          0x100   /* PCI control register values */
+#define CR_PBAM                 (1<<12)
+#define CR_PFCS                 (1<<11)
+#define CR_FTO                  (1<<10)
+#define CR_PFE                  (1<<9)
+#define CR_TBS                  (1<<8)
+#define CR_SPUE                 (1<<7)
+#define CR_BMAM                 (1<<6)
+#define CR_HOST                 (1<<5)
+#define CR_CLKEN                (1<<4)
+#define CR_SOCS                 (1<<3)
+#define CR_IOCS                 (1<<2)
+#define CR_RSTCTL               (1<<1)
+#define CR_CFINT                (1<<0)
+#define CR_LOCK_MASK            0xa5000000
+
+#define PCISH5_ICR_INT         0x114   /* Interrupt registert values     */
+#define INT_MADIM               (1<<2)
+
+#define PCISH5_ICR_LSR0        0X104   /* Local space register values    */
+#define PCISH5_ICR_LSR1        0X108   /* Local space register values    */
+#define PCISH5_ICR_LAR0        0x10c   /* Local address register values  */
+#define PCISH5_ICR_LAR1        0x110   /* Local address register values  */
+#define PCISH5_ICR_INTM        0x118   /* Interrupt mask register values                         */
+#define PCISH5_ICR_AIR         0x11c   /* Interrupt error address information register values    */
+#define PCISH5_ICR_CIR         0x120   /* Interrupt error command information register values    */
+#define PCISH5_ICR_AINT        0x130   /* Interrupt error arbiter interrupt register values      */
+#define PCISH5_ICR_AINTM       0x134   /* Interrupt error arbiter interrupt mask register values */
+#define PCISH5_ICR_BMIR        0x138   /* Interrupt error info register of bus master values     */
+#define PCISH5_ICR_PAR         0x1c0   /* Pio address register values                            */
+#define PCISH5_ICR_MBR         0x1c4   /* Memory space bank register values                      */
+#define PCISH5_ICR_IOBR        0x1c8   /* I/O space bank register values                         */
+#define PCISH5_ICR_PINT        0x1cc   /* power management interrupt register values             */
+#define PCISH5_ICR_PINTM       0x1d0   /* power management interrupt mask register values        */
+#define PCISH5_ICR_MBMR        0x1d8   /* memory space bank mask register values                 */
+#define PCISH5_ICR_IOBMR       0x1dc   /* I/O space bank mask register values                    */
+#define PCISH5_ICR_CSCR0       0x210   /* PCI cache snoop control register 0                     */
+#define PCISH5_ICR_CSCR1       0x214   /* PCI cache snoop control register 1                     */
+#define PCISH5_ICR_PDR         0x220   /* Pio data register values                               */
+
+/* These are configs space registers */
+#define PCISH5_ICR_CSR_VID     0x000   /* Vendor id                           */
+#define PCISH5_ICR_CSR_DID     0x002   /* Device id                           */
+#define PCISH5_ICR_CSR_CMD     0x004   /* Command register                    */
+#define PCISH5_ICR_CSR_STATUS  0x006   /* Stautus                             */
+#define PCISH5_ICR_CSR_IBAR0   0x010   /* I/O base address register           */
+#define PCISH5_ICR_CSR_MBAR0   0x014   /* First  Memory base address register */
+#define PCISH5_ICR_CSR_MBAR1   0x018   /* Second Memory base address register */
+
+
+
+/* Base address of registers */
+#define SH5PCI_ICR_BASE (PHYS_PCI_BLOCK + 0x00040000)
+#define SH5PCI_IO_BASE  (PHYS_PCI_BLOCK + 0x00800000)
+/* #define SH5PCI_VCR_BASE (P2SEG_PCICB_BLOCK + P2SEG)    */
+
+/* Register selection macro */
+#define PCISH5_ICR_REG(x)                ( pcicr_virt + (PCISH5_ICR_##x))
+/* #define PCISH5_VCR_REG(x)                ( SH5PCI_VCR_BASE (PCISH5_VCR_##x)) */
+
+/* Write I/O functions */
+#define SH5PCI_WRITE(reg,val)        ctrl_outl((u32)(val),PCISH5_ICR_REG(reg))
+#define SH5PCI_WRITE_SHORT(reg,val)  ctrl_outw((u16)(val),PCISH5_ICR_REG(reg))
+#define SH5PCI_WRITE_BYTE(reg,val)   ctrl_outb((u8)(val),PCISH5_ICR_REG(reg))
+
+/* Read I/O functions */
+#define SH5PCI_READ(reg)             ctrl_inl(PCISH5_ICR_REG(reg))
+#define SH5PCI_READ_SHORT(reg)       ctrl_inw(PCISH5_ICR_REG(reg))
+#define SH5PCI_READ_BYTE(reg)        ctrl_inb(PCISH5_ICR_REG(reg))
+
+/* Set PCI config bits */
+#define SET_CONFIG_BITS(bus,devfn,where)  ((((bus) << 16) | ((devfn) << 8) | ((where) & ~3)) | 0x80000000)
+
+/* Set PCI command register */
+#define CONFIG_CMD(bus, devfn, where)            SET_CONFIG_BITS(bus->number,devfn,where)
+
+/* Size converters */
+#define PCISH5_MEM_SIZCONV(x)            (((x / 0x40000) - 1) << 18)
+#define PCISH5_IO_SIZCONV(x)             (((x / 0x40000) - 1) << 18)
+
+
diff --git a/arch/sh64/kernel/semaphore.c b/arch/sh64/kernel/semaphore.c
new file mode 100644 (file)
index 0000000..72c1653
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Just taken from alpha implementation.
+ * This can't work well, perhaps.
+ */
+/*
+ *  Generic semaphore code. Buyer beware. Do your own
+ * specific changes in <asm/semaphore-helper.h>
+ */
+
+#include <linux/errno.h>
+#include <linux/rwsem.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/init.h>
+#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
+ * that tries to sleep, while the "waking" variable is
+ * incremented when the "up()" code goes to wake up waiting
+ * processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * waking_non_zero() (from asm/semaphore.h) must execute
+ * atomically.
+ *
+ * When __up() is called, the count was negative before
+ * incrementing it, and we need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to
+ * wake up and exit.  ALL waiting processes actually wake up but
+ * only the one that gets to the "waking" field first will gate
+ * through and acquire the semaphore.  The others will go back
+ * to sleep.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+void __up(struct semaphore *sem)
+{
+       wake_one_more(sem);
+       wake_up(&sem->wait);
+}
+
+/*
+ * Perform the "down" function.  Return zero for semaphore acquired,
+ * return negative for signalled out of the function.
+ *
+ * If called from __down, the return is ignored and the wait loop is
+ * not interruptible.  This means that a task waiting on a semaphore
+ * using "down()" cannot be killed until someone does an "up()" on
+ * the semaphore.
+ *
+ * If called from __down_interruptible, the return value gets checked
+ * upon return.  If the return value is negative then the task continues
+ * with the negative value in the return register (it can be tested by
+ * the caller).
+ *
+ * Either form may be used in conjunction with "up()".
+ *
+ */
+
+#define DOWN_VAR                               \
+       struct task_struct *tsk = current;      \
+       wait_queue_t wait;                      \
+       init_waitqueue_entry(&wait, tsk);
+
+#define DOWN_HEAD(task_state)                                          \
+                                                                       \
+                                                                       \
+       tsk->state = (task_state);                                      \
+       add_wait_queue(&sem->wait, &wait);                              \
+                                                                       \
+       /*                                                              \
+        * Ok, we're set up.  sem->count is known to be less than zero  \
+        * so we must wait.                                             \
+        *                                                              \
+        * We can let go the lock for purposes of waiting.              \
+        * We re-acquire it after awaking so as to protect              \
+        * all semaphore operations.                                    \
+        *                                                              \
+        * If "up()" is called before we call waking_non_zero() then    \
+        * we will catch it right away.  If it is called later then     \
+        * we will have to go through a wakeup cycle to catch it.       \
+        *                                                              \
+        * Multiple waiters contend for the semaphore lock to see       \
+        * who gets to gate through and who has to wait some more.      \
+        */                                                             \
+       for (;;) {
+
+#define DOWN_TAIL(task_state)                  \
+               tsk->state = (task_state);      \
+       }                                       \
+       tsk->state = TASK_RUNNING;              \
+       remove_wait_queue(&sem->wait, &wait);
+
+void __sched __down(struct semaphore * sem)
+{
+       DOWN_VAR
+       DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+       if (waking_non_zero(sem))
+               break;
+       schedule();
+       DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+}
+
+int __sched __down_interruptible(struct semaphore * sem)
+{
+       int ret = 0;
+       DOWN_VAR
+       DOWN_HEAD(TASK_INTERRUPTIBLE)
+
+       ret = waking_non_zero_interruptible(sem, tsk);
+       if (ret)
+       {
+               if (ret == 1)
+                       /* ret != 0 only if we get interrupted -arca */
+                       ret = 0;
+               break;
+       }
+       schedule();
+       DOWN_TAIL(TASK_INTERRUPTIBLE)
+       return ret;
+}
+
+int __down_trylock(struct semaphore * sem)
+{
+       return waking_non_zero_trylock(sem);
+}
diff --git a/arch/sh64/kernel/switchto.S b/arch/sh64/kernel/switchto.S
new file mode 100644 (file)
index 0000000..24ef14c
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * arch/sh64/kernel/switchto.S
+ *
+ * sh64 context switch
+ *
+ * Copyright (C) 2004  Richard Curnow
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+*/
+
+       .section .text..SHmedia32,"ax"
+       .little
+
+       .balign 32
+
+       .type sh64_switch_to,@function
+       .global sh64_switch_to
+       .global __sh64_switch_to_end
+sh64_switch_to:
+
+/* Incoming args
+   r2 - prev
+   r3 - &prev->thread
+   r4 - next
+   r5 - &next->thread
+
+   Outgoing results
+   r2 - last (=prev)
+
+   Want to create a full (struct pt_regs) on the stack to allow backtracing
+   functions to work.  However, we only need to populate the callee-save
+   register slots in this structure; since we're a function our ancestors must
+   have themselves preserved all caller saved state in the stack.  This saves
+   some wasted effort since we won't need to look at the values.
+
+   In particular, all caller-save registers are immediately available for
+   scratch use.
+
+*/
+
+#define FRAME_SIZE (76*8 + 8)
+
+       movi    FRAME_SIZE, r0
+       sub.l   r15, r0, r15
+       ! Do normal-style register save to support backtrace
+
+       st.l    r15,   0, r18   ! save link reg
+       st.l    r15,   4, r14   ! save fp
+       add.l   r15, r63, r14   ! setup frame pointer
+
+       ! hopefully this looks normal to the backtrace now.
+
+       addi.l  r15,   8, r1    ! base of pt_regs
+       addi.l  r1,   24, r0    ! base of pt_regs.regs
+       addi.l  r0, (63*8), r8  ! base of pt_regs.trregs
+
+       /* Note : to be fixed?
+          struct pt_regs is really designed for holding the state on entry
+          to an exception, i.e. pc,sr,regs etc.  However, for the context
+          switch state, some of this is not required.  But the unwinder takes
+          struct pt_regs * as an arg so we have to build this structure
+          to allow unwinding switched tasks in show_state() */
+
+       st.q    r0, ( 9*8), r9
+       st.q    r0, (10*8), r10
+       st.q    r0, (11*8), r11
+       st.q    r0, (12*8), r12
+       st.q    r0, (13*8), r13
+       st.q    r0, (14*8), r14 ! for unwind, want to look as though we took a trap at
+       ! the point where the process is left in suspended animation, i.e. current
+       ! fp here, not the saved one.
+       st.q    r0, (16*8), r16
+
+       st.q    r0, (24*8), r24
+       st.q    r0, (25*8), r25
+       st.q    r0, (26*8), r26
+       st.q    r0, (27*8), r27
+       st.q    r0, (28*8), r28
+       st.q    r0, (29*8), r29
+       st.q    r0, (30*8), r30
+       st.q    r0, (31*8), r31
+       st.q    r0, (32*8), r32
+       st.q    r0, (33*8), r33
+       st.q    r0, (34*8), r34
+       st.q    r0, (35*8), r35
+
+       st.q    r0, (44*8), r44
+       st.q    r0, (45*8), r45
+       st.q    r0, (46*8), r46
+       st.q    r0, (47*8), r47
+       st.q    r0, (48*8), r48
+       st.q    r0, (49*8), r49
+       st.q    r0, (50*8), r50
+       st.q    r0, (51*8), r51
+       st.q    r0, (52*8), r52
+       st.q    r0, (53*8), r53
+       st.q    r0, (54*8), r54
+       st.q    r0, (55*8), r55
+       st.q    r0, (56*8), r56
+       st.q    r0, (57*8), r57
+       st.q    r0, (58*8), r58
+       st.q    r0, (59*8), r59
+
+       ! do this early as pta->gettr has no pipeline forwarding (=> 5 cycle latency)
+       ! Use a local label to avoid creating a symbol that will confuse the !
+       ! backtrace
+       pta     .Lsave_pc, tr0
+
+       gettr   tr5, r45
+       gettr   tr6, r46
+       gettr   tr7, r47
+       st.q    r8, (5*8), r45
+       st.q    r8, (6*8), r46
+       st.q    r8, (7*8), r47
+
+       ! Now switch context
+       gettr   tr0, r9
+       st.l    r3, 0, r15      ! prev->thread.sp
+       st.l    r3, 8, r1       ! prev->thread.kregs
+       st.l    r3, 4, r9       ! prev->thread.pc
+       st.q    r1, 0, r9       ! save prev->thread.pc into pt_regs->pc
+
+       ! Load PC for next task (init value or save_pc later)
+       ld.l    r5, 4, r18      ! next->thread.pc
+       ! Switch stacks
+       ld.l    r5, 0, r15      ! next->thread.sp
+       ptabs   r18, tr0
+
+       ! Update current
+       ld.l    r4, 4, r9       ! next->thread_info (2nd element of next task_struct)
+       putcon  r9, kcr0        ! current = next->thread_info
+
+       ! go to save_pc for a reschedule, or the initial thread.pc for a new process
+       blink   tr0, r63
+
+       ! Restore (when we come back to a previously saved task)
+.Lsave_pc:
+       addi.l  r15, 32, r0     ! r0 = next's regs
+       addi.l  r0, (63*8), r8  ! r8 = next's tr_regs
+
+       ld.q    r8, (5*8), r45
+       ld.q    r8, (6*8), r46
+       ld.q    r8, (7*8), r47
+       ptabs   r45, tr5
+       ptabs   r46, tr6
+       ptabs   r47, tr7
+
+       ld.q    r0, ( 9*8), r9
+       ld.q    r0, (10*8), r10
+       ld.q    r0, (11*8), r11
+       ld.q    r0, (12*8), r12
+       ld.q    r0, (13*8), r13
+       ld.q    r0, (14*8), r14
+       ld.q    r0, (16*8), r16
+
+       ld.q    r0, (24*8), r24
+       ld.q    r0, (25*8), r25
+       ld.q    r0, (26*8), r26
+       ld.q    r0, (27*8), r27
+       ld.q    r0, (28*8), r28
+       ld.q    r0, (29*8), r29
+       ld.q    r0, (30*8), r30
+       ld.q    r0, (31*8), r31
+       ld.q    r0, (32*8), r32
+       ld.q    r0, (33*8), r33
+       ld.q    r0, (34*8), r34
+       ld.q    r0, (35*8), r35
+
+       ld.q    r0, (44*8), r44
+       ld.q    r0, (45*8), r45
+       ld.q    r0, (46*8), r46
+       ld.q    r0, (47*8), r47
+       ld.q    r0, (48*8), r48
+       ld.q    r0, (49*8), r49
+       ld.q    r0, (50*8), r50
+       ld.q    r0, (51*8), r51
+       ld.q    r0, (52*8), r52
+       ld.q    r0, (53*8), r53
+       ld.q    r0, (54*8), r54
+       ld.q    r0, (55*8), r55
+       ld.q    r0, (56*8), r56
+       ld.q    r0, (57*8), r57
+       ld.q    r0, (58*8), r58
+       ld.q    r0, (59*8), r59
+
+       ! epilogue
+       ld.l    r15, 0, r18
+       ld.l    r15, 4, r14
+       ori     r4, 0, r2       ! last = prev
+       ptabs   r18, tr0
+       movi    FRAME_SIZE, r0
+       add     r15, r0, r15
+       blink   tr0, r63
+__sh64_switch_to_end:
+.LFE1:
+       .size   sh64_switch_to,.LFE1-sh64_switch_to
+
diff --git a/arch/sh64/kernel/syscalls.S b/arch/sh64/kernel/syscalls.S
new file mode 100644 (file)
index 0000000..819e335
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ * arch/sh64/kernel/syscalls.S
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2004  Paul Mundt
+ * Copyright (C) 2003, 2004 Richard Curnow
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/sys.h>
+
+       .section .data, "aw"
+       .balign 32
+
+/*
+ * System calls jump table
+ */
+       .globl  sys_call_table
+sys_call_table:
+       .long sys_ni_syscall            /* 0  -  old "setup()" system call  */
+       .long sys_exit
+       .long sys_fork
+       .long sys_read
+       .long sys_write
+       .long sys_open                  /* 5 */
+       .long sys_close
+       .long sys_waitpid
+       .long sys_creat
+       .long sys_link
+       .long sys_unlink                /* 10 */
+       .long sys_execve
+       .long sys_chdir
+       .long sys_time
+       .long sys_mknod
+       .long sys_chmod                 /* 15 */
+       .long sys_lchown16
+       .long sys_ni_syscall    /* old break syscall holder */
+       .long sys_stat
+       .long sys_lseek
+       .long sys_getpid                /* 20 */
+       .long sys_mount
+       .long sys_oldumount
+       .long sys_setuid16
+       .long sys_getuid16
+       .long sys_stime                 /* 25 */
+       .long sys_ptrace
+       .long sys_alarm
+       .long sys_fstat
+       .long sys_pause
+       .long sys_utime                 /* 30 */
+       .long sys_ni_syscall    /* old stty syscall holder */
+       .long sys_ni_syscall    /* old gtty syscall holder */
+       .long sys_access
+       .long sys_nice
+       .long sys_ni_syscall            /* 35 */ /* old ftime syscall holder */
+       .long sys_sync
+       .long sys_kill
+       .long sys_rename
+       .long sys_mkdir
+       .long sys_rmdir                 /* 40 */
+       .long sys_dup
+       .long sys_pipe
+       .long sys_times
+       .long sys_ni_syscall    /* old prof syscall holder */
+       .long sys_brk                   /* 45 */
+       .long sys_setgid16
+       .long sys_getgid16
+       .long sys_signal
+       .long sys_geteuid16
+       .long sys_getegid16             /* 50 */
+       .long sys_acct
+       .long sys_umount                /* recycled never used phys( */
+       .long sys_ni_syscall    /* old lock syscall holder */
+       .long sys_ioctl
+       .long sys_fcntl                 /* 55 */
+       .long sys_ni_syscall    /* old mpx syscall holder */
+       .long sys_setpgid
+       .long sys_ni_syscall    /* old ulimit syscall holder */
+       .long sys_ni_syscall    /* sys_olduname */
+       .long sys_umask                 /* 60 */
+       .long sys_chroot
+       .long sys_ustat
+       .long sys_dup2
+       .long sys_getppid
+       .long sys_getpgrp               /* 65 */
+       .long sys_setsid
+       .long sys_sigaction
+       .long sys_sgetmask
+       .long sys_ssetmask
+       .long sys_setreuid16            /* 70 */
+       .long sys_setregid16
+       .long sys_sigsuspend
+       .long sys_sigpending
+       .long sys_sethostname
+       .long sys_setrlimit             /* 75 */
+       .long sys_old_getrlimit
+       .long sys_getrusage
+       .long sys_gettimeofday
+       .long sys_settimeofday
+       .long sys_getgroups16           /* 80 */
+       .long sys_setgroups16
+       .long sys_ni_syscall    /* sys_oldselect */
+       .long sys_symlink
+       .long sys_lstat
+       .long sys_readlink              /* 85 */
+       .long sys_uselib
+       .long sys_swapon
+       .long sys_reboot
+       .long old_readdir
+       .long old_mmap                  /* 90 */
+       .long sys_munmap
+       .long sys_truncate
+       .long sys_ftruncate
+       .long sys_fchmod
+       .long sys_fchown16              /* 95 */
+       .long sys_getpriority
+       .long sys_setpriority
+       .long sys_ni_syscall    /* old profil syscall holder */
+       .long sys_statfs
+       .long sys_fstatfs               /* 100 */
+       .long sys_ni_syscall    /* ioperm */
+       .long sys_socketcall    /* Obsolete implementation of socket syscall */
+       .long sys_syslog
+       .long sys_setitimer
+       .long sys_getitimer             /* 105 */
+       .long sys_newstat
+       .long sys_newlstat
+       .long sys_newfstat
+       .long sys_uname
+       .long sys_ni_syscall            /* 110 */ /* iopl */
+       .long sys_vhangup
+       .long sys_ni_syscall    /* idle */
+       .long sys_ni_syscall    /* vm86old */
+       .long sys_wait4
+       .long sys_swapoff               /* 115 */
+       .long sys_sysinfo
+       .long sys_ipc           /* Obsolete ipc syscall implementation */
+       .long sys_fsync
+       .long sys_sigreturn
+       .long sys_clone                 /* 120 */
+       .long sys_setdomainname
+       .long sys_newuname
+       .long sys_ni_syscall    /* sys_modify_ldt */
+       .long sys_adjtimex
+       .long sys_mprotect              /* 125 */
+       .long sys_sigprocmask
+       .long sys_ni_syscall            /* old "create_module" */
+       .long sys_init_module
+       .long sys_delete_module
+       .long sys_ni_syscall            /* 130: old "get_kernel_syms" */
+       .long sys_quotactl
+       .long sys_getpgid
+       .long sys_fchdir
+       .long sys_bdflush
+       .long sys_sysfs                 /* 135 */
+       .long sys_personality
+       .long sys_ni_syscall    /* for afs_syscall */
+       .long sys_setfsuid16
+       .long sys_setfsgid16
+       .long sys_llseek                /* 140 */
+       .long sys_getdents
+       .long sys_select
+       .long sys_flock
+       .long sys_msync
+       .long sys_readv                 /* 145 */
+       .long sys_writev
+       .long sys_getsid
+       .long sys_fdatasync
+       .long sys_sysctl
+       .long sys_mlock                 /* 150 */
+       .long sys_munlock
+       .long sys_mlockall
+       .long sys_munlockall
+       .long sys_sched_setparam
+       .long sys_sched_getparam        /* 155 */
+       .long sys_sched_setscheduler
+       .long sys_sched_getscheduler
+       .long sys_sched_yield
+       .long sys_sched_get_priority_max
+       .long sys_sched_get_priority_min  /* 160 */
+       .long sys_sched_rr_get_interval
+       .long sys_nanosleep
+       .long sys_mremap
+       .long sys_setresuid16
+       .long sys_getresuid16           /* 165 */
+       .long sys_ni_syscall    /* vm86 */
+       .long sys_ni_syscall    /* old "query_module" */
+       .long sys_poll
+       .long sys_nfsservctl
+       .long sys_setresgid16           /* 170 */
+       .long sys_getresgid16
+       .long sys_prctl
+       .long sys_rt_sigreturn
+       .long sys_rt_sigaction
+       .long sys_rt_sigprocmask        /* 175 */
+       .long sys_rt_sigpending
+       .long sys_rt_sigtimedwait
+       .long sys_rt_sigqueueinfo
+       .long sys_rt_sigsuspend
+       .long sys_pread64               /* 180 */
+       .long sys_pwrite64
+       .long sys_chown16
+       .long sys_getcwd
+       .long sys_capget
+       .long sys_capset                /* 185 */
+       .long sys_sigaltstack
+       .long sys_sendfile
+       .long sys_ni_syscall    /* streams1 */
+       .long sys_ni_syscall    /* streams2 */
+       .long sys_vfork                 /* 190 */
+       .long sys_getrlimit
+       .long sys_mmap2
+       .long sys_truncate64
+       .long sys_ftruncate64
+       .long sys_stat64                /* 195 */
+       .long sys_lstat64
+       .long sys_fstat64
+       .long sys_lchown
+       .long sys_getuid
+       .long sys_getgid                /* 200 */
+       .long sys_geteuid
+       .long sys_getegid
+       .long sys_setreuid
+       .long sys_setregid
+       .long sys_getgroups             /* 205 */
+       .long sys_setgroups
+       .long sys_fchown
+       .long sys_setresuid
+       .long sys_getresuid
+       .long sys_setresgid             /* 210 */
+       .long sys_getresgid
+       .long sys_chown
+       .long sys_setuid
+       .long sys_setgid
+       .long sys_setfsuid              /* 215 */
+       .long sys_setfsgid
+       .long sys_pivot_root
+       .long sys_mincore
+       .long sys_madvise
+       /* Broken-out socket family (maintain backwards compatibility in syscall
+          numbering with 2.4) */
+       .long sys_socket                /* 220 */
+       .long sys_bind
+       .long sys_connect
+       .long sys_listen
+       .long sys_accept
+       .long sys_getsockname           /* 225 */
+       .long sys_getpeername
+       .long sys_socketpair
+       .long sys_send
+       .long sys_sendto
+       .long sys_recv                  /* 230*/
+       .long sys_recvfrom
+       .long sys_shutdown
+       .long sys_setsockopt
+       .long sys_getsockopt
+       .long sys_sendmsg               /* 235 */
+       .long sys_recvmsg
+       /* Broken-out IPC family (maintain backwards compatibility in syscall
+          numbering with 2.4) */
+       .long sys_semop
+       .long sys_semget
+       .long sys_semctl
+       .long sys_msgsnd                /* 240 */
+       .long sys_msgrcv
+       .long sys_msgget
+       .long sys_msgctl
+       .long sys_ni_syscall /* sys_shmatcall */
+       .long sys_shmdt                 /* 245 */
+       .long sys_shmget
+       .long sys_shmctl
+       /* Rest of syscalls listed in 2.4 i386 unistd.h */
+       .long sys_getdents64
+       .long sys_fcntl64
+       .long sys_ni_syscall            /* 250 reserved for TUX */
+       .long sys_ni_syscall            /* Reserved for Security */
+       .long sys_gettid
+       .long sys_readahead
+       .long sys_setxattr
+       .long sys_lsetxattr             /* 255 */
+       .long sys_fsetxattr
+       .long sys_getxattr
+       .long sys_lgetxattr
+       .long sys_fgetxattr
+       .long sys_listxattr             /* 260 */
+       .long sys_llistxattr
+       .long sys_flistxattr
+       .long sys_removexattr
+       .long sys_lremovexattr
+       .long sys_fremovexattr          /* 265 */
+       .long sys_tkill
+       .long sys_sendfile64
+       .long sys_futex
+       .long sys_sched_setaffinity
+       .long sys_sched_getaffinity     /* 270 */
+       .long sys_ni_syscall
+       .long sys_ni_syscall
+       .long sys_io_setup
+       .long sys_io_destroy
+       .long sys_io_getevents          /* 275 */
+       .long sys_io_submit
+       .long sys_io_cancel
+       .long sys_fadvise64
+       .long sys_ni_syscall
+       .long sys_exit_group            /* 280 */
+       /* Rest of new 2.6 syscalls */
+       .long sys_lookup_dcookie
+       .long sys_epoll_create
+       .long sys_epoll_ctl
+       .long sys_epoll_wait
+       .long sys_remap_file_pages      /* 285 */
+       .long sys_set_tid_address
+       .long sys_timer_create
+       .long sys_timer_settime
+       .long sys_timer_gettime
+       .long sys_timer_getoverrun      /* 290 */
+       .long sys_timer_delete
+       .long sys_clock_settime
+       .long sys_clock_gettime
+       .long sys_clock_getres
+       .long sys_clock_nanosleep       /* 295 */
+       .long sys_statfs64
+       .long sys_fstatfs64
+       .long sys_tgkill
+       .long sys_utimes
+       .long sys_fadvise64_64          /* 300 */
+       .long sys_ni_syscall    /* Reserved for vserver */
+       .long sys_ni_syscall    /* Reserved for mbind */
+       .long sys_ni_syscall    /* get_mempolicy */
+       .long sys_ni_syscall    /* set_mempolicy */
+       .long sys_mq_open               /* 305 */
+       .long sys_mq_unlink
+       .long sys_mq_timedsend
+       .long sys_mq_timedreceive
+       .long sys_mq_notify
+       .long sys_mq_getsetattr         /* 310 */
+
diff --git a/arch/sh64/kernel/traps.c b/arch/sh64/kernel/traps.c
new file mode 100644 (file)
index 0000000..b2b2bde
--- /dev/null
@@ -0,0 +1,958 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * arch/sh64/kernel/traps.c
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003, 2004  Paul Mundt
+ * Copyright (C) 2003, 2004  Richard Curnow
+ *
+ */
+
+/*
+ * 'Traps.c' handles hardware traps and faults after we have saved some
+ * state in 'entry.S'.
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/kallsyms.h>
+#include <linux/interrupt.h>
+#include <linux/sysctl.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/processor.h>
+#include <asm/pgtable.h>
+
+#undef DEBUG_EXCEPTION
+#ifdef DEBUG_EXCEPTION
+/* implemented in ../lib/dbg.c */
+extern void show_excp_regs(char *fname, int trapnr, int signr,
+                          struct pt_regs *regs);
+#else
+#define show_excp_regs(a, b, c, d)
+#endif
+
+static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name,
+               unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk);
+
+#define DO_ERROR(trapnr, signr, str, name, tsk) \
+asmlinkage void do_##name(unsigned long error_code, struct pt_regs *regs) \
+{ \
+       do_unhandled_exception(trapnr, signr, str, __stringify(name), error_code, regs, current); \
+}
+
+spinlock_t die_lock;
+
+void die(const char * str, struct pt_regs * regs, long err)
+{
+       console_verbose();
+       spin_lock_irq(&die_lock);
+       printk("%s: %lx\n", str, (err & 0xffffff));
+       show_regs(regs);
+       spin_unlock_irq(&die_lock);
+       do_exit(SIGSEGV);
+}
+
+static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
+{
+       if (!user_mode(regs))
+               die(str, regs, err);
+}
+
+static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
+{
+       if (!user_mode(regs)) {
+               const struct exception_table_entry *fixup;
+               fixup = search_exception_tables(regs->pc);
+               if (fixup) {
+                       regs->pc = fixup->fixup;
+                       return;
+               }
+               die(str, regs, err);
+       }
+}
+
+DO_ERROR(13, SIGILL,  "illegal slot instruction", illegal_slot_inst, current)
+DO_ERROR(87, SIGSEGV, "address error (exec)", address_error_exec, current)
+
+
+/* Implement misaligned load/store handling for kernel (and optionally for user
+   mode too).  Limitation : only SHmedia mode code is handled - there is no
+   handling at all for misaligned accesses occurring in SHcompact code yet. */
+
+static int misaligned_fixup(struct pt_regs *regs);
+
+asmlinkage void do_address_error_load(unsigned long error_code, struct pt_regs *regs)
+{
+       if (misaligned_fixup(regs) < 0) {
+               do_unhandled_exception(7, SIGSEGV, "address error(load)",
+                               "do_address_error_load",
+                               error_code, regs, current);
+       }
+       return;
+}
+
+asmlinkage void do_address_error_store(unsigned long error_code, struct pt_regs *regs)
+{
+       if (misaligned_fixup(regs) < 0) {
+               do_unhandled_exception(8, SIGSEGV, "address error(store)",
+                               "do_address_error_store",
+                               error_code, regs, current);
+       }
+       return;
+}
+
+#if defined(CONFIG_SH64_ID2815_WORKAROUND)
+
+#define OPCODE_INVALID      0
+#define OPCODE_USER_VALID   1
+#define OPCODE_PRIV_VALID   2
+
+/* getcon/putcon - requires checking which control register is referenced. */
+#define OPCODE_CTRL_REG     3
+
+/* Table of valid opcodes for SHmedia mode.
+   Form a 10-bit value by concatenating the major/minor opcodes i.e.
+   opcode[31:26,20:16].  The 6 MSBs of this value index into the following
+   array.  The 4 LSBs select the bit-pair in the entry (bits 1:0 correspond to
+   LSBs==4'b0000 etc). */
+static unsigned long shmedia_opcode_table[64] = {
+       0x55554044,0x54445055,0x15141514,0x14541414,0x00000000,0x10001000,0x01110055,0x04050015,
+       0x00000444,0xc0000000,0x44545515,0x40405555,0x55550015,0x10005555,0x55555505,0x04050000,
+       0x00000555,0x00000404,0x00040445,0x15151414,0x00000000,0x00000000,0x00000000,0x00000000,
+       0x00000055,0x40404444,0x00000404,0xc0009495,0x00000000,0x00000000,0x00000000,0x00000000,
+       0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,
+       0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,
+       0x80005050,0x04005055,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,
+       0x81055554,0x00000404,0x55555555,0x55555555,0x00000000,0x00000000,0x00000000,0x00000000
+};
+
+void do_reserved_inst(unsigned long error_code, struct pt_regs *regs)
+{
+       /* Workaround SH5-101 cut2 silicon defect #2815 :
+          in some situations, inter-mode branches from SHcompact -> SHmedia
+          which should take ITLBMISS or EXECPROT exceptions at the target
+          falsely take RESINST at the target instead. */
+
+       unsigned long opcode = 0x6ff4fff0; /* guaranteed reserved opcode */
+       unsigned long pc, aligned_pc;
+       int get_user_error;
+       int trapnr = 12;
+       int signr = SIGILL;
+       char *exception_name = "reserved_instruction";
+
+       pc = regs->pc;
+       if ((pc & 3) == 1) {
+               /* SHmedia : check for defect.  This requires executable vmas
+                  to be readable too. */
+               aligned_pc = pc & ~3;
+               if (!access_ok(VERIFY_READ, aligned_pc, sizeof(unsigned long))) {
+                       get_user_error = -EFAULT;
+               } else {
+                       get_user_error = __get_user(opcode, (unsigned long *)aligned_pc);
+               }
+               if (get_user_error >= 0) {
+                       unsigned long index, shift;
+                       unsigned long major, minor, combined;
+                       unsigned long reserved_field;
+                       reserved_field = opcode & 0xf; /* These bits are currently reserved as zero in all valid opcodes */
+                       major = (opcode >> 26) & 0x3f;
+                       minor = (opcode >> 16) & 0xf;
+                       combined = (major << 4) | minor;
+                       index = major;
+                       shift = minor << 1;
+                       if (reserved_field == 0) {
+                               int opcode_state = (shmedia_opcode_table[index] >> shift) & 0x3;
+                               switch (opcode_state) {
+                                       case OPCODE_INVALID:
+                                               /* Trap. */
+                                               break;
+                                       case OPCODE_USER_VALID:
+                                               /* Restart the instruction : the branch to the instruction will now be from an RTE
+                                                  not from SHcompact so the silicon defect won't be triggered. */
+                                               return;
+                                       case OPCODE_PRIV_VALID:
+                                               if (!user_mode(regs)) {
+                                                       /* Should only ever get here if a module has
+                                                          SHcompact code inside it.  If so, the same fix up is needed. */
+                                                       return; /* same reason */
+                                               }
+                                               /* Otherwise, user mode trying to execute a privileged instruction -
+                                                  fall through to trap. */
+                                               break;
+                                       case OPCODE_CTRL_REG:
+                                               /* If in privileged mode, return as above. */
+                                               if (!user_mode(regs)) return;
+                                               /* In user mode ... */
+                                               if (combined == 0x9f) { /* GETCON */
+                                                       unsigned long regno = (opcode >> 20) & 0x3f;
+                                                       if (regno >= 62) {
+                                                               return;
+                                                       }
+                                                       /* Otherwise, reserved or privileged control register, => trap */
+                                               } else if (combined == 0x1bf) { /* PUTCON */
+                                                       unsigned long regno = (opcode >> 4) & 0x3f;
+                                                       if (regno >= 62) {
+                                                               return;
+                                                       }
+                                                       /* Otherwise, reserved or privileged control register, => trap */
+                                               } else {
+                                                       /* Trap */
+                                               }
+                                               break;
+                                       default:
+                                               /* Fall through to trap. */
+                                               break;
+                               }
+                       }
+                       /* fall through to normal resinst processing */
+               } else {
+                       /* Error trying to read opcode.  This typically means a
+                          real fault, not a RESINST any more.  So change the
+                          codes. */
+                       trapnr = 87;
+                       exception_name = "address error (exec)";
+                       signr = SIGSEGV;
+               }
+       }
+
+       do_unhandled_exception(trapnr, signr, exception_name, "do_reserved_inst", error_code, regs, current);
+}
+
+#else /* CONFIG_SH64_ID2815_WORKAROUND */
+
+/* If the workaround isn't needed, this is just a straightforward reserved
+   instruction */
+DO_ERROR(12, SIGILL,  "reserved instruction", reserved_inst, current)
+
+#endif /* CONFIG_SH64_ID2815_WORKAROUND */
+
+
+#include <asm/system.h>
+
+/* Called with interrupts disabled */
+asmlinkage void do_exception_error(unsigned long ex, struct pt_regs *regs)
+{
+       PLS();
+       show_excp_regs(__FUNCTION__, -1, -1, regs);
+       die_if_kernel("exception", regs, ex);
+}
+
+int do_unknown_trapa(unsigned long scId, struct pt_regs *regs)
+{
+       /* Syscall debug */
+        printk("System call ID error: [0x1#args:8 #syscall:16  0x%lx]\n", scId);
+
+       die_if_kernel("unknown trapa", regs, scId);
+
+       return -ENOSYS;
+}
+
+void show_stack(struct task_struct *tsk, unsigned long *sp)
+{
+#ifdef CONFIG_KALLSYMS
+       extern void sh64_unwind(struct pt_regs *regs);
+       struct pt_regs *regs;
+
+       regs = tsk ? tsk->thread.kregs : NULL;
+
+       sh64_unwind(regs);
+#else
+       printk(KERN_ERR "Can't backtrace on sh64 without CONFIG_KALLSYMS\n");
+#endif
+}
+
+void show_task(unsigned long *sp)
+{
+       show_stack(NULL, sp);
+}
+
+void dump_stack(void)
+{
+       show_task(NULL);
+}
+
+static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name,
+               unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk)
+{
+       show_excp_regs(fn_name, trapnr, signr, regs);
+       tsk->thread.error_code = error_code;
+       tsk->thread.trap_no = trapnr;
+
+       if (user_mode(regs))
+               force_sig(signr, tsk);
+
+       die_if_no_fixup(str, regs, error_code);
+}
+
+static int read_opcode(unsigned long long pc, unsigned long *result_opcode, int from_user_mode)
+{
+       int get_user_error;
+       unsigned long aligned_pc;
+       unsigned long opcode;
+
+       if ((pc & 3) == 1) {
+               /* SHmedia */
+               aligned_pc = pc & ~3;
+               if (from_user_mode) {
+                       if (!access_ok(VERIFY_READ, aligned_pc, sizeof(unsigned long))) {
+                               get_user_error = -EFAULT;
+                       } else {
+                               get_user_error = __get_user(opcode, (unsigned long *)aligned_pc);
+                               *result_opcode = opcode;
+                       }
+                       return get_user_error;
+               } else {
+                       /* If the fault was in the kernel, we can either read
+                        * this directly, or if not, we fault.
+                       */
+                       *result_opcode = *(unsigned long *) aligned_pc;
+                       return 0;
+               }
+       } else if ((pc & 1) == 0) {
+               /* SHcompact */
+               /* TODO : provide handling for this.  We don't really support
+                  user-mode SHcompact yet, and for a kernel fault, this would
+                  have to come from a module built for SHcompact.  */
+               return -EFAULT;
+       } else {
+               /* misaligned */
+               return -EFAULT;
+       }
+}
+
+static int address_is_sign_extended(__u64 a)
+{
+       __u64 b;
+#if (NEFF == 32)
+       b = (__u64)(__s64)(__s32)(a & 0xffffffffUL);
+       return (b == a) ? 1 : 0;
+#else
+#error "Sign extend check only works for NEFF==32"
+#endif
+}
+
+static int generate_and_check_address(struct pt_regs *regs,
+                                     __u32 opcode,
+                                     int displacement_not_indexed,
+                                     int width_shift,
+                                     __u64 *address)
+{
+       /* return -1 for fault, 0 for OK */
+
+       __u64 base_address, addr;
+       int basereg;
+
+       basereg = (opcode >> 20) & 0x3f;
+       base_address = regs->regs[basereg];
+       if (displacement_not_indexed) {
+               __s64 displacement;
+               displacement = (opcode >> 10) & 0x3ff;
+               displacement = ((displacement << 54) >> 54); /* sign extend */
+               addr = (__u64)((__s64)base_address + (displacement << width_shift));
+       } else {
+               __u64 offset;
+               int offsetreg;
+               offsetreg = (opcode >> 10) & 0x3f;
+               offset = regs->regs[offsetreg];
+               addr = base_address + offset;
+       }
+
+       /* Check sign extended */
+       if (!address_is_sign_extended(addr)) {
+               return -1;
+       }
+
+#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
+       /* Check accessible.  For misaligned access in the kernel, assume the
+          address is always accessible (and if not, just fault when the
+          load/store gets done.) */
+       if (user_mode(regs)) {
+               if (addr >= TASK_SIZE) {
+                       return -1;
+               }
+               /* Do access_ok check later - it depends on whether it's a load or a store. */
+       }
+#endif
+
+       *address = addr;
+       return 0;
+}
+
+/* Default value as for sh */
+#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
+static int user_mode_unaligned_fixup_count = 10;
+static int user_mode_unaligned_fixup_enable = 1;
+#endif
+
+static int kernel_mode_unaligned_fixup_count = 32;
+
+static void misaligned_kernel_word_load(__u64 address, int do_sign_extend, __u64 *result)
+{
+       unsigned short x;
+       unsigned char *p, *q;
+       p = (unsigned char *) (int) address;
+       q = (unsigned char *) &x;
+       q[0] = p[0];
+       q[1] = p[1];
+
+       if (do_sign_extend) {
+               *result = (__u64)(__s64) *(short *) &x;
+       } else {
+               *result = (__u64) x;
+       }
+}
+
+static void misaligned_kernel_word_store(__u64 address, __u64 value)
+{
+       unsigned short x;
+       unsigned char *p, *q;
+       p = (unsigned char *) (int) address;
+       q = (unsigned char *) &x;
+
+       x = (__u16) value;
+       p[0] = q[0];
+       p[1] = q[1];
+}
+
+static int misaligned_load(struct pt_regs *regs,
+                          __u32 opcode,
+                          int displacement_not_indexed,
+                          int width_shift,
+                          int do_sign_extend)
+{
+       /* Return -1 for a fault, 0 for OK */
+       int error;
+       int destreg;
+       __u64 address;
+
+       error = generate_and_check_address(regs, opcode,
+                       displacement_not_indexed, width_shift, &address);
+       if (error < 0) {
+               return error;
+       }
+
+       destreg = (opcode >> 4) & 0x3f;
+#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
+       if (user_mode(regs)) {
+               __u64 buffer;
+
+               if (!access_ok(VERIFY_READ, (unsigned long) address, 1UL<<width_shift)) {
+                       return -1;
+               }
+
+               if (__copy_user(&buffer, (const void *)(int)address, (1 << width_shift)) > 0) {
+                       return -1; /* fault */
+               }
+               switch (width_shift) {
+               case 1:
+                       if (do_sign_extend) {
+                               regs->regs[destreg] = (__u64)(__s64) *(__s16 *) &buffer;
+                       } else {
+                               regs->regs[destreg] = (__u64) *(__u16 *) &buffer;
+                       }
+                       break;
+               case 2:
+                       regs->regs[destreg] = (__u64)(__s64) *(__s32 *) &buffer;
+                       break;
+               case 3:
+                       regs->regs[destreg] = buffer;
+                       break;
+               default:
+                       printk("Unexpected width_shift %d in misaligned_load, PC=%08lx\n",
+                               width_shift, (unsigned long) regs->pc);
+                       break;
+               }
+       } else
+#endif
+       {
+               /* kernel mode - we can take short cuts since if we fault, it's a genuine bug */
+               __u64 lo, hi;
+
+               switch (width_shift) {
+               case 1:
+                       misaligned_kernel_word_load(address, do_sign_extend, &regs->regs[destreg]);
+                       break;
+               case 2:
+                       asm ("ldlo.l %1, 0, %0" : "=r" (lo) : "r" (address));
+                       asm ("ldhi.l %1, 3, %0" : "=r" (hi) : "r" (address));
+                       regs->regs[destreg] = lo | hi;
+                       break;
+               case 3:
+                       asm ("ldlo.q %1, 0, %0" : "=r" (lo) : "r" (address));
+                       asm ("ldhi.q %1, 7, %0" : "=r" (hi) : "r" (address));
+                       regs->regs[destreg] = lo | hi;
+                       break;
+
+               default:
+                       printk("Unexpected width_shift %d in misaligned_load, PC=%08lx\n",
+                               width_shift, (unsigned long) regs->pc);
+                       break;
+               }
+       }
+
+       return 0;
+
+}
+
+static int misaligned_store(struct pt_regs *regs,
+                           __u32 opcode,
+                           int displacement_not_indexed,
+                           int width_shift)
+{
+       /* Return -1 for a fault, 0 for OK */
+       int error;
+       int srcreg;
+       __u64 address;
+
+       error = generate_and_check_address(regs, opcode,
+                       displacement_not_indexed, width_shift, &address);
+       if (error < 0) {
+               return error;
+       }
+
+       srcreg = (opcode >> 4) & 0x3f;
+#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
+       if (user_mode(regs)) {
+               __u64 buffer;
+
+               if (!access_ok(VERIFY_WRITE, (unsigned long) address, 1UL<<width_shift)) {
+                       return -1;
+               }
+
+               switch (width_shift) {
+               case 1:
+                       *(__u16 *) &buffer = (__u16) regs->regs[srcreg];
+                       break;
+               case 2:
+                       *(__u32 *) &buffer = (__u32) regs->regs[srcreg];
+                       break;
+               case 3:
+                       buffer = regs->regs[srcreg];
+                       break;
+               default:
+                       printk("Unexpected width_shift %d in misaligned_store, PC=%08lx\n",
+                               width_shift, (unsigned long) regs->pc);
+                       break;
+               }
+
+               if (__copy_user((void *)(int)address, &buffer, (1 << width_shift)) > 0) {
+                       return -1; /* fault */
+               }
+       } else
+#endif
+       {
+               /* kernel mode - we can take short cuts since if we fault, it's a genuine bug */
+               __u64 val = regs->regs[srcreg];
+
+               switch (width_shift) {
+               case 1:
+                       misaligned_kernel_word_store(address, val);
+                       break;
+               case 2:
+                       asm ("stlo.l %1, 0, %0" : : "r" (val), "r" (address));
+                       asm ("sthi.l %1, 3, %0" : : "r" (val), "r" (address));
+                       break;
+               case 3:
+                       asm ("stlo.q %1, 0, %0" : : "r" (val), "r" (address));
+                       asm ("sthi.q %1, 7, %0" : : "r" (val), "r" (address));
+                       break;
+
+               default:
+                       printk("Unexpected width_shift %d in misaligned_store, PC=%08lx\n",
+                               width_shift, (unsigned long) regs->pc);
+                       break;
+               }
+       }
+
+       return 0;
+
+}
+
+#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
+/* Never need to fix up misaligned FPU accesses within the kernel since that's a real
+   error. */
+static int misaligned_fpu_load(struct pt_regs *regs,
+                          __u32 opcode,
+                          int displacement_not_indexed,
+                          int width_shift,
+                          int do_paired_load)
+{
+       /* Return -1 for a fault, 0 for OK */
+       int error;
+       int destreg;
+       __u64 address;
+
+       error = generate_and_check_address(regs, opcode,
+                       displacement_not_indexed, width_shift, &address);
+       if (error < 0) {
+               return error;
+       }
+
+       destreg = (opcode >> 4) & 0x3f;
+       if (user_mode(regs)) {
+               __u64 buffer;
+               __u32 buflo, bufhi;
+
+               if (!access_ok(VERIFY_READ, (unsigned long) address, 1UL<<width_shift)) {
+                       return -1;
+               }
+
+               if (__copy_user(&buffer, (const void *)(int)address, (1 << width_shift)) > 0) {
+                       return -1; /* fault */
+               }
+               /* 'current' may be the current owner of the FPU state, so
+                  context switch the registers into memory so they can be
+                  indexed by register number. */
+               if (last_task_used_math == current) {
+                       grab_fpu();
+                       fpsave(&current->thread.fpu.hard);
+                       release_fpu();
+                       last_task_used_math = NULL;
+                       regs->sr |= SR_FD;
+               }
+
+               buflo = *(__u32*) &buffer;
+               bufhi = *(1 + (__u32*) &buffer);
+
+               switch (width_shift) {
+               case 2:
+                       current->thread.fpu.hard.fp_regs[destreg] = buflo;
+                       break;
+               case 3:
+                       if (do_paired_load) {
+                               current->thread.fpu.hard.fp_regs[destreg] = buflo;
+                               current->thread.fpu.hard.fp_regs[destreg+1] = bufhi;
+                       } else {
+#if defined(CONFIG_LITTLE_ENDIAN)
+                               current->thread.fpu.hard.fp_regs[destreg] = bufhi;
+                               current->thread.fpu.hard.fp_regs[destreg+1] = buflo;
+#else
+                               current->thread.fpu.hard.fp_regs[destreg] = buflo;
+                               current->thread.fpu.hard.fp_regs[destreg+1] = bufhi;
+#endif
+                       }
+                       break;
+               default:
+                       printk("Unexpected width_shift %d in misaligned_fpu_load, PC=%08lx\n",
+                               width_shift, (unsigned long) regs->pc);
+                       break;
+               }
+               return 0;
+       } else {
+               die ("Misaligned FPU load inside kernel", regs, 0);
+               return -1;
+       }
+
+
+}
+
+static int misaligned_fpu_store(struct pt_regs *regs,
+                          __u32 opcode,
+                          int displacement_not_indexed,
+                          int width_shift,
+                          int do_paired_load)
+{
+       /* Return -1 for a fault, 0 for OK */
+       int error;
+       int srcreg;
+       __u64 address;
+
+       error = generate_and_check_address(regs, opcode,
+                       displacement_not_indexed, width_shift, &address);
+       if (error < 0) {
+               return error;
+       }
+
+       srcreg = (opcode >> 4) & 0x3f;
+       if (user_mode(regs)) {
+               __u64 buffer;
+               /* Initialise these to NaNs. */
+               __u32 buflo=0xffffffffUL, bufhi=0xffffffffUL;
+
+               if (!access_ok(VERIFY_WRITE, (unsigned long) address, 1UL<<width_shift)) {
+                       return -1;
+               }
+
+               /* 'current' may be the current owner of the FPU state, so
+                  context switch the registers into memory so they can be
+                  indexed by register number. */
+               if (last_task_used_math == current) {
+                       grab_fpu();
+                       fpsave(&current->thread.fpu.hard);
+                       release_fpu();
+                       last_task_used_math = NULL;
+                       regs->sr |= SR_FD;
+               }
+
+               switch (width_shift) {
+               case 2:
+                       buflo = current->thread.fpu.hard.fp_regs[srcreg];
+                       break;
+               case 3:
+                       if (do_paired_load) {
+                               buflo = current->thread.fpu.hard.fp_regs[srcreg];
+                               bufhi = current->thread.fpu.hard.fp_regs[srcreg+1];
+                       } else {
+#if defined(CONFIG_LITTLE_ENDIAN)
+                               bufhi = current->thread.fpu.hard.fp_regs[srcreg];
+                               buflo = current->thread.fpu.hard.fp_regs[srcreg+1];
+#else
+                               buflo = current->thread.fpu.hard.fp_regs[srcreg];
+                               bufhi = current->thread.fpu.hard.fp_regs[srcreg+1];
+#endif
+                       }
+                       break;
+               default:
+                       printk("Unexpected width_shift %d in misaligned_fpu_store, PC=%08lx\n",
+                               width_shift, (unsigned long) regs->pc);
+                       break;
+               }
+
+               *(__u32*) &buffer = buflo;
+               *(1 + (__u32*) &buffer) = bufhi;
+               if (__copy_user((void *)(int)address, &buffer, (1 << width_shift)) > 0) {
+                       return -1; /* fault */
+               }
+               return 0;
+       } else {
+               die ("Misaligned FPU load inside kernel", regs, 0);
+               return -1;
+       }
+}
+#endif
+
+static int misaligned_fixup(struct pt_regs *regs)
+{
+       unsigned long opcode;
+       int error;
+       int major, minor;
+
+#if !defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
+       /* Never fixup user mode misaligned accesses without this option enabled. */
+       return -1;
+#else
+       if (!user_mode_unaligned_fixup_enable) return -1;
+#endif
+
+       error = read_opcode(regs->pc, &opcode, user_mode(regs));
+       if (error < 0) {
+               return error;
+       }
+       major = (opcode >> 26) & 0x3f;
+       minor = (opcode >> 16) & 0xf;
+
+#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
+       if (user_mode(regs) && (user_mode_unaligned_fixup_count > 0)) {
+               --user_mode_unaligned_fixup_count;
+               /* Only do 'count' worth of these reports, to remove a potential DoS against syslog */
+               printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n",
+                      current->comm, current->pid, (__u32)regs->pc, opcode);
+       } else
+#endif
+       if (!user_mode(regs) && (kernel_mode_unaligned_fixup_count > 0)) {
+               --kernel_mode_unaligned_fixup_count;
+               if (in_interrupt()) {
+                       printk("Fixing up unaligned kernelspace access in interrupt pc=0x%08x ins=0x%08lx\n",
+                              (__u32)regs->pc, opcode);
+               } else {
+                       printk("Fixing up unaligned kernelspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n",
+                              current->comm, current->pid, (__u32)regs->pc, opcode);
+               }
+       }
+
+
+       switch (major) {
+               case (0x84>>2): /* LD.W */
+                       error = misaligned_load(regs, opcode, 1, 1, 1);
+                       break;
+               case (0xb0>>2): /* LD.UW */
+                       error = misaligned_load(regs, opcode, 1, 1, 0);
+                       break;
+               case (0x88>>2): /* LD.L */
+                       error = misaligned_load(regs, opcode, 1, 2, 1);
+                       break;
+               case (0x8c>>2): /* LD.Q */
+                       error = misaligned_load(regs, opcode, 1, 3, 0);
+                       break;
+
+               case (0xa4>>2): /* ST.W */
+                       error = misaligned_store(regs, opcode, 1, 1);
+                       break;
+               case (0xa8>>2): /* ST.L */
+                       error = misaligned_store(regs, opcode, 1, 2);
+                       break;
+               case (0xac>>2): /* ST.Q */
+                       error = misaligned_store(regs, opcode, 1, 3);
+                       break;
+
+               case (0x40>>2): /* indexed loads */
+                       switch (minor) {
+                               case 0x1: /* LDX.W */
+                                       error = misaligned_load(regs, opcode, 0, 1, 1);
+                                       break;
+                               case 0x5: /* LDX.UW */
+                                       error = misaligned_load(regs, opcode, 0, 1, 0);
+                                       break;
+                               case 0x2: /* LDX.L */
+                                       error = misaligned_load(regs, opcode, 0, 2, 1);
+                                       break;
+                               case 0x3: /* LDX.Q */
+                                       error = misaligned_load(regs, opcode, 0, 3, 0);
+                                       break;
+                               default:
+                                       error = -1;
+                                       break;
+                       }
+                       break;
+
+               case (0x60>>2): /* indexed stores */
+                       switch (minor) {
+                               case 0x1: /* STX.W */
+                                       error = misaligned_store(regs, opcode, 0, 1);
+                                       break;
+                               case 0x2: /* STX.L */
+                                       error = misaligned_store(regs, opcode, 0, 2);
+                                       break;
+                               case 0x3: /* STX.Q */
+                                       error = misaligned_store(regs, opcode, 0, 3);
+                                       break;
+                               default:
+                                       error = -1;
+                                       break;
+                       }
+                       break;
+
+#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
+               case (0x94>>2): /* FLD.S */
+                       error = misaligned_fpu_load(regs, opcode, 1, 2, 0);
+                       break;
+               case (0x98>>2): /* FLD.P */
+                       error = misaligned_fpu_load(regs, opcode, 1, 3, 1);
+                       break;
+               case (0x9c>>2): /* FLD.D */
+                       error = misaligned_fpu_load(regs, opcode, 1, 3, 0);
+                       break;
+               case (0x1c>>2): /* floating indexed loads */
+                       switch (minor) {
+                       case 0x8: /* FLDX.S */
+                               error = misaligned_fpu_load(regs, opcode, 0, 2, 0);
+                               break;
+                       case 0xd: /* FLDX.P */
+                               error = misaligned_fpu_load(regs, opcode, 0, 3, 1);
+                               break;
+                       case 0x9: /* FLDX.D */
+                               error = misaligned_fpu_load(regs, opcode, 0, 3, 0);
+                               break;
+                       default:
+                               error = -1;
+                               break;
+                       }
+                       break;
+               case (0xb4>>2): /* FLD.S */
+                       error = misaligned_fpu_store(regs, opcode, 1, 2, 0);
+                       break;
+               case (0xb8>>2): /* FLD.P */
+                       error = misaligned_fpu_store(regs, opcode, 1, 3, 1);
+                       break;
+               case (0xbc>>2): /* FLD.D */
+                       error = misaligned_fpu_store(regs, opcode, 1, 3, 0);
+                       break;
+               case (0x3c>>2): /* floating indexed stores */
+                       switch (minor) {
+                       case 0x8: /* FSTX.S */
+                               error = misaligned_fpu_store(regs, opcode, 0, 2, 0);
+                               break;
+                       case 0xd: /* FSTX.P */
+                               error = misaligned_fpu_store(regs, opcode, 0, 3, 1);
+                               break;
+                       case 0x9: /* FSTX.D */
+                               error = misaligned_fpu_store(regs, opcode, 0, 3, 0);
+                               break;
+                       default:
+                               error = -1;
+                               break;
+                       }
+                       break;
+#endif
+
+               default:
+                       /* Fault */
+                       error = -1;
+                       break;
+       }
+
+       if (error < 0) {
+               return error;
+       } else {
+               regs->pc += 4; /* Skip the instruction that's just been emulated */
+               return 0;
+       }
+
+}
+
+static ctl_table unaligned_table[] = {
+       {1, "kernel_reports", &kernel_mode_unaligned_fixup_count,
+               sizeof(int), 0644, NULL, &proc_dointvec},
+#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP)
+       {2, "user_reports", &user_mode_unaligned_fixup_count,
+               sizeof(int), 0644, NULL, &proc_dointvec},
+       {3, "user_enable", &user_mode_unaligned_fixup_enable,
+               sizeof(int), 0644, NULL, &proc_dointvec},
+#endif
+       {0}
+};
+
+static ctl_table unaligned_root[] = {
+       {1, "unaligned_fixup", NULL, 0, 0555, unaligned_table},
+       {0}
+};
+
+static ctl_table sh64_root[] = {
+       {1, "sh64", NULL, 0, 0555, unaligned_root},
+       {0}
+};
+static struct ctl_table_header *sysctl_header;
+static int __init init_sysctl(void)
+{
+       sysctl_header = register_sysctl_table(sh64_root, 0);
+       return 0;
+}
+
+__initcall(init_sysctl);
+
+
+asmlinkage void do_debug_interrupt(unsigned long code, struct pt_regs *regs)
+{
+       u64 peek_real_address_q(u64 addr);
+       u64 poke_real_address_q(u64 addr, u64 val);
+       unsigned long long DM_EXP_CAUSE_PHY = 0x0c100010;
+       unsigned long long exp_cause;
+       /* It's not worth ioremapping the debug module registers for the amount
+          of access we make to them - just go direct to their physical
+          addresses. */
+       exp_cause = peek_real_address_q(DM_EXP_CAUSE_PHY);
+       if (exp_cause & ~4) {
+               printk("DM.EXP_CAUSE had unexpected bits set (=%08lx)\n",
+                       (unsigned long)(exp_cause & 0xffffffff));
+       }
+       show_state();
+       /* Clear all DEBUGINT causes */
+       poke_real_address_q(DM_EXP_CAUSE_PHY, 0x0);
+}
+
diff --git a/arch/sh64/kernel/unwind.c b/arch/sh64/kernel/unwind.c
new file mode 100644 (file)
index 0000000..f934f97
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * arch/sh64/kernel/unwind.c
+ *
+ * Copyright (C) 2004  Paul Mundt
+ * Copyright (C) 2004  Richard Curnow
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kallsyms.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+static u8 regcache[63];
+
+/*
+ * Finding the previous stack frame isn't horribly straightforward as it is
+ * on some other platforms. In the sh64 case, we don't have "linked" stack
+ * frames, so we need to do a bit of work to determine the previous frame,
+ * and in turn, the previous r14/r18 pair.
+ *
+ * There are generally a few cases which determine where we can find out
+ * the r14/r18 values. In the general case, this can be determined by poking
+ * around the prologue of the symbol PC is in (note that we absolutely must
+ * have frame pointer support as well as the kernel symbol table mapped,
+ * otherwise we can't even get this far).
+ *
+ * In other cases, such as the interrupt/exception path, we can poke around
+ * the sp/fp.
+ *
+ * Notably, this entire approach is somewhat error prone, and in the event
+ * that the previous frame cannot be determined, that's all we can do.
+ * Either way, this still leaves us with a more correct backtrace then what
+ * we would be able to come up with by walking the stack (which is garbage
+ * for anything beyond the first frame).
+ *                                             -- PFM.
+ */
+static int lookup_prev_stack_frame(unsigned long fp, unsigned long pc,
+                     unsigned long *pprev_fp, unsigned long *pprev_pc,
+                     struct pt_regs *regs)
+{
+       const char *sym;
+       char *modname, namebuf[128];
+       unsigned long offset, size;
+       unsigned long prologue = 0;
+       unsigned long fp_displacement = 0;
+       unsigned long fp_prev = 0;
+       unsigned long offset_r14 = 0, offset_r18 = 0;
+       int i, found_prologue_end = 0;
+
+       sym = kallsyms_lookup(pc, &size, &offset, &modname, namebuf);
+       if (!sym)
+               return -EINVAL;
+
+       prologue = pc - offset;
+       if (!prologue)
+               return -EINVAL;
+
+       /* Validate fp, to avoid risk of dereferencing a bad pointer later.
+          Assume 128Mb since that's the amount of RAM on a Cayman.  Modify
+          when there is an SH-5 board with more. */
+       if ((fp < (unsigned long) phys_to_virt(__MEMORY_START)) ||
+           (fp >= (unsigned long)(phys_to_virt(__MEMORY_START)) + 128*1024*1024) ||
+           ((fp & 7) != 0)) {
+               return -EINVAL;
+       }
+
+       /*
+        * Depth to walk, depth is completely arbitrary.
+        */
+       for (i = 0; i < 100; i++, prologue += sizeof(unsigned long)) {
+               unsigned long op;
+               u8 major, minor;
+               u8 src, dest, disp;
+
+               op = *(unsigned long *)prologue;
+
+               major = (op >> 26) & 0x3f;
+               src   = (op >> 20) & 0x3f;
+               minor = (op >> 16) & 0xf;
+               disp  = (op >> 10) & 0x3f;
+               dest  = (op >>  4) & 0x3f;
+
+               /*
+                * Stack frame creation happens in a number of ways.. in the
+                * general case when the stack frame is less than 511 bytes,
+                * it's generally created by an addi or addi.l:
+                *
+                *      addi/addi.l r15, -FRAME_SIZE, r15
+                *
+                * in the event that the frame size is bigger than this, it's
+                * typically created using a movi/sub pair as follows:
+                *
+                *      movi    FRAME_SIZE, rX
+                *      sub     r15, rX, r15
+                */
+
+               switch (major) {
+               case (0x00 >> 2):
+                       switch (minor) {
+                       case 0x8: /* add.l */
+                       case 0x9: /* add */
+                               /* Look for r15, r63, r14 */
+                               if (src == 15 && disp == 63 && dest == 14)
+                                       found_prologue_end = 1;
+
+                               break;
+                       case 0xa: /* sub.l */
+                       case 0xb: /* sub */
+                               if (src != 15 || dest != 15)
+                                       continue;
+
+                               fp_displacement -= regcache[disp];
+                               fp_prev = fp - fp_displacement;
+                               break;
+                       }
+                       break;
+               case (0xa8 >> 2): /* st.l */
+                       if (src != 15)
+                               continue;
+
+                       switch (dest) {
+                       case 14:
+                               if (offset_r14 || fp_displacement == 0)
+                                       continue;
+
+                               offset_r14 = (u64)(((((s64)op >> 10) & 0x3ff) << 54) >> 54);
+                               offset_r14 *= sizeof(unsigned long);
+                               offset_r14 += fp_displacement;
+                               break;
+                       case 18:
+                               if (offset_r18 || fp_displacement == 0)
+                                       continue;
+
+                               offset_r18 = (u64)(((((s64)op >> 10) & 0x3ff) << 54) >> 54);
+                               offset_r18 *= sizeof(unsigned long);
+                               offset_r18 += fp_displacement;
+                               break;
+                       }
+
+                       break;
+               case (0xcc >> 2): /* movi */
+                       if (dest >= 63) {
+                               printk(KERN_NOTICE "%s: Invalid dest reg %d "
+                                      "specified in movi handler. Failed "
+                                      "opcode was 0x%lx: ", __FUNCTION__,
+                                      dest, op);
+
+                               continue;
+                       }
+
+                       /* Sign extend */
+                       regcache[dest] =
+                               ((((s64)(u64)op >> 10) & 0xffff) << 54) >> 54;
+                       break;
+               case (0xd0 >> 2): /* addi */
+               case (0xd4 >> 2): /* addi.l */
+                       /* Look for r15, -FRAME_SIZE, r15 */
+                       if (src != 15 || dest != 15)
+                               continue;
+
+                       /* Sign extended frame size.. */
+                       fp_displacement +=
+                               (u64)(((((s64)op >> 10) & 0x3ff) << 54) >> 54);
+                       fp_prev = fp - fp_displacement;
+                       break;
+               }
+
+               if (found_prologue_end && offset_r14 && (offset_r18 || *pprev_pc) && fp_prev)
+                       break;
+       }
+
+       if (offset_r14 == 0 || fp_prev == 0) {
+               if (!offset_r14)
+                       pr_debug("Unable to find r14 offset\n");
+               if (!fp_prev)
+                       pr_debug("Unable to find previous fp\n");
+
+               return -EINVAL;
+       }
+
+       /* For innermost leaf function, there might not be a offset_r18 */
+       if (!*pprev_pc && (offset_r18 == 0))
+               return -EINVAL;
+
+       *pprev_fp = *(unsigned long *)(fp_prev + offset_r14);
+
+       if (offset_r18)
+               *pprev_pc = *(unsigned long *)(fp_prev + offset_r18);
+
+       *pprev_pc &= ~1;
+
+       return 0;
+}
+
+/* Don't put this on the stack since we'll want to call sh64_unwind
+ * when we're close to underflowing the stack anyway. */
+static struct pt_regs here_regs;
+
+extern const char syscall_ret;
+extern const char ret_from_syscall;
+extern const char ret_from_exception;
+extern const char ret_from_irq;
+
+static void sh64_unwind_inner(struct pt_regs *regs);
+
+static void unwind_nested (unsigned long pc, unsigned long fp)
+{
+       if ((fp >= __MEMORY_START) &&
+           ((fp & 7) == 0)) {
+               sh64_unwind_inner((struct pt_regs *) fp);
+       }
+}
+
+static void sh64_unwind_inner(struct pt_regs *regs)
+{
+       unsigned long pc, fp;
+       int ofs = 0;
+       int first_pass;
+
+       pc = regs->pc & ~1;
+       fp = regs->regs[14];
+
+       first_pass = 1;
+       for (;;) {
+               int cond;
+               unsigned long next_fp, next_pc;
+
+               if (pc == ((unsigned long) &syscall_ret & ~1)) {
+                       printk("SYSCALL\n");
+                       unwind_nested(pc,fp);
+                       return;
+               }
+
+               if (pc == ((unsigned long) &ret_from_syscall & ~1)) {
+                       printk("SYSCALL (PREEMPTED)\n");
+                       unwind_nested(pc,fp);
+                       return;
+               }
+
+               /* In this case, the PC is discovered by lookup_prev_stack_frame but
+                  it has 4 taken off it to look like the 'caller' */
+               if (pc == ((unsigned long) &ret_from_exception & ~1)) {
+                       printk("EXCEPTION\n");
+                       unwind_nested(pc,fp);
+                       return;
+               }
+
+               if (pc == ((unsigned long) &ret_from_irq & ~1)) {
+                       printk("IRQ\n");
+                       unwind_nested(pc,fp);
+                       return;
+               }
+
+               cond = ((pc >= __MEMORY_START) && (fp >= __MEMORY_START) &&
+                       ((pc & 3) == 0) && ((fp & 7) == 0));
+
+               pc -= ofs;
+
+               printk("[<%08lx>] ", pc);
+               print_symbol("%s\n", pc);
+
+               if (first_pass) {
+                       /* If the innermost frame is a leaf function, it's
+                        * possible that r18 is never saved out to the stack.
+                        */
+                       next_pc = regs->regs[18];
+               } else {
+                       next_pc = 0;
+               }
+
+               if (lookup_prev_stack_frame(fp, pc, &next_fp, &next_pc, regs) == 0) {
+                       ofs = sizeof(unsigned long);
+                       pc = next_pc & ~1;
+                       fp = next_fp;
+               } else {
+                       printk("Unable to lookup previous stack frame\n");
+                       break;
+               }
+               first_pass = 0;
+       }
+
+       printk("\n");
+
+}
+
+void sh64_unwind(struct pt_regs *regs)
+{
+       if (!regs) {
+               /*
+                * Fetch current regs if we have no other saved state to back
+                * trace from.
+                */
+               regs = &here_regs;
+
+               __asm__ __volatile__ ("ori r14, 0, %0" : "=r" (regs->regs[14]));
+               __asm__ __volatile__ ("ori r15, 0, %0" : "=r" (regs->regs[15]));
+               __asm__ __volatile__ ("ori r18, 0, %0" : "=r" (regs->regs[18]));
+
+               __asm__ __volatile__ ("gettr tr0, %0" : "=r" (regs->tregs[0]));
+               __asm__ __volatile__ ("gettr tr1, %0" : "=r" (regs->tregs[1]));
+               __asm__ __volatile__ ("gettr tr2, %0" : "=r" (regs->tregs[2]));
+               __asm__ __volatile__ ("gettr tr3, %0" : "=r" (regs->tregs[3]));
+               __asm__ __volatile__ ("gettr tr4, %0" : "=r" (regs->tregs[4]));
+               __asm__ __volatile__ ("gettr tr5, %0" : "=r" (regs->tregs[5]));
+               __asm__ __volatile__ ("gettr tr6, %0" : "=r" (regs->tregs[6]));
+               __asm__ __volatile__ ("gettr tr7, %0" : "=r" (regs->tregs[7]));
+
+               __asm__ __volatile__ (
+                       "pta 0f, tr0\n\t"
+                       "blink tr0, %0\n\t"
+                       "0: nop"
+                       : "=r" (regs->pc)
+               );
+       }
+
+       printk("\nCall Trace:\n");
+       sh64_unwind_inner(regs);
+}
+
diff --git a/arch/sh64/lib/Makefile b/arch/sh64/lib/Makefile
new file mode 100644 (file)
index 0000000..0a2dc69
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2000, 2001  Paolo Alberelli
+# Coprygith (C) 2003  Paul Mundt
+#
+# Makefile for the SH-5 specific library files..
+#
+# 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).
+#
+
+# Panic should really be compiled as PIC
+lib-y  := udelay.o c-checksum.o dbg.o io.o panic.o memcpy.o copy_user_memcpy.o \
+               page_copy.o page_clear.o
+
diff --git a/arch/sh64/lib/copy_user_memcpy.S b/arch/sh64/lib/copy_user_memcpy.S
new file mode 100644 (file)
index 0000000..5b6ca39
--- /dev/null
@@ -0,0 +1,213 @@
+!
+! Fast SH memcpy
+!
+! by Toshiyasu Morita (tm@netcom.com)
+! hacked by J"orn Rernnecke (joern.rennecke@superh.com) ("o for o-umlaut)
+! SH5 code Copyright 2002 SuperH Ltd.
+!
+! Entry: ARG0: destination pointer
+!        ARG1: source pointer
+!        ARG2: byte count
+!
+! Exit:  RESULT: destination pointer
+!        any other registers in the range r0-r7: trashed
+!
+! Notes: Usually one wants to do small reads and write a longword, but
+!        unfortunately it is difficult in some cases to concatanate bytes
+!        into a longword on the SH, so this does a longword read and small
+!        writes.
+!
+! This implementation makes two assumptions about how it is called:
+!
+! 1.: If the byte count is nonzero, the address of the last byte to be
+!     copied is unsigned greater than the address of the first byte to
+!     be copied.  This could be easily swapped for a signed comparison,
+!     but the algorithm used needs some comparison.
+!
+! 2.: When there are two or three bytes in the last word of an 11-or-more
+!     bytes memory chunk to b copied, the rest of the word can be read
+!     without side effects.
+!     This could be easily changed by increasing the minumum size of
+!     a fast memcpy and the amount subtracted from r7 before L_2l_loop be 2,
+!     however, this would cost a few extra cyles on average.
+!     For SHmedia, the assumption is that any quadword can be read in its
+!     enirety if at least one byte is included in the copy.
+
+/* Imported into Linux kernel by Richard Curnow.  This is used to implement the
+   __copy_user function in the general case, so it has to be a distinct
+   function from intra-kernel memcpy to allow for exception fix-ups in the
+   event that the user pointer is bad somewhere in the copy (e.g. due to
+   running off the end of the vma).
+
+   Note, this algorithm will be slightly wasteful in the case where the source
+   and destination pointers are equally aligned, because the stlo/sthi pairs
+   could then be merged back into single stores.  If there are a lot of cache
+   misses, this is probably offset by the stall lengths on the preloads.
+
+*/
+
+       .section .text..SHmedia32,"ax"
+       .little
+       .balign 32
+       .global copy_user_memcpy
+       .global copy_user_memcpy_end
+copy_user_memcpy:
+
+#define LDUAQ(P,O,D0,D1) ldlo.q P,O,D0; ldhi.q P,O+7,D1
+#define STUAQ(P,O,D0,D1) stlo.q P,O,D0; sthi.q P,O+7,D1
+#define LDUAL(P,O,D0,D1) ldlo.l P,O,D0; ldhi.l P,O+3,D1
+#define STUAL(P,O,D0,D1) stlo.l P,O,D0; sthi.l P,O+3,D1
+
+       ld.b r3,0,r63
+       pta/l Large,tr0
+       movi 25,r0
+       bgeu/u r4,r0,tr0
+       nsb r4,r0
+       shlli r0,5,r0
+       movi (L1-L0+63*32 + 1) & 0xffff,r1
+       sub r1, r0, r0
+L0:    ptrel r0,tr0
+       add r2,r4,r5
+       ptabs r18,tr1
+       add r3,r4,r6
+       blink tr0,r63
+
+/* Rearranged to make cut2 safe */
+       .balign 8
+L4_7:  /* 4..7 byte memcpy cntd. */
+       stlo.l r2, 0, r0
+       or r6, r7, r6
+       sthi.l r5, -1, r6
+       stlo.l r5, -4, r6
+       blink tr1,r63
+
+       .balign 8
+L1:    /* 0 byte memcpy */
+       nop
+       blink tr1,r63
+       nop
+       nop
+       nop
+       nop
+
+L2_3:  /* 2 or 3 byte memcpy cntd. */
+       st.b r5,-1,r6
+       blink tr1,r63
+
+       /* 1 byte memcpy */
+       ld.b r3,0,r0
+       st.b r2,0,r0
+       blink tr1,r63
+
+L8_15: /* 8..15 byte memcpy cntd. */
+       stlo.q r2, 0, r0
+       or r6, r7, r6
+       sthi.q r5, -1, r6
+       stlo.q r5, -8, r6
+       blink tr1,r63
+
+       /* 2 or 3 byte memcpy */
+       ld.b r3,0,r0
+       ld.b r2,0,r63
+       ld.b r3,1,r1
+       st.b r2,0,r0
+       pta/l L2_3,tr0
+       ld.b r6,-1,r6
+       st.b r2,1,r1
+       blink tr0, r63
+
+       /* 4 .. 7 byte memcpy */
+       LDUAL (r3, 0, r0, r1)
+       pta L4_7, tr0
+       ldlo.l r6, -4, r7
+       or r0, r1, r0
+       sthi.l r2, 3, r0
+       ldhi.l r6, -1, r6
+       blink tr0, r63
+
+       /* 8 .. 15 byte memcpy */
+       LDUAQ (r3, 0, r0, r1)
+       pta L8_15, tr0
+       ldlo.q r6, -8, r7
+       or r0, r1, r0
+       sthi.q r2, 7, r0
+       ldhi.q r6, -1, r6
+       blink tr0, r63
+
+       /* 16 .. 24 byte memcpy */
+       LDUAQ (r3, 0, r0, r1)
+       LDUAQ (r3, 8, r8, r9)
+       or r0, r1, r0
+       sthi.q r2, 7, r0
+       or r8, r9, r8
+       sthi.q r2, 15, r8
+       ldlo.q r6, -8, r7
+       ldhi.q r6, -1, r6
+       stlo.q r2, 8, r8
+       stlo.q r2, 0, r0
+       or r6, r7, r6
+       sthi.q r5, -1, r6
+       stlo.q r5, -8, r6
+       blink tr1,r63
+
+Large:
+       ld.b r2, 0, r63
+       pta/l  Loop_ua, tr1
+       ori r3, -8, r7
+       sub r2, r7, r22
+       sub r3, r2, r6
+       add r2, r4, r5
+       ldlo.q r3, 0, r0
+       addi r5, -16, r5
+       movi 64+8, r27 ! could subtract r7 from that.
+       stlo.q r2, 0, r0
+       sthi.q r2, 7, r0
+       ldx.q r22, r6, r0
+       bgtu/l r27, r4, tr1
+
+       addi r5, -48, r27
+       pta/l Loop_line, tr0
+       addi r6, 64, r36
+       addi r6, -24, r19
+       addi r6, -16, r20
+       addi r6, -8, r21
+
+Loop_line:
+       ldx.q r22, r36, r63
+       synco
+       alloco r22, 32
+       synco
+       addi r22, 32, r22
+       ldx.q r22, r19, r23
+       sthi.q r22, -25, r0
+       ldx.q r22, r20, r24
+       ldx.q r22, r21, r25
+       stlo.q r22, -32, r0
+       ldx.q r22, r6,  r0
+       sthi.q r22, -17, r23
+       sthi.q r22,  -9, r24
+       sthi.q r22,  -1, r25
+       stlo.q r22, -24, r23
+       stlo.q r22, -16, r24
+       stlo.q r22,  -8, r25
+       bgeu r27, r22, tr0
+
+Loop_ua:
+       addi r22, 8, r22
+       sthi.q r22, -1, r0
+       stlo.q r22, -8, r0
+       ldx.q r22, r6, r0
+       bgtu/l r5, r22, tr1
+
+       add r3, r4, r7
+       ldlo.q r7, -8, r1
+       sthi.q r22, 7, r0
+       ldhi.q r7, -1, r7
+       ptabs r18,tr1
+       stlo.q r22, 0, r0
+       or r1, r7, r1
+       sthi.q r5, 15, r1
+       stlo.q r5, 8, r1
+       blink tr1, r63
+copy_user_memcpy_end:
+       nop
diff --git a/arch/sh64/lib/page_clear.S b/arch/sh64/lib/page_clear.S
new file mode 100644 (file)
index 0000000..2aadd2c
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+   Copyright 2003 Richard Curnow, SuperH (UK) Ltd.
+
+   This file is subject to the terms and conditions of the GNU General Public
+   License.  See the file "COPYING" in the main directory of this archive
+   for more details.
+
+   Tight version of memset for the case of just clearing a page.  It turns out
+   that having the alloco's spaced out slightly due to the increment/branch
+   pair causes them to contend less for access to the cache.  Similarly,
+   keeping the stores apart from the allocos causes less contention.  => Do two
+   separate loops.  Do multiple stores per loop to amortise the
+   increment/branch cost a little.
+
+   Parameters:
+   r2 : source effective address (start of page)
+
+   Always clears 4096 bytes.
+
+*/
+
+       .section .text..SHmedia32,"ax"
+       .little
+
+       .balign 8
+       .global sh64_page_clear
+sh64_page_clear:
+       pta/l 1f, tr1
+       pta/l 2f, tr2
+       ptabs/l r18, tr0
+
+       movi 4096, r7
+       add  r2, r7, r7
+       add  r2, r63, r6
+1:
+       alloco r6, 0
+       addi    r6, 32, r6
+       bgt/l   r7, r6, tr1
+
+       add  r2, r63, r6
+2:
+       st.q  r6,   0, r63
+       st.q  r6,   8, r63
+       st.q  r6,  16, r63
+       st.q  r6,  24, r63
+       addi r6, 32, r6
+       bgt/l r7, r6, tr2
+
+       blink tr0, r63
+
+
diff --git a/arch/sh64/lib/page_copy.S b/arch/sh64/lib/page_copy.S
new file mode 100644 (file)
index 0000000..804d2a0
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+   Copyright 2003 Richard Curnow, SuperH (UK) Ltd.
+
+   This file is subject to the terms and conditions of the GNU General Public
+   License.  See the file "COPYING" in the main directory of this archive
+   for more details.
+
+   Tight version of mempy for the case of just copying a page.
+   Prefetch strategy empirically optimised against RTL simulations
+   of SH5-101 cut2 eval chip with Cayman board DDR memory.
+
+   Parameters:
+   r2 : source effective address (start of page)
+   r3 : destination effective address (start of page)
+
+   Always copies 4096 bytes.
+
+   Points to review.
+   * Currently the prefetch is 4 lines ahead and the alloco is 2 lines ahead.
+     It seems like the prefetch needs to be at at least 4 lines ahead to get
+     the data into the cache in time, and the allocos contend with outstanding
+     prefetches for the same cache set, so it's better to have the numbers
+     different.
+   */
+
+       .section .text..SHmedia32,"ax"
+       .little
+
+       .balign 8
+       .global sh64_page_copy
+sh64_page_copy:
+
+       /* Copy 4096 bytes worth of data from r2 to r3.
+          Do prefetches 4 lines ahead.
+          Do alloco 2 lines ahead */
+
+       pta 1f, tr1
+       pta 2f, tr2
+       pta 3f, tr3
+       ptabs r18, tr0
+
+       ld.q r2, 0x00, r63
+       ld.q r2, 0x20, r63
+       ld.q r2, 0x40, r63
+       ld.q r2, 0x60, r63
+       alloco r3, 0x00
+       alloco r3, 0x20
+
+       movi 3968, r6
+       add  r3, r6, r6
+       addi r6, 64, r7
+       addi r7, 64, r8
+       sub r2, r3, r60
+       addi r60, 8, r61
+       addi r61, 8, r62
+       addi r62, 8, r23
+       addi r60, 0x80, r22
+
+/* Minimal code size.  The extra branches inside the loop don't cost much
+   because they overlap with the time spent waiting for prefetches to
+   complete. */
+1:
+       bge/u r3, r6, tr2  ! skip prefetch for last 4 lines
+       ldx.q r3, r22, r63 ! prefetch 4 lines hence
+2:
+       bge/u r3, r7, tr3  ! skip alloco for last 2 lines
+       alloco r3, 0x40    ! alloc destination line 2 lines ahead
+3:
+       ldx.q r3, r60, r36
+       ldx.q r3, r61, r37
+       ldx.q r3, r62, r38
+       ldx.q r3, r23, r39
+       st.q  r3,   0, r36
+       st.q  r3,   8, r37
+       st.q  r3,  16, r38
+       st.q  r3,  24, r39
+       addi r3, 32, r3
+       bgt/l r8, r3, tr1
+
+       blink tr0, r63     ! return
+
+
diff --git a/arch/sh64/lib/panic.c b/arch/sh64/lib/panic.c
new file mode 100644 (file)
index 0000000..c9eb1cb
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2003  Richard Curnow, SuperH UK Limited
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <asm/registers.h>
+
+/* THIS IS A PHYSICAL ADDRESS */
+#define HDSP2534_ADDR (0x04002100)
+
+#ifdef CONFIG_SH_CAYMAN
+
+static void poor_mans_delay(void)
+{
+       int i;
+       for (i = 0; i < 2500000; i++) {
+       }               /* poor man's delay */
+}
+
+static void show_value(unsigned long x)
+{
+       int i;
+       unsigned nibble;
+       for (i = 0; i < 8; i++) {
+               nibble = ((x >> (i * 4)) & 0xf);
+
+               ctrl_outb(nibble + ((nibble > 9) ? 55 : 48),
+                         HDSP2534_ADDR + 0xe0 + ((7 - i) << 2));
+       }
+}
+
+#endif
+
+void
+panic_handler(unsigned long panicPC, unsigned long panicSSR,
+             unsigned long panicEXPEVT)
+{
+#ifdef CONFIG_SH_CAYMAN
+       while (1) {
+               /* This piece of code displays the PC on the LED display */
+               show_value(panicPC);
+               poor_mans_delay();
+               show_value(panicSSR);
+               poor_mans_delay();
+               show_value(panicEXPEVT);
+               poor_mans_delay();
+       }
+#endif
+
+       /* Never return from the panic handler */
+       for (;;) ;
+
+}
diff --git a/arch/sh64/mach-cayman/Makefile b/arch/sh64/mach-cayman/Makefile
new file mode 100644 (file)
index 0000000..4a48b53
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for the Hitachi Cayman specific parts of the kernel
+#
+# 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).
+#
+
+obj-y := setup.o irq.o
+obj-$(CONFIG_HEARTBEAT)        += led.o
+
diff --git a/arch/sh64/mach-harp/Makefile b/arch/sh64/mach-harp/Makefile
new file mode 100644 (file)
index 0000000..63f065b
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# Makefile for the ST50 Harp specific parts of the kernel
+#
+# 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).
+#
+
+O_TARGET := harp.o
+
+obj-y := setup.o
+
+include $(TOPDIR)/Rules.make
+
diff --git a/arch/sh64/mach-romram/Makefile b/arch/sh64/mach-romram/Makefile
new file mode 100644 (file)
index 0000000..02d05c0
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# Makefile for the SH-5 ROM/RAM specific parts of the kernel
+#
+# 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).
+#
+
+O_TARGET := romram.o
+
+obj-y := setup.o
+
+include $(TOPDIR)/Rules.make
+
diff --git a/arch/sh64/mach-sim/Makefile b/arch/sh64/mach-sim/Makefile
new file mode 100644 (file)
index 0000000..819c407
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# Makefile for the SH-5 Simulator specific parts of the kernel
+#
+# 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).
+#
+
+O_TARGET := sim.o
+
+obj-y := setup.o
+
+include $(TOPDIR)/Rules.make
+
diff --git a/arch/sh64/mm/Makefile b/arch/sh64/mm/Makefile
new file mode 100644 (file)
index 0000000..ff19378
--- /dev/null
@@ -0,0 +1,44 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2000, 2001  Paolo Alberelli
+# Copyright (C) 2003, 2004  Paul Mundt
+#
+# Makefile for the sh64-specific parts of the Linux memory manager.
+#
+# 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).
+#
+
+obj-y := init.o fault.o ioremap.o extable.o cache.o tlbmiss.o tlb.o
+
+obj-$(CONFIG_HUGETLB_PAGE)     += hugetlbpage.o
+
+# Special flags for tlbmiss.o.  This puts restrictions on the number of
+# caller-save registers that the compiler can target when building this file.
+# This is required because the code is called from a context in entry.S where
+# very few registers have been saved in the exception handler (for speed
+# reasons).
+# The caller save registers that have been saved and which can be used are
+# r2,r3,r4,r5 : argument passing
+# r15, r18 : SP and LINK
+# tr0-4 : allow all caller-save TR's.  The compiler seems to be able to make
+#         use of them, so it's probably beneficial to performance to save them
+#         and have them available for it.
+#
+# The resources not listed below are callee save, i.e. the compiler is free to
+# use any of them and will spill them to the stack itself.
+
+CFLAGS_tlbmiss.o += -ffixed-r7 \
+       -ffixed-r8 -ffixed-r9 -ffixed-r10 -ffixed-r11 -ffixed-r12 \
+       -ffixed-r13 -ffixed-r14 -ffixed-r16 -ffixed-r17 -ffixed-r19 \
+       -ffixed-r20 -ffixed-r21 -ffixed-r22 -ffixed-r23 \
+       -ffixed-r24 -ffixed-r25 -ffixed-r26 -ffixed-r27 \
+       -ffixed-r36 -ffixed-r37 -ffixed-r38 -ffixed-r39 -ffixed-r40 \
+       -ffixed-r41 -ffixed-r42 -ffixed-r43  \
+       -ffixed-r60 -ffixed-r61 -ffixed-r62 \
+       -fomit-frame-pointer
+
diff --git a/arch/sh64/mm/tlb.c b/arch/sh64/mm/tlb.c
new file mode 100644 (file)
index 0000000..d517e7d
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * arch/sh64/mm/tlb.c
+ *
+ * Copyright (C) 2003  Paul Mundt <lethal@linux-sh.org>
+ * Copyright (C) 2003  Richard Curnow <richard.curnow@superh.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <asm/page.h>
+#include <asm/tlb.h>
+#include <asm/mmu_context.h>
+
+/**
+ * sh64_tlb_init
+ *
+ * Perform initial setup for the DTLB and ITLB.
+ */
+int __init sh64_tlb_init(void)
+{
+       /* Assign some sane DTLB defaults */
+       cpu_data->dtlb.entries  = 64;
+       cpu_data->dtlb.step     = 0x10;
+
+       cpu_data->dtlb.first    = DTLB_FIXED | cpu_data->dtlb.step;
+       cpu_data->dtlb.next     = cpu_data->dtlb.first;
+
+       cpu_data->dtlb.last     = DTLB_FIXED |
+                                 ((cpu_data->dtlb.entries - 1) *
+                                  cpu_data->dtlb.step);
+
+       /* And again for the ITLB */
+       cpu_data->itlb.entries  = 64;
+       cpu_data->itlb.step     = 0x10;
+
+       cpu_data->itlb.first    = ITLB_FIXED | cpu_data->itlb.step;
+       cpu_data->itlb.next     = cpu_data->itlb.first;
+       cpu_data->itlb.last     = ITLB_FIXED |
+                                 ((cpu_data->itlb.entries - 1) *
+                                  cpu_data->itlb.step);
+
+       return 0;
+}
+
+/**
+ * sh64_next_free_dtlb_entry
+ *
+ * Find the next available DTLB entry
+ */
+unsigned long long sh64_next_free_dtlb_entry(void)
+{
+       return cpu_data->dtlb.next;
+}
+
+/**
+ * sh64_get_wired_dtlb_entry
+ *
+ * Allocate a wired (locked-in) entry in the DTLB
+ */
+unsigned long long sh64_get_wired_dtlb_entry(void)
+{
+       unsigned long long entry = sh64_next_free_dtlb_entry();
+
+       cpu_data->dtlb.first += cpu_data->dtlb.step;
+       cpu_data->dtlb.next  += cpu_data->dtlb.step;
+
+       return entry;
+}
+
+/**
+ * sh64_put_wired_dtlb_entry
+ *
+ * @entry:     Address of TLB slot.
+ *
+ * Free a wired (locked-in) entry in the DTLB.
+ *
+ * Works like a stack, last one to allocate must be first one to free.
+ */
+int sh64_put_wired_dtlb_entry(unsigned long long entry)
+{
+       __flush_tlb_slot(entry);
+
+       /*
+        * We don't do any particularly useful tracking of wired entries,
+        * so this approach works like a stack .. last one to be allocated
+        * has to be the first one to be freed.
+        *
+        * We could potentially load wired entries into a list and work on
+        * rebalancing the list periodically (which also entails moving the
+        * contents of a TLB entry) .. though I have a feeling that this is
+        * more trouble than it's worth.
+        */
+
+       /*
+        * Entry must be valid .. we don't want any ITLB addresses!
+        */
+       if (entry <= DTLB_FIXED)
+               return -EINVAL;
+
+       /*
+        * Next, check if we're within range to be freed. (ie, must be the
+        * entry beneath the first 'free' entry!
+        */
+       if (entry < (cpu_data->dtlb.first - cpu_data->dtlb.step))
+               return -EINVAL;
+
+       /* If we are, then bring this entry back into the list */
+       cpu_data->dtlb.first    -= cpu_data->dtlb.step;
+       cpu_data->dtlb.next     = entry;
+
+       return 0;
+}
+
+/**
+ * sh64_setup_tlb_slot
+ *
+ * @config_addr:       Address of TLB slot.
+ * @eaddr:             Virtual address.
+ * @asid:              Address Space Identifier.
+ * @paddr:             Physical address.
+ *
+ * Load up a virtual<->physical translation for @eaddr<->@paddr in the
+ * pre-allocated TLB slot @config_addr (see sh64_get_wired_dtlb_entry).
+ */
+inline void sh64_setup_tlb_slot(unsigned long long config_addr,
+                               unsigned long eaddr,
+                               unsigned long asid,
+                               unsigned long paddr)
+{
+       unsigned long long pteh, ptel;
+
+       /* Sign extension */
+#if (NEFF == 32)
+       pteh = (unsigned long long)(signed long long)(signed long) eaddr;
+#else
+#error "Can't sign extend more than 32 bits yet"
+#endif
+       pteh &= PAGE_MASK;
+       pteh |= (asid << PTEH_ASID_SHIFT) | PTEH_VALID;
+#if (NEFF == 32)
+       ptel = (unsigned long long)(signed long long)(signed long) paddr;
+#else
+#error "Can't sign extend more than 32 bits yet"
+#endif
+       ptel &= PAGE_MASK;
+       ptel |= (_PAGE_CACHABLE | _PAGE_READ | _PAGE_WRITE);
+
+       asm volatile("putcfg %0, 1, %1\n\t"
+                       "putcfg %0, 0, %2\n"
+                       : : "r" (config_addr), "r" (ptel), "r" (pteh));
+}
+
+/**
+ * sh64_teardown_tlb_slot
+ *
+ * @config_addr:       Address of TLB slot.
+ *
+ * Teardown any existing mapping in the TLB slot @config_addr.
+ */
+inline void sh64_teardown_tlb_slot(unsigned long long config_addr)
+       __attribute__ ((alias("__flush_tlb_slot")));
+
diff --git a/arch/sh64/mm/tlbmiss.c b/arch/sh64/mm/tlbmiss.c
new file mode 100644 (file)
index 0000000..a69f775
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * arch/sh64/mm/tlbmiss.c
+ *
+ * Original code from fault.c
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ * Fast PTE->TLB refill path
+ * Copyright (C) 2003 Richard.Curnow@superh.com
+ *
+ * IMPORTANT NOTES :
+ * The do_fast_page_fault function is called from a context in entry.S where very few registers
+ * have been saved.  In particular, the code in this file must be compiled not to use ANY
+ * caller-save regiseters that are not part of the restricted save set.  Also, it means that
+ * code in this file must not make calls to functions elsewhere in the kernel, or else the
+ * excepting context will see corruption in its caller-save registers.  Plus, the entry.S save
+ * area is non-reentrant, so this code has to run with SR.BL==1, i.e. no interrupts taken inside
+ * it and panic on any exception.
+ *
+ */
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/tlb.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/registers.h>             /* required by inline asm statements */
+
+/* Callable from fault.c, so not static */
+inline void __do_tlb_refill(unsigned long address,
+                            unsigned long long is_text_not_data, pte_t *pte)
+{
+       unsigned long long ptel;
+       unsigned long long pteh=0;
+       struct tlb_info *tlbp;
+       unsigned long long next;
+
+       /* Get PTEL first */
+       ptel = pte_val(*pte);
+
+       /*
+        * Set PTEH register
+        */
+       pteh = address & MMU_VPN_MASK;
+
+       /* Sign extend based on neff. */
+#if (NEFF == 32)
+       /* Faster sign extension */
+       pteh = (unsigned long long)(signed long long)(signed long)pteh;
+#else
+       /* General case */
+       pteh = (pteh & NEFF_SIGN) ? (pteh | NEFF_MASK) : pteh;
+#endif
+
+       /* Set the ASID. */
+       pteh |= get_asid() << PTEH_ASID_SHIFT;
+       pteh |= PTEH_VALID;
+
+       /* Set PTEL register, set_pte has performed the sign extension */
+       ptel &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
+       ptel |= _PAGE_FLAGS_HARDWARE_DEFAULT; /* add default flags */
+
+       tlbp = is_text_not_data ? &(cpu_data->itlb) : &(cpu_data->dtlb);
+       next = tlbp->next;
+       __flush_tlb_slot(next);
+       asm volatile ("putcfg %0,1,%2\n\n\t"
+                     "putcfg %0,0,%1\n"
+                     :  : "r" (next), "r" (pteh), "r" (ptel) );
+
+       next += TLB_STEP;
+       if (next > tlbp->last) next = tlbp->first;
+       tlbp->next = next;
+
+}
+
+static int handle_vmalloc_fault(struct mm_struct *mm, unsigned long protection_flags,
+                                unsigned long long textaccess,
+                               unsigned long address)
+{
+       pgd_t *dir;
+       pmd_t *pmd;
+       static pte_t *pte;
+       pte_t entry;
+
+       dir = pgd_offset_k(address);
+       pmd = pmd_offset(dir, address);
+
+       if (pmd_none(*pmd)) {
+               return 0;
+       }
+
+       if (pmd_bad(*pmd)) {
+               pmd_clear(pmd);
+               return 0;
+       }
+
+       pte = pte_offset_kernel(pmd, address);
+       entry = *pte;
+
+       if (pte_none(entry) || !pte_present(entry)) {
+               return 0;
+       }
+
+       if ((pte_val(entry) & protection_flags) != protection_flags) {
+               return 0;
+       }
+
+        __do_tlb_refill(address, textaccess, pte);
+
+       return 1;
+}
+
+static int handle_tlbmiss(struct mm_struct *mm, unsigned long long protection_flags,
+                       unsigned long long textaccess,
+                       unsigned long address)
+{
+       pgd_t *dir;
+       pmd_t *pmd;
+       pte_t *pte;
+       pte_t entry;
+
+       /* NB. The PGD currently only contains a single entry - there is no
+          page table tree stored for the top half of the address space since
+          virtual pages in that region should never be mapped in user mode.
+          (In kernel mode, the only things in that region are the 512Mb super
+          page (locked in), and vmalloc (modules) +  I/O device pages (handled
+          by handle_vmalloc_fault), so no PGD for the upper half is required
+          by kernel mode either).
+
+          See how mm->pgd is allocated and initialised in pgd_alloc to see why
+          the next test is necessary.  - RPC */
+       if (address >= (unsigned long) TASK_SIZE) {
+               /* upper half - never has page table entries. */
+               return 0;
+       }
+       dir = pgd_offset(mm, address);
+       if (pgd_none(*dir)) {
+               return 0;
+       }
+       if (!pgd_present(*dir)) {
+               return 0;
+       }
+
+       pmd = pmd_offset(dir, address);
+       if (pmd_none(*pmd)) {
+               return 0;
+       }
+       if (!pmd_present(*pmd)) {
+               return 0;
+       }
+       pte = pte_offset_kernel(pmd, address);
+       entry = *pte;
+       if (pte_none(entry)) {
+               return 0;
+       }
+       if (!pte_present(entry)) {
+               return 0;
+       }
+
+       /* If the page doesn't have sufficient protection bits set to service the
+          kind of fault being handled, there's not much point doing the TLB refill.
+          Punt the fault to the general handler. */
+       if ((pte_val(entry) & protection_flags) != protection_flags) {
+               return 0;
+       }
+
+        __do_tlb_refill(address, textaccess, pte);
+
+       return 1;
+}
+
+/* Put all this information into one structure so that everything is just arithmetic
+   relative to a single base address.  This reduces the number of movi/shori pairs needed
+   just to load addresses of static data. */
+struct expevt_lookup {
+       unsigned short protection_flags[8];
+       unsigned char  is_text_access[8];
+       unsigned char  is_write_access[8];
+};
+
+#define PRU (1<<9)
+#define PRW (1<<8)
+#define PRX (1<<7)
+#define PRR (1<<6)
+
+#define DIRTY (_PAGE_DIRTY | _PAGE_ACCESSED)
+#define YOUNG (_PAGE_ACCESSED)
+
+/* Sized as 8 rather than 4 to allow checking the PTE's PRU bit against whether
+   the fault happened in user mode or privileged mode. */
+static struct expevt_lookup expevt_lookup_table = {
+       .protection_flags = {PRX, PRX, 0, 0, PRR, PRR, PRW, PRW},
+       .is_text_access   = {1,   1,   0, 0, 0,   0,   0,   0}
+};
+
+/*
+   This routine handles page faults that can be serviced just by refilling a
+   TLB entry from an existing page table entry.  (This case represents a very
+   large majority of page faults.) Return 1 if the fault was successfully
+   handled.  Return 0 if the fault could not be handled.  (This leads into the
+   general fault handling in fault.c which deals with mapping file-backed
+   pages, stack growth, segmentation faults, swapping etc etc)
+ */
+asmlinkage int do_fast_page_fault(unsigned long long ssr_md, unsigned long long expevt,
+                                 unsigned long address)
+{
+       struct task_struct *tsk;
+       struct mm_struct *mm;
+       unsigned long long textaccess;
+       unsigned long long protection_flags;
+       unsigned long long index;
+       unsigned long long expevt4;
+
+       /* The next few lines implement a way of hashing EXPEVT into a small array index
+          which can be used to lookup parameters specific to the type of TLBMISS being
+          handled.  Note:
+          ITLBMISS has EXPEVT==0xa40
+          RTLBMISS has EXPEVT==0x040
+          WTLBMISS has EXPEVT==0x060
+       */
+
+       expevt4 = (expevt >> 4);
+       /* TODO : xor ssr_md into this expression too.  Then we can check that PRU is set
+          when it needs to be. */
+       index = expevt4 ^ (expevt4 >> 5);
+       index &= 7;
+       protection_flags = expevt_lookup_table.protection_flags[index];
+       textaccess       = expevt_lookup_table.is_text_access[index];
+
+#ifdef CONFIG_SH64_PROC_TLB
+       ++calls_to_do_fast_page_fault;
+#endif
+
+       /* SIM
+        * Note this is now called with interrupts still disabled
+        * This is to cope with being called for a missing IO port
+        * address with interupts disabled. This should be fixed as
+        * soon as we have a better 'fast path' miss handler.
+        *
+        * Plus take care how you try and debug this stuff.
+        * For example, writing debug data to a port which you
+        * have just faulted on is not going to work.
+        */
+
+       tsk = current;
+       mm = tsk->mm;
+
+       if ((address >= VMALLOC_START && address < VMALLOC_END) ||
+           (address >= IOBASE_VADDR  && address < IOBASE_END)) {
+               if (ssr_md) {
+                       /* Process-contexts can never have this address range mapped */
+                       if (handle_vmalloc_fault(mm, protection_flags, textaccess, address)) {
+                               return 1;
+                       }
+               }
+       } else if (!in_interrupt() && mm) {
+               if (handle_tlbmiss(mm, protection_flags, textaccess, address)) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
diff --git a/arch/sh64/oprofile/Kconfig b/arch/sh64/oprofile/Kconfig
new file mode 100644 (file)
index 0000000..19d3773
--- /dev/null
@@ -0,0 +1,23 @@
+
+menu "Profiling support"
+       depends on EXPERIMENTAL
+
+config PROFILING
+       bool "Profiling support (EXPERIMENTAL)"
+       help
+         Say Y here to enable the extended profiling support mechanisms used
+         by profilers such as OProfile.
+
+
+config OPROFILE
+       tristate "OProfile system profiling (EXPERIMENTAL)"
+       depends on PROFILING
+       help
+         OProfile is a profiling system capable of profiling the
+         whole system, include the kernel, kernel modules, libraries,
+         and applications.
+
+         If unsure, say N.
+
+endmenu
+
diff --git a/arch/sh64/oprofile/Makefile b/arch/sh64/oprofile/Makefile
new file mode 100644 (file)
index 0000000..11a451f
--- /dev/null
@@ -0,0 +1,12 @@
+obj-$(CONFIG_OPROFILE) += oprofile.o
+
+DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
+               oprof.o cpu_buffer.o buffer_sync.o \
+               event_buffer.o oprofile_files.o \
+               oprofilefs.o oprofile_stats.o \
+               timer_int.o )
+
+profdrvr-y                             := op_model_null.o
+
+oprofile-y                             := $(DRIVER_OBJS) $(profdrvr-y)
+
diff --git a/crypto/mpi/Makefile b/crypto/mpi/Makefile
new file mode 100644 (file)
index 0000000..e96597d
--- /dev/null
@@ -0,0 +1,30 @@
+#
+# MPI multiprecision maths library (from gpg) 
+#
+
+obj-$(CONFIG_CRYPTO_MPILIB) = \
+       generic_mpih-lshift.o           \
+       generic_mpih-mul1.o             \
+       generic_mpih-mul2.o             \
+       generic_mpih-mul3.o             \
+       generic_mpih-rshift.o           \
+       generic_mpih-sub1.o             \
+       generic_mpih-add1.o             \
+       generic_udiv-w-sdiv.o           \
+       mpicoder.o                      \
+       mpi-add.o                       \
+       mpi-bit.o                       \
+       mpi-div.o                       \
+       mpi-cmp.o                       \
+       mpi-gcd.o                       \
+       mpih-cmp.o                      \
+       mpih-div.o                      \
+       mpih-mul.o                      \
+       mpi-inline.o                    \
+       mpi-inv.o                       \
+       mpi-mpow.o                      \
+       mpi-mul.o                       \
+       mpi-pow.o                       \
+       mpi-scan.o                      \
+       mpiutil.o
+
diff --git a/crypto/mpi/generic_mpi-asm-defs.h b/crypto/mpi/generic_mpi-asm-defs.h
new file mode 100644 (file)
index 0000000..13424e2
--- /dev/null
@@ -0,0 +1,10 @@
+/* This file defines some basic constants for the MPI machinery.  We
+ * need to define the types on a per-CPU basis, so it is done with
+ * this file here.  */
+#define BYTES_PER_MPI_LIMB  (SIZEOF_UNSIGNED_LONG)
+
+
+
+
+
+
diff --git a/crypto/mpi/generic_mpih-add1.c b/crypto/mpi/generic_mpih-add1.c
new file mode 100644 (file)
index 0000000..891fef0
--- /dev/null
@@ -0,0 +1,62 @@
+/* mpihelp-add_1.c  -  MPI helper functions
+ * Copyright (C) 1994, 1996, 1997, 1998, 
+ *               2000 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#include "mpi-internal.h"
+#include "longlong.h"
+
+mpi_limb_t
+mpihelp_add_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
+              mpi_ptr_t s2_ptr, mpi_size_t size)
+{
+    mpi_limb_t x, y, cy;
+    mpi_size_t j;
+
+    /* The loop counter and index J goes from -SIZE to -1.  This way
+       the loop becomes faster.  */
+    j = -size;
+
+    /* Offset the base pointers to compensate for the negative indices. */
+    s1_ptr -= j;
+    s2_ptr -= j;
+    res_ptr -= j;
+
+    cy = 0;
+    do {
+       y = s2_ptr[j];
+       x = s1_ptr[j];
+       y += cy;                  /* add previous carry to one addend */
+       cy = y < cy;              /* get out carry from that addition */
+       y += x;                   /* add other addend */
+       cy += y < x;              /* get out carry from that add, combine */
+       res_ptr[j] = y;
+    } while( ++j );
+
+    return cy;
+}
+
diff --git a/crypto/mpi/generic_mpih-lshift.c b/crypto/mpi/generic_mpih-lshift.c
new file mode 100644 (file)
index 0000000..9e159b5
--- /dev/null
@@ -0,0 +1,66 @@
+/* mpihelp-lshift.c  - MPI helper functions
+ * Copyright (C) 1994, 1996, 1998, 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#include "mpi-internal.h"
+
+/* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left
+ * and store the USIZE least significant digits of the result at WP.
+ * Return the bits shifted out from the most significant digit.
+ *
+ * Argument constraints:
+ * 1. 0 < CNT < BITS_PER_MP_LIMB
+ * 2. If the result is to be written over the input, WP must be >= UP.
+ */
+
+mpi_limb_t
+mpihelp_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
+                                           unsigned int cnt)
+{
+    mpi_limb_t high_limb, low_limb;
+    unsigned sh_1, sh_2;
+    mpi_size_t i;
+    mpi_limb_t retval;
+
+    sh_1 = cnt;
+    wp += 1;
+    sh_2 = BITS_PER_MPI_LIMB - sh_1;
+    i = usize - 1;
+    low_limb = up[i];
+    retval = low_limb >> sh_2;
+    high_limb = low_limb;
+    while( --i >= 0 ) {
+       low_limb = up[i];
+       wp[i] = (high_limb << sh_1) | (low_limb >> sh_2);
+       high_limb = low_limb;
+    }
+    wp[i] = high_limb << sh_1;
+
+    return retval;
+}
+
+
diff --git a/crypto/mpi/generic_mpih-mul1.c b/crypto/mpi/generic_mpih-mul1.c
new file mode 100644 (file)
index 0000000..4e34d46
--- /dev/null
@@ -0,0 +1,58 @@
+/* mpihelp-mul_1.c  -  MPI helper functions
+ * Copyright (C) 1994, 1996, 1997, 1998, 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#include "mpi-internal.h"
+#include "longlong.h"
+
+mpi_limb_t
+mpihelp_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
+                                                   mpi_limb_t s2_limb)
+{
+    mpi_limb_t cy_limb;
+    mpi_size_t j;
+    mpi_limb_t prod_high, prod_low;
+
+    /* The loop counter and index J goes from -S1_SIZE to -1.  This way
+     * the loop becomes faster.  */
+    j = -s1_size;
+
+    /* Offset the base pointers to compensate for the negative indices.  */
+    s1_ptr -= j;
+    res_ptr -= j;
+
+    cy_limb = 0;
+    do {
+       umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb );
+       prod_low += cy_limb;
+       cy_limb = (prod_low < cy_limb?1:0) + prod_high;
+       res_ptr[j] = prod_low;
+    } while( ++j );
+
+    return cy_limb;
+}
+
diff --git a/crypto/mpi/generic_mpih-mul2.c b/crypto/mpi/generic_mpih-mul2.c
new file mode 100644 (file)
index 0000000..c1f41f3
--- /dev/null
@@ -0,0 +1,63 @@
+/* mpihelp-mul_2.c  -  MPI helper functions
+ * Copyright (C) 1994, 1996, 1997, 1998, 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#include "mpi-internal.h"
+#include "longlong.h"
+
+
+mpi_limb_t
+mpihelp_addmul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
+                 mpi_size_t s1_size, mpi_limb_t s2_limb)
+{
+    mpi_limb_t cy_limb;
+    mpi_size_t j;
+    mpi_limb_t prod_high, prod_low;
+    mpi_limb_t x;
+
+    /* The loop counter and index J goes from -SIZE to -1.  This way
+     * the loop becomes faster.  */
+    j = -s1_size;
+    res_ptr -= j;
+    s1_ptr -= j;
+
+    cy_limb = 0;
+    do {
+       umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb );
+
+       prod_low += cy_limb;
+       cy_limb = (prod_low < cy_limb?1:0) + prod_high;
+
+       x = res_ptr[j];
+       prod_low = x + prod_low;
+       cy_limb += prod_low < x?1:0;
+       res_ptr[j] = prod_low;
+    } while ( ++j );
+    return cy_limb;
+}
+
+
diff --git a/crypto/mpi/generic_mpih-mul3.c b/crypto/mpi/generic_mpih-mul3.c
new file mode 100644 (file)
index 0000000..6b1d04b
--- /dev/null
@@ -0,0 +1,64 @@
+/* mpihelp-mul_3.c  -  MPI helper functions
+ * Copyright (C) 1994, 1996, 1997, 1998, 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#include "mpi-internal.h"
+#include "longlong.h"
+
+
+mpi_limb_t
+mpihelp_submul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
+                 mpi_size_t s1_size, mpi_limb_t s2_limb)
+{
+    mpi_limb_t cy_limb;
+    mpi_size_t j;
+    mpi_limb_t prod_high, prod_low;
+    mpi_limb_t x;
+
+    /* The loop counter and index J goes from -SIZE to -1.  This way
+     * the loop becomes faster.  */
+    j = -s1_size;
+    res_ptr -= j;
+    s1_ptr -= j;
+
+    cy_limb = 0;
+    do {
+       umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb);
+
+       prod_low += cy_limb;
+       cy_limb = (prod_low < cy_limb?1:0) + prod_high;
+
+       x = res_ptr[j];
+       prod_low = x - prod_low;
+       cy_limb += prod_low > x?1:0;
+       res_ptr[j] = prod_low;
+    } while( ++j );
+
+    return cy_limb;
+}
+
+
diff --git a/crypto/mpi/generic_mpih-rshift.c b/crypto/mpi/generic_mpih-rshift.c
new file mode 100644 (file)
index 0000000..0fc3bc8
--- /dev/null
@@ -0,0 +1,65 @@
+/* mpih-rshift.c  -  MPI helper functions
+ * Copyright (C) 1994, 1996, 1998, 1999,
+ *               2000, 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GNUPG
+ *
+ * GNUPG 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.
+ *
+ * GNUPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#include "mpi-internal.h"
+
+
+/* Shift U (pointed to by UP and USIZE limbs long) CNT bits to the right
+ * and store the USIZE least significant limbs of the result at WP.
+ * The bits shifted out to the right are returned.
+ *
+ * Argument constraints:
+ * 1. 0 < CNT < BITS_PER_MP_LIMB
+ * 2. If the result is to be written over the input, WP must be <= UP.
+ */
+
+mpi_limb_t
+mpihelp_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned cnt)
+{
+    mpi_limb_t high_limb, low_limb;
+    unsigned sh_1, sh_2;
+    mpi_size_t i;
+    mpi_limb_t retval;
+
+    sh_1 = cnt;
+    wp -= 1;
+    sh_2 = BITS_PER_MPI_LIMB - sh_1;
+    high_limb = up[0];
+    retval = high_limb << sh_2;
+    low_limb = high_limb;
+    for( i=1; i < usize; i++) {
+       high_limb = up[i];
+       wp[i] = (low_limb >> sh_1) | (high_limb << sh_2);
+       low_limb = high_limb;
+    }
+    wp[i] = low_limb >> sh_1;
+
+    return retval;
+}
+
diff --git a/crypto/mpi/generic_mpih-sub1.c b/crypto/mpi/generic_mpih-sub1.c
new file mode 100644 (file)
index 0000000..9c78f15
--- /dev/null
@@ -0,0 +1,62 @@
+/* mpihelp-add_2.c  -  MPI helper functions
+ * Copyright (C) 1994, 1996, 1997, 1998, 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#include "mpi-internal.h"
+#include "longlong.h"
+
+mpi_limb_t
+mpihelp_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
+                                 mpi_ptr_t s2_ptr, mpi_size_t size)
+{
+    mpi_limb_t x, y, cy;
+    mpi_size_t j;
+
+    /* The loop counter and index J goes from -SIZE to -1.  This way
+       the loop becomes faster.  */
+    j = -size;
+
+    /* Offset the base pointers to compensate for the negative indices.  */
+    s1_ptr -= j;
+    s2_ptr -= j;
+    res_ptr -= j;
+
+    cy = 0;
+    do {
+       y = s2_ptr[j];
+       x = s1_ptr[j];
+       y += cy;                  /* add previous carry to subtrahend */
+       cy = y < cy;              /* get out carry from that addition */
+       y = x - y;                /* main subtract */
+       cy += y > x;              /* get out carry from the subtract, combine */
+       res_ptr[j] = y;
+    } while( ++j );
+
+    return cy;
+}
+
+
diff --git a/crypto/mpi/generic_udiv-w-sdiv.c b/crypto/mpi/generic_udiv-w-sdiv.c
new file mode 100644 (file)
index 0000000..8cfc6d3
--- /dev/null
@@ -0,0 +1,130 @@
+/* mpihelp_udiv_w_sdiv -- implement udiv_qrnnd on machines with only signed
+ *                       division.
+ * Copyright (C) 1992, 1994, 1996, 1998 Free Software Foundation, Inc.
+ * Contributed by Peter L. Montgomery.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "mpi-internal.h"
+#include "longlong.h"
+
+
+#if 0  /* not yet ported to MPI */
+
+mpi_limb_t
+mpihelp_udiv_w_sdiv( mpi_limp_t *rp,
+                    mpi_limp_t *a1,
+                    mpi_limp_t *a0,
+                    mpi_limp_t *d   )
+{
+  mp_limb_t q, r;
+  mp_limb_t c0, c1, b1;
+
+  if ((mpi_limb_signed_t) d >= 0)
+    {
+      if (a1 < d - a1 - (a0 >> (BITS_PER_MP_LIMB - 1)))
+       {
+         /* dividend, divisor, and quotient are nonnegative */
+         sdiv_qrnnd (q, r, a1, a0, d);
+       }
+      else
+       {
+         /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
+         sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (BITS_PER_MP_LIMB - 1));
+         /* Divide (c1*2^32 + c0) by d */
+         sdiv_qrnnd (q, r, c1, c0, d);
+         /* Add 2^31 to quotient */
+         q += (mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1);
+       }
+    }
+  else
+    {
+      b1 = d >> 1;                     /* d/2, between 2^30 and 2^31 - 1 */
+      c1 = a1 >> 1;                    /* A/2 */
+      c0 = (a1 << (BITS_PER_MP_LIMB - 1)) + (a0 >> 1);
+
+      if (a1 < b1)                     /* A < 2^32*b1, so A/2 < 2^31*b1 */
+       {
+         sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
+
+         r = 2*r + (a0 & 1);           /* Remainder from A/(2*b1) */
+         if ((d & 1) != 0)
+           {
+             if (r >= q)
+               r = r - q;
+             else if (q - r <= d)
+               {
+                 r = r - q + d;
+                 q--;
+               }
+             else
+               {
+                 r = r - q + 2*d;
+                 q -= 2;
+               }
+           }
+       }
+      else if (c1 < b1)                /* So 2^31 <= (A/2)/b1 < 2^32 */
+       {
+         c1 = (b1 - 1) - c1;
+         c0 = ~c0;                     /* logical NOT */
+
+         sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
+
+         q = ~q;                       /* (A/2)/b1 */
+         r = (b1 - 1) - r;
+
+         r = 2*r + (a0 & 1);           /* A/(2*b1) */
+
+         if ((d & 1) != 0)
+           {
+             if (r >= q)
+               r = r - q;
+             else if (q - r <= d)
+               {
+                 r = r - q + d;
+                 q--;
+               }
+             else
+               {
+                 r = r - q + 2*d;
+                 q -= 2;
+               }
+           }
+       }
+      else                             /* Implies c1 = b1 */
+       {                               /* Hence a1 = d - 1 = 2*b1 - 1 */
+         if (a0 >= -d)
+           {
+             q = -1;
+             r = a0 + d;
+           }
+         else
+           {
+             q = -2;
+             r = a0 + 2*d;
+           }
+       }
+    }
+
+  *rp = r;
+  return q;
+}
+
+#endif
+
diff --git a/crypto/mpi/longlong.h b/crypto/mpi/longlong.h
new file mode 100644 (file)
index 0000000..bf084fc
--- /dev/null
@@ -0,0 +1,1502 @@
+/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
+   Note: I added some stuff for use with gnupg
+
+Copyright (C) 1991, 1992, 1993, 1994, 1996, 1998,
+              2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify
+it under the terms of the GNU Library General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with this file; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+MA 02111-1307, USA. */
+
+/* You have to define the following before including this file:
+
+   UWtype -- An unsigned type, default type for operations (typically a "word")
+   UHWtype -- An unsigned type, at least half the size of UWtype.
+   UDWtype -- An unsigned type, at least twice as large a UWtype
+   W_TYPE_SIZE -- size in bits of UWtype
+
+   SItype, USItype -- Signed and unsigned 32 bit types.
+   DItype, UDItype -- Signed and unsigned 64 bit types.
+
+   On a 32 bit machine UWtype should typically be USItype;
+   on a 64 bit machine, UWtype should typically be UDItype.
+*/
+
+#define __BITS4 (W_TYPE_SIZE / 4)
+#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
+#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
+
+/* This is used to make sure no undesirable sharing between different libraries
+   that use this file takes place.  */
+#ifndef __MPN
+#define __MPN(x) __##x
+#endif
+
+/* Define auxiliary asm macros.
+
+   1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two
+   UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype
+   word product in HIGH_PROD and LOW_PROD.
+
+   2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a
+   UDWtype product.  This is just a variant of umul_ppmm.
+
+   3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+   denominator) divides a UDWtype, composed by the UWtype integers
+   HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
+   in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less
+   than DENOMINATOR for correct operation.  If, in addition, the most
+   significant bit of DENOMINATOR must be 1, then the pre-processor symbol
+   UDIV_NEEDS_NORMALIZATION is defined to 1.
+
+   4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+   denominator).  Like udiv_qrnnd but the numbers are signed.  The quotient
+   is rounded towards 0.
+
+   5) count_leading_zeros(count, x) counts the number of zero-bits from the
+   msb to the first non-zero bit in the UWtype X.  This is the number of
+   steps X needs to be shifted left to set the msb.  Undefined for X == 0,
+   unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value.
+
+   6) count_trailing_zeros(count, x) like count_leading_zeros, but counts
+   from the least significant end.
+
+   7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
+   high_addend_2, low_addend_2) adds two UWtype integers, composed by
+   HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
+   respectively.  The result is placed in HIGH_SUM and LOW_SUM.  Overflow
+   (i.e. carry out) is not stored anywhere, and is lost.
+
+   8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
+   high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
+   composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
+   LOW_SUBTRAHEND_2 respectively.  The result is placed in HIGH_DIFFERENCE
+   and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere,
+   and is lost.
+
+   If any of these macros are left undefined for a particular CPU,
+   C macros are used.  */
+
+/* The CPUs come in alphabetical order below.
+
+   Please add support for more CPUs here, or improve the current support
+   for the CPUs below! */
+
+#if defined (__GNUC__) && !defined (NO_ASM)
+
+/* We sometimes need to clobber "cc" with gcc2, but that would not be
+   understood by gcc1. Use cpp to avoid major code duplication.  */
+#if __GNUC__ < 2
+#define __CLOBBER_CC
+#define __AND_CLOBBER_CC
+#else /* __GNUC__ >= 2 */
+#define __CLOBBER_CC : "cc"
+#define __AND_CLOBBER_CC , "cc"
+#endif /* __GNUC__ < 2 */
+
+
+/***************************************
+ **************  A29K  *****************
+ ***************************************/
+#if (defined (__a29k__) || defined (_AM29K)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("add %1,%4,%5\n"   \
+           "addc %0,%2,%3"                                              \
+          : "=r" ((USItype)(sh)),                                      \
+           "=&r" ((USItype)(sl))                                       \
+          : "%r" ((USItype)(ah)),                                      \
+            "rI" ((USItype)(bh)),                                      \
+            "%r" ((USItype)(al)),                                      \
+            "rI" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("sub %1,%4,%5\n"                                             \
+          "subc %0,%2,%3"                                              \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "r" ((USItype)(ah)),                                       \
+            "rI" ((USItype)(bh)),                                      \
+            "r" ((USItype)(al)),                                       \
+            "rI" ((USItype)(bl)))
+#define umul_ppmm(xh, xl, m0, m1) \
+  do {                                                                 \
+    USItype __m0 = (m0), __m1 = (m1);                                  \
+    __asm__ ("multiplu %0,%1,%2"                                        \
+            : "=r" ((USItype)(xl))                                     \
+            : "r" (__m0),                                              \
+              "r" (__m1));                                             \
+    __asm__ ("multmu %0,%1,%2"                                          \
+            : "=r" ((USItype)(xh))                                     \
+            : "r" (__m0),                                              \
+              "r" (__m1));                                             \
+  } while (0)
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  __asm__ ("dividu %0,%3,%4"                                            \
+          : "=r" ((USItype)(q)),                                       \
+            "=q" ((USItype)(r))                                        \
+          : "1" ((USItype)(n1)),                                       \
+            "r" ((USItype)(n0)),                                       \
+            "r" ((USItype)(d)))
+
+#define count_leading_zeros(count, x) \
+    __asm__ ("clz %0,%1"                                                \
+            : "=r" ((USItype)(count))                                  \
+            : "r" ((USItype)(x)))
+#define COUNT_LEADING_ZEROS_0 32
+#endif /* __a29k__ */
+
+
+#if defined (__alpha) && W_TYPE_SIZE == 64
+#define umul_ppmm(ph, pl, m0, m1) \
+  do {                                                                 \
+    UDItype __m0 = (m0), __m1 = (m1);                                  \
+    __asm__ ("umulh %r1,%2,%0"                                          \
+            : "=r" ((UDItype) ph)                                      \
+            : "%rJ" (__m0),                                            \
+              "rI" (__m1));                                            \
+    (pl) = __m0 * __m1;                                                \
+  } while (0)
+#define UMUL_TIME 46
+#ifndef LONGLONG_STANDALONE
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  do { UDItype __r;                                                    \
+    (q) = __udiv_qrnnd (&__r, (n1), (n0), (d));                        \
+    (r) = __r;                                                         \
+  } while (0)
+extern UDItype __udiv_qrnnd ();
+#define UDIV_TIME 220
+#endif /* LONGLONG_STANDALONE */
+#endif /* __alpha */
+
+/***************************************
+ **************  ARM  ******************
+ ***************************************/
+#if defined (__arm__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("adds %1, %4, %5\n"                                          \
+          "adc  %0, %2, %3"                                            \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "%r" ((USItype)(ah)),                                      \
+            "rI" ((USItype)(bh)),                                      \
+            "%r" ((USItype)(al)),                                      \
+            "rI" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subs %1, %4, %5\n"                                          \
+          "sbc  %0, %2, %3"                                            \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "r" ((USItype)(ah)),                                       \
+            "rI" ((USItype)(bh)),                                      \
+            "r" ((USItype)(al)),                                       \
+            "rI" ((USItype)(bl)))
+#if defined __ARM_ARCH_2__ || defined __ARM_ARCH_3__
+#define umul_ppmm(xh, xl, a, b) \
+  __asm__ ("%@ Inlined umul_ppmm\n"                                     \
+       "mov    %|r0, %2, lsr #16               @ AAAA\n"               \
+       "mov    %|r2, %3, lsr #16               @ BBBB\n"               \
+       "bic    %|r1, %2, %|r0, lsl #16         @ aaaa\n"               \
+       "bic    %0, %3, %|r2, lsl #16           @ bbbb\n"               \
+       "mul    %1, %|r1, %|r2                  @ aaaa * BBBB\n"        \
+       "mul    %|r2, %|r0, %|r2                @ AAAA * BBBB\n"        \
+       "mul    %|r1, %0, %|r1                  @ aaaa * bbbb\n"        \
+       "mul    %0, %|r0, %0                    @ AAAA * bbbb\n"        \
+       "adds   %|r0, %1, %0                    @ central sum\n"        \
+       "addcs  %|r2, %|r2, #65536\n"                                   \
+       "adds   %1, %|r1, %|r0, lsl #16\n"                              \
+       "adc    %0, %|r2, %|r0, lsr #16"                                \
+          : "=&r" ((USItype)(xh)),                                     \
+            "=r" ((USItype)(xl))                                       \
+          : "r" ((USItype)(a)),                                        \
+            "r" ((USItype)(b))                                         \
+          : "r0", "r1", "r2")
+#else
+#define umul_ppmm(xh, xl, a, b)                                         \
+  __asm__ ("%@ Inlined umul_ppmm\n"                                     \
+          "umull %r1, %r0, %r2, %r3"                                   \
+                  : "=&r" ((USItype)(xh)),                             \
+                    "=r" ((USItype)(xl))                               \
+                  : "r" ((USItype)(a)),                                \
+                    "r" ((USItype)(b))                                 \
+                  : "r0", "r1")
+#endif
+#define UMUL_TIME 20
+#define UDIV_TIME 100
+#endif /* __arm__ */
+
+/***************************************
+ **************  CLIPPER  **************
+ ***************************************/
+#if defined (__clipper__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+  ({union {UDItype __ll;                                               \
+          struct {USItype __l, __h;} __i;                              \
+         } __xx;                                                       \
+  __asm__ ("mulwux %2,%0"                                               \
+          : "=r" (__xx.__ll)                                           \
+          : "%0" ((USItype)(u)),                                       \
+            "r" ((USItype)(v)));                                       \
+  (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define smul_ppmm(w1, w0, u, v) \
+  ({union {DItype __ll;                                                \
+          struct {SItype __l, __h;} __i;                               \
+         } __xx;                                                       \
+  __asm__ ("mulwx %2,%0"                                                \
+          : "=r" (__xx.__ll)                                           \
+          : "%0" ((SItype)(u)),                                        \
+            "r" ((SItype)(v)));                                        \
+  (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define __umulsidi3(u, v) \
+  ({UDItype __w;                                                       \
+    __asm__ ("mulwux %2,%0"                                             \
+            : "=r" (__w)                                               \
+            : "%0" ((USItype)(u)),                                     \
+              "r" ((USItype)(v)));                                     \
+    __w; })
+#endif /* __clipper__ */
+
+
+/***************************************
+ **************  GMICRO  ***************
+ ***************************************/
+#if defined (__gmicro__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("add.w %5,%1\n"                                              \
+          "addx %3,%0"                                                 \
+          : "=g" ((USItype)(sh)),                                      \
+            "=&g" ((USItype)(sl))                                      \
+          : "%0" ((USItype)(ah)),                                      \
+            "g" ((USItype)(bh)),                                       \
+            "%1" ((USItype)(al)),                                      \
+            "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("sub.w %5,%1\n"                                              \
+          "subx %3,%0"                                                 \
+          : "=g" ((USItype)(sh)),                                      \
+            "=&g" ((USItype)(sl))                                      \
+          : "0" ((USItype)(ah)),                                       \
+            "g" ((USItype)(bh)),                                       \
+            "1" ((USItype)(al)),                                       \
+            "g" ((USItype)(bl)))
+#define umul_ppmm(ph, pl, m0, m1) \
+  __asm__ ("mulx %3,%0,%1"                                              \
+          : "=g" ((USItype)(ph)),                                      \
+            "=r" ((USItype)(pl))                                       \
+          : "%0" ((USItype)(m0)),                                      \
+            "g" ((USItype)(m1)))
+#define udiv_qrnnd(q, r, nh, nl, d) \
+  __asm__ ("divx %4,%0,%1"                                              \
+          : "=g" ((USItype)(q)),                                       \
+            "=r" ((USItype)(r))                                        \
+          : "1" ((USItype)(nh)),                                       \
+            "0" ((USItype)(nl)),                                       \
+            "g" ((USItype)(d)))
+#define count_leading_zeros(count, x) \
+  __asm__ ("bsch/1 %1,%0"                                               \
+          : "=g" (count)                                               \
+          : "g" ((USItype)(x)),                                        \
+            "0" ((USItype)0))
+#endif
+
+
+/***************************************
+ **************  HPPA  *****************
+ ***************************************/
+#if defined (__hppa) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("   add %4,%5,%1\n"                                             \
+          "    addc %2,%3,%0"                                              \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "%rM" ((USItype)(ah)),                                     \
+            "rM" ((USItype)(bh)),                                      \
+            "%rM" ((USItype)(al)),                                     \
+            "rM" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("   sub %4,%5,%1\n"                                             \
+          "    subb %2,%3,%0"                                              \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "rM" ((USItype)(ah)),                                      \
+            "rM" ((USItype)(bh)),                                      \
+            "rM" ((USItype)(al)),                                      \
+            "rM" ((USItype)(bl)))
+#if defined (_PA_RISC1_1)
+#define umul_ppmm(wh, wl, u, v) \
+  do {                                                                 \
+    union {UDItype __ll;                                               \
+          struct {USItype __h, __l;} __i;                              \
+         } __xx;                                                       \
+    __asm__ (" xmpyu %1,%2,%0"                                           \
+            : "=*f" (__xx.__ll)                                        \
+            : "*f" ((USItype)(u)),                                     \
+              "*f" ((USItype)(v)));                                    \
+    (wh) = __xx.__i.__h;                                               \
+    (wl) = __xx.__i.__l;                                               \
+  } while (0)
+#define UMUL_TIME 8
+#define UDIV_TIME 60
+#else
+#define UMUL_TIME 40
+#define UDIV_TIME 80
+#endif
+#ifndef LONGLONG_STANDALONE
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  do { USItype __r;                                                    \
+    (q) = __udiv_qrnnd (&__r, (n1), (n0), (d));                        \
+    (r) = __r;                                                         \
+  } while (0)
+extern USItype __udiv_qrnnd ();
+#endif /* LONGLONG_STANDALONE */
+#define count_leading_zeros(count, x) \
+  do {                                                                \
+    USItype __tmp;                                                    \
+    __asm__ (                                                         \
+       "       ldi             1,%0                                       \n" \
+       "       extru,=         %1,15,16,%%r0  ; Bits 31..16 zero?         \n" \
+       "       extru,tr        %1,15,16,%1    ; No.  Shift down, skip add.\n" \
+       "       ldo             16(%0),%0      ; Yes.   Perform add.       \n" \
+       "       extru,=         %1,23,8,%%r0   ; Bits 15..8 zero?          \n" \
+       "       extru,tr        %1,23,8,%1     ; No.  Shift down, skip add.\n" \
+       "       ldo             8(%0),%0       ; Yes.   Perform add.       \n" \
+       "       extru,=         %1,27,4,%%r0   ; Bits 7..4 zero?           \n" \
+       "       extru,tr        %1,27,4,%1     ; No.  Shift down, skip add.\n" \
+       "       ldo             4(%0),%0       ; Yes.   Perform add.       \n" \
+       "       extru,=         %1,29,2,%%r0   ; Bits 3..2 zero?           \n" \
+       "       extru,tr        %1,29,2,%1     ; No.  Shift down, skip add.\n" \
+       "       ldo             2(%0),%0       ; Yes.   Perform add.       \n" \
+       "       extru           %1,30,1,%1     ; Extract bit 1.            \n" \
+       "       sub             %0,%1,%0       ; Subtract it.              "   \
+       : "=r" (count), "=r" (__tmp) : "1" (x));                        \
+  } while (0)
+#endif /* hppa */
+
+
+/***************************************
+ **************  I370  *****************
+ ***************************************/
+#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32
+#define umul_ppmm(xh, xl, m0, m1) \
+  do {                                                                 \
+    union {UDItype __ll;                                               \
+          struct {USItype __h, __l;} __i;                              \
+         } __xx;                                                       \
+    USItype __m0 = (m0), __m1 = (m1);                                  \
+    __asm__ ("mr %0,%3"                                                 \
+            : "=r" (__xx.__i.__h),                                     \
+              "=r" (__xx.__i.__l)                                      \
+            : "%1" (__m0),                                             \
+              "r" (__m1));                                             \
+    (xh) = __xx.__i.__h; (xl) = __xx.__i.__l;                          \
+    (xh) += ((((SItype) __m0 >> 31) & __m1)                            \
+            + (((SItype) __m1 >> 31) & __m0));                         \
+  } while (0)
+#define smul_ppmm(xh, xl, m0, m1) \
+  do {                                                                 \
+    union {DItype __ll;                                                \
+          struct {USItype __h, __l;} __i;                              \
+         } __xx;                                                       \
+    __asm__ ("mr %0,%3"                                                 \
+            : "=r" (__xx.__i.__h),                                     \
+              "=r" (__xx.__i.__l)                                      \
+            : "%1" (m0),                                               \
+              "r" (m1));                                               \
+    (xh) = __xx.__i.__h; (xl) = __xx.__i.__l;                          \
+  } while (0)
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+  do {                                                                 \
+    union {DItype __ll;                                                \
+          struct {USItype __h, __l;} __i;                              \
+         } __xx;                                                       \
+    __xx.__i.__h = n1; __xx.__i.__l = n0;                              \
+    __asm__ ("dr %0,%2"                                                 \
+            : "=r" (__xx.__ll)                                         \
+            : "0" (__xx.__ll), "r" (d));                               \
+    (q) = __xx.__i.__l; (r) = __xx.__i.__h;                            \
+  } while (0)
+#endif
+
+
+/***************************************
+ **************  I386  *****************
+ ***************************************/
+#undef __i386__
+#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("addl %5,%1\n"                                               \
+          "adcl %3,%0"                                                 \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "%0" ((USItype)(ah)),                                      \
+            "g" ((USItype)(bh)),                                       \
+            "%1" ((USItype)(al)),                                      \
+            "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subl %5,%1\n"                                               \
+          "sbbl %3,%0"                                                 \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "0" ((USItype)(ah)),                                       \
+            "g" ((USItype)(bh)),                                       \
+            "1" ((USItype)(al)),                                       \
+            "g" ((USItype)(bl)))
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("mull %3"                                                    \
+          : "=a" ((USItype)(w0)),                                      \
+            "=d" ((USItype)(w1))                                       \
+          : "%0" ((USItype)(u)),                                       \
+            "rm" ((USItype)(v)))
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  __asm__ ("divl %4"                                                    \
+          : "=a" ((USItype)(q)),                                       \
+            "=d" ((USItype)(r))                                        \
+          : "0" ((USItype)(n0)),                                       \
+            "1" ((USItype)(n1)),                                       \
+            "rm" ((USItype)(d)))
+#define count_leading_zeros(count, x) \
+  do {                                                                 \
+    USItype __cbtmp;                                                   \
+    __asm__ ("bsrl %1,%0"                                               \
+            : "=r" (__cbtmp) : "rm" ((USItype)(x)));                   \
+    (count) = __cbtmp ^ 31;                                            \
+  } while (0)
+#define count_trailing_zeros(count, x) \
+  __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x)))
+#ifndef UMUL_TIME
+#define UMUL_TIME 40
+#endif
+#ifndef UDIV_TIME
+#define UDIV_TIME 40
+#endif
+#endif /* 80x86 */
+
+
+/***************************************
+ **************  I860  *****************
+ ***************************************/
+#if defined (__i860__) && W_TYPE_SIZE == 32
+#define rshift_rhlc(r,h,l,c) \
+  __asm__ ("shr %3,r0,r0\n"  \
+           "shrd %1,%2,%0"   \
+          "=r" (r) : "r" (h), "r" (l), "rn" (c))
+#endif /* i860 */
+
+/***************************************
+ **************  I960  *****************
+ ***************************************/
+#if defined (__i960__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("cmpo 1,0\n"      \
+           "addc %5,%4,%1\n" \
+           "addc %3,%2,%0"   \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "%dI" ((USItype)(ah)),                                     \
+            "dI" ((USItype)(bh)),                                      \
+            "%dI" ((USItype)(al)),                                     \
+            "dI" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("cmpo 0,0\n"      \
+           "subc %5,%4,%1\n" \
+           "subc %3,%2,%0"   \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "dI" ((USItype)(ah)),                                      \
+            "dI" ((USItype)(bh)),                                      \
+            "dI" ((USItype)(al)),                                      \
+            "dI" ((USItype)(bl)))
+#define umul_ppmm(w1, w0, u, v) \
+  ({union {UDItype __ll;                                               \
+          struct {USItype __l, __h;} __i;                              \
+         } __xx;                                                       \
+  __asm__ ("emul        %2,%1,%0"                                       \
+          : "=d" (__xx.__ll)                                           \
+          : "%dI" ((USItype)(u)),                                      \
+            "dI" ((USItype)(v)));                                      \
+  (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define __umulsidi3(u, v) \
+  ({UDItype __w;                                                       \
+    __asm__ ("emul      %2,%1,%0"                                       \
+            : "=d" (__w)                                               \
+            : "%dI" ((USItype)(u)),                                    \
+              "dI" ((USItype)(v)));                                    \
+    __w; })
+#define udiv_qrnnd(q, r, nh, nl, d) \
+  do {                                                                 \
+    union {UDItype __ll;                                               \
+          struct {USItype __l, __h;} __i;                              \
+         } __nn;                                                       \
+    __nn.__i.__h = (nh); __nn.__i.__l = (nl);                          \
+    __asm__ ("ediv %d,%n,%0"                                            \
+          : "=d" (__rq.__ll)                                           \
+          : "dI" (__nn.__ll),                                          \
+            "dI" ((USItype)(d)));                                      \
+    (r) = __rq.__i.__l; (q) = __rq.__i.__h;                            \
+  } while (0)
+#define count_leading_zeros(count, x) \
+  do {                                                                 \
+    USItype __cbtmp;                                                   \
+    __asm__ ("scanbit %1,%0"                                            \
+            : "=r" (__cbtmp)                                           \
+            : "r" ((USItype)(x)));                                     \
+    (count) = __cbtmp ^ 31;                                            \
+  } while (0)
+#define COUNT_LEADING_ZEROS_0 (-32) /* sic */
+#if defined (__i960mx)         /* what is the proper symbol to test??? */
+#define rshift_rhlc(r,h,l,c) \
+  do {                                                                 \
+    union {UDItype __ll;                                               \
+          struct {USItype __l, __h;} __i;                              \
+         } __nn;                                                       \
+    __nn.__i.__h = (h); __nn.__i.__l = (l);                            \
+    __asm__ ("shre %2,%1,%0"                                            \
+            : "=d" (r) : "dI" (__nn.__ll), "dI" (c));                  \
+  }
+#endif /* i960mx */
+#endif /* i960 */
+
+
+/***************************************
+ **************  68000 ****************
+ ***************************************/
+#if (defined (__mc68000__) || defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("add%.l %5,%1\n"                                             \
+          "addx%.l %3,%0"                                              \
+          : "=d" ((USItype)(sh)),                                      \
+            "=&d" ((USItype)(sl))                                      \
+          : "%0" ((USItype)(ah)),                                      \
+            "d" ((USItype)(bh)),                                       \
+            "%1" ((USItype)(al)),                                      \
+            "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("sub%.l %5,%1\n"                                             \
+          "subx%.l %3,%0"                                              \
+          : "=d" ((USItype)(sh)),                                      \
+            "=&d" ((USItype)(sl))                                      \
+          : "0" ((USItype)(ah)),                                       \
+            "d" ((USItype)(bh)),                                       \
+            "1" ((USItype)(al)),                                       \
+            "g" ((USItype)(bl)))
+#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("mulu%.l %3,%1:%0"                                           \
+          : "=d" ((USItype)(w0)),                                      \
+            "=d" ((USItype)(w1))                                       \
+          : "%0" ((USItype)(u)),                                       \
+            "dmi" ((USItype)(v)))
+#define UMUL_TIME 45
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  __asm__ ("divu%.l %4,%1:%0"                                           \
+          : "=d" ((USItype)(q)),                                       \
+            "=d" ((USItype)(r))                                        \
+          : "0" ((USItype)(n0)),                                       \
+            "1" ((USItype)(n1)),                                       \
+            "dmi" ((USItype)(d)))
+#define UDIV_TIME 90
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+  __asm__ ("divs%.l %4,%1:%0"                                           \
+          : "=d" ((USItype)(q)),                                       \
+            "=d" ((USItype)(r))                                        \
+          : "0" ((USItype)(n0)),                                       \
+            "1" ((USItype)(n1)),                                       \
+            "dmi" ((USItype)(d)))
+#define count_leading_zeros(count, x) \
+  __asm__ ("bfffo %1{%b2:%b2},%0"                                       \
+          : "=d" ((USItype)(count))                                    \
+          : "od" ((USItype)(x)), "n" (0))
+#define COUNT_LEADING_ZEROS_0 32
+#else /* not mc68020 */
+#define umul_ppmm(xh, xl, a, b) \
+  do { USItype __umul_tmp1, __umul_tmp2;                         \
+       __asm__ ("| Inlined umul_ppmm                         \n" \
+ "        move%.l %5,%3                                       \n" \
+ "        move%.l %2,%0                                       \n" \
+ "        move%.w %3,%1                                       \n" \
+ "        swap %3                                            \n" \
+ "        swap %0                                            \n" \
+ "        mulu %2,%1                                         \n" \
+ "        mulu %3,%0                                         \n" \
+ "        mulu %2,%3                                         \n" \
+ "        swap %2                                            \n" \
+ "        mulu %5,%2                                         \n" \
+ "        add%.l       %3,%2                                 \n" \
+ "        jcc  1f                                            \n" \
+ "        add%.l       %#0x10000,%0                          \n" \
+ "1:   move%.l %2,%3                                         \n" \
+ "        clr%.w       %2                                    \n" \
+ "        swap %2                                            \n" \
+ "        swap %3                                            \n" \
+ "        clr%.w       %3                                    \n" \
+ "        add%.l       %3,%1                                 \n" \
+ "        addx%.l %2,%0                                       \n" \
+ "        | End inlined umul_ppmm"                                \
+             : "=&d" ((USItype)(xh)), "=&d" ((USItype)(xl)),     \
+               "=d" (__umul_tmp1), "=&d" (__umul_tmp2)           \
+             : "%2" ((USItype)(a)), "d" ((USItype)(b)));         \
+  } while (0)
+#define UMUL_TIME 100
+#define UDIV_TIME 400
+#endif /* not mc68020 */
+#endif /* mc68000 */
+
+
+/***************************************
+ **************  88000 ****************
+ ***************************************/
+#if defined (__m88000__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("addu.co %1,%r4,%r5\n"                                       \
+          "addu.ci %0,%r2,%r3"                                         \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "%rJ" ((USItype)(ah)),                                     \
+            "rJ" ((USItype)(bh)),                                      \
+            "%rJ" ((USItype)(al)),                                     \
+            "rJ" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subu.co %1,%r4,%r5\n"                                       \
+          "subu.ci %0,%r2,%r3"                                         \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "rJ" ((USItype)(ah)),                                      \
+            "rJ" ((USItype)(bh)),                                      \
+            "rJ" ((USItype)(al)),                                      \
+            "rJ" ((USItype)(bl)))
+#define count_leading_zeros(count, x) \
+  do {                                                                 \
+    USItype __cbtmp;                                                   \
+    __asm__ ("ff1 %0,%1"                                                \
+            : "=r" (__cbtmp)                                           \
+            : "r" ((USItype)(x)));                                     \
+    (count) = __cbtmp ^ 31;                                            \
+  } while (0)
+#define COUNT_LEADING_ZEROS_0 63 /* sic */
+#if defined (__m88110__)
+#define umul_ppmm(wh, wl, u, v) \
+  do {                                                                 \
+    union {UDItype __ll;                                               \
+          struct {USItype __h, __l;} __i;                              \
+         } __x;                                                        \
+    __asm__ ("mulu.d %0,%1,%2" : "=r" (__x.__ll) : "r" (u), "r" (v));   \
+    (wh) = __x.__i.__h;                                                \
+    (wl) = __x.__i.__l;                                                \
+  } while (0)
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  ({union {UDItype __ll;                                               \
+          struct {USItype __h, __l;} __i;                              \
+         } __x, __q;                                                   \
+  __x.__i.__h = (n1); __x.__i.__l = (n0);                              \
+  __asm__ ("divu.d %0,%1,%2"                                            \
+          : "=r" (__q.__ll) : "r" (__x.__ll), "r" (d));                \
+  (r) = (n0) - __q.__l * (d); (q) = __q.__l; })
+#define UMUL_TIME 5
+#define UDIV_TIME 25
+#else
+#define UMUL_TIME 17
+#define UDIV_TIME 150
+#endif /* __m88110__ */
+#endif /* __m88000__ */
+
+/***************************************
+ **************  MIPS  *****************
+ ***************************************/
+#if defined (__mips__) && W_TYPE_SIZE == 32
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("multu %2,%3"                                                \
+          : "=l" ((USItype)(w0)),                                      \
+            "=h" ((USItype)(w1))                                       \
+          : "d" ((USItype)(u)),                                        \
+            "d" ((USItype)(v)))
+#else
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("multu %2,%3 \n" \
+          "mflo %0 \n"     \
+          "mfhi %1"                                                        \
+          : "=d" ((USItype)(w0)),                                      \
+            "=d" ((USItype)(w1))                                       \
+          : "d" ((USItype)(u)),                                        \
+            "d" ((USItype)(v)))
+#endif
+#define UMUL_TIME 10
+#define UDIV_TIME 100
+#endif /* __mips__ */
+
+/***************************************
+ **************  MIPS/64  **************
+ ***************************************/
+#if (defined (__mips) && __mips >= 3) && W_TYPE_SIZE == 64
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("dmultu %2,%3"                                               \
+          : "=l" ((UDItype)(w0)),                                      \
+            "=h" ((UDItype)(w1))                                       \
+          : "d" ((UDItype)(u)),                                        \
+            "d" ((UDItype)(v)))
+#else
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("dmultu %2,%3 \n"    \
+          "mflo %0 \n"         \
+          "mfhi %1"                                                        \
+          : "=d" ((UDItype)(w0)),                                      \
+            "=d" ((UDItype)(w1))                                       \
+          : "d" ((UDItype)(u)),                                        \
+            "d" ((UDItype)(v)))
+#endif
+#define UMUL_TIME 20
+#define UDIV_TIME 140
+#endif /* __mips__ */
+
+
+/***************************************
+ **************  32000 ****************
+ ***************************************/
+#if defined (__ns32000__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+  ({union {UDItype __ll;                                               \
+          struct {USItype __l, __h;} __i;                              \
+         } __xx;                                                       \
+  __asm__ ("meid %2,%0"                                                 \
+          : "=g" (__xx.__ll)                                           \
+          : "%0" ((USItype)(u)),                                       \
+            "g" ((USItype)(v)));                                       \
+  (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define __umulsidi3(u, v) \
+  ({UDItype __w;                                                       \
+    __asm__ ("meid %2,%0"                                               \
+            : "=g" (__w)                                               \
+            : "%0" ((USItype)(u)),                                     \
+              "g" ((USItype)(v)));                                     \
+    __w; })
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  ({union {UDItype __ll;                                               \
+          struct {USItype __l, __h;} __i;                              \
+         } __xx;                                                       \
+  __xx.__i.__h = (n1); __xx.__i.__l = (n0);                            \
+  __asm__ ("deid %2,%0"                                                 \
+          : "=g" (__xx.__ll)                                           \
+          : "0" (__xx.__ll),                                           \
+            "g" ((USItype)(d)));                                       \
+  (r) = __xx.__i.__l; (q) = __xx.__i.__h; })
+#define count_trailing_zeros(count,x) \
+  do {
+    __asm__ ("ffsd      %2,%0"                                          \
+            : "=r" ((USItype) (count))                                 \
+            : "0" ((USItype) 0),                                       \
+              "r" ((USItype) (x)));                                    \
+  } while (0)
+#endif /* __ns32000__ */
+
+
+/***************************************
+ **************  PPC  ******************
+ ***************************************/
+#if (defined (_ARCH_PPC) || defined (_IBMR2)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  do {                                                                 \
+    if (__builtin_constant_p (bh) && (bh) == 0)                        \
+      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2"           \
+            : "=r" ((USItype)(sh)),                                    \
+              "=&r" ((USItype)(sl))                                    \
+            : "%r" ((USItype)(ah)),                                    \
+              "%r" ((USItype)(al)),                                    \
+              "rI" ((USItype)(bl)));                                   \
+    else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0)         \
+      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2"           \
+            : "=r" ((USItype)(sh)),                                    \
+              "=&r" ((USItype)(sl))                                    \
+            : "%r" ((USItype)(ah)),                                    \
+              "%r" ((USItype)(al)),                                    \
+              "rI" ((USItype)(bl)));                                   \
+    else                                                               \
+      __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3"          \
+            : "=r" ((USItype)(sh)),                                    \
+              "=&r" ((USItype)(sl))                                    \
+            : "%r" ((USItype)(ah)),                                    \
+              "r" ((USItype)(bh)),                                     \
+              "%r" ((USItype)(al)),                                    \
+              "rI" ((USItype)(bl)));                                   \
+  } while (0)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  do {                                                                 \
+    if (__builtin_constant_p (ah) && (ah) == 0)                        \
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2"       \
+              : "=r" ((USItype)(sh)),                                  \
+                "=&r" ((USItype)(sl))                                  \
+              : "r" ((USItype)(bh)),                                   \
+                "rI" ((USItype)(al)),                                  \
+                "r" ((USItype)(bl)));                                  \
+    else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0)         \
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2"       \
+              : "=r" ((USItype)(sh)),                                  \
+                "=&r" ((USItype)(sl))                                  \
+              : "r" ((USItype)(bh)),                                   \
+                "rI" ((USItype)(al)),                                  \
+                "r" ((USItype)(bl)));                                  \
+    else if (__builtin_constant_p (bh) && (bh) == 0)                   \
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2"         \
+              : "=r" ((USItype)(sh)),                                  \
+                "=&r" ((USItype)(sl))                                  \
+              : "r" ((USItype)(ah)),                                   \
+                "rI" ((USItype)(al)),                                  \
+                "r" ((USItype)(bl)));                                  \
+    else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0)         \
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2"         \
+              : "=r" ((USItype)(sh)),                                  \
+                "=&r" ((USItype)(sl))                                  \
+              : "r" ((USItype)(ah)),                                   \
+                "rI" ((USItype)(al)),                                  \
+                "r" ((USItype)(bl)));                                  \
+    else                                                               \
+      __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2"      \
+              : "=r" ((USItype)(sh)),                                  \
+                "=&r" ((USItype)(sl))                                  \
+              : "r" ((USItype)(ah)),                                   \
+                "r" ((USItype)(bh)),                                   \
+                "rI" ((USItype)(al)),                                  \
+                "r" ((USItype)(bl)));                                  \
+  } while (0)
+#define count_leading_zeros(count, x) \
+  __asm__ ("{cntlz|cntlzw} %0,%1"                                       \
+          : "=r" ((USItype)(count))                                    \
+          : "r" ((USItype)(x)))
+#define COUNT_LEADING_ZEROS_0 32
+#if defined (_ARCH_PPC)
+#define umul_ppmm(ph, pl, m0, m1) \
+  do {                                                                 \
+    USItype __m0 = (m0), __m1 = (m1);                                  \
+    __asm__ ("mulhwu %0,%1,%2"                                          \
+            : "=r" ((USItype) ph)                                      \
+            : "%r" (__m0),                                             \
+              "r" (__m1));                                             \
+    (pl) = __m0 * __m1;                                                \
+  } while (0)
+#define UMUL_TIME 15
+#define smul_ppmm(ph, pl, m0, m1) \
+  do {                                                                 \
+    SItype __m0 = (m0), __m1 = (m1);                                   \
+    __asm__ ("mulhw %0,%1,%2"                                           \
+            : "=r" ((SItype) ph)                                       \
+            : "%r" (__m0),                                             \
+              "r" (__m1));                                             \
+    (pl) = __m0 * __m1;                                                \
+  } while (0)
+#define SMUL_TIME 14
+#define UDIV_TIME 120
+#else
+#define umul_ppmm(xh, xl, m0, m1) \
+  do {                                                                 \
+    USItype __m0 = (m0), __m1 = (m1);                                  \
+    __asm__ ("mul %0,%2,%3"                                             \
+            : "=r" ((USItype)(xh)),                                    \
+              "=q" ((USItype)(xl))                                     \
+            : "r" (__m0),                                              \
+              "r" (__m1));                                             \
+    (xh) += ((((SItype) __m0 >> 31) & __m1)                            \
+            + (((SItype) __m1 >> 31) & __m0));                         \
+  } while (0)
+#define UMUL_TIME 8
+#define smul_ppmm(xh, xl, m0, m1) \
+  __asm__ ("mul %0,%2,%3"                                               \
+          : "=r" ((SItype)(xh)),                                       \
+            "=q" ((SItype)(xl))                                        \
+          : "r" (m0),                                                  \
+            "r" (m1))
+#define SMUL_TIME 4
+#define sdiv_qrnnd(q, r, nh, nl, d) \
+  __asm__ ("div %0,%2,%4"                                               \
+          : "=r" ((SItype)(q)), "=q" ((SItype)(r))                     \
+          : "r" ((SItype)(nh)), "1" ((SItype)(nl)), "r" ((SItype)(d)))
+#define UDIV_TIME 100
+#endif
+#endif /* Power architecture variants. */
+
+
+/***************************************
+ **************  PYR  ******************
+ ***************************************/
+#if defined (__pyr__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("addw        %5,%1 \n" \
+          "addwc       %3,%0"                                          \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "%0" ((USItype)(ah)),                                      \
+            "g" ((USItype)(bh)),                                       \
+            "%1" ((USItype)(al)),                                      \
+            "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subw        %5,%1 \n" \
+          "subwb       %3,%0"                                          \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "0" ((USItype)(ah)),                                       \
+            "g" ((USItype)(bh)),                                       \
+            "1" ((USItype)(al)),                                       \
+            "g" ((USItype)(bl)))
+/* This insn works on Pyramids with AP, XP, or MI CPUs, but not with SP.  */
+#define umul_ppmm(w1, w0, u, v) \
+  ({union {UDItype __ll;                                               \
+          struct {USItype __h, __l;} __i;                              \
+         } __xx;                                                       \
+  __asm__ ("movw %1,%R0 \n" \
+          "uemul %2,%0"                                                \
+          : "=&r" (__xx.__ll)                                          \
+          : "g" ((USItype) (u)),                                       \
+            "g" ((USItype)(v)));                                       \
+  (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#endif /* __pyr__ */
+
+
+/***************************************
+ **************  RT/ROMP  **************
+ ***************************************/
+#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("a %1,%5 \n" \
+          "ae %0,%3"                                                   \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "%0" ((USItype)(ah)),                                      \
+            "r" ((USItype)(bh)),                                       \
+            "%1" ((USItype)(al)),                                      \
+            "r" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("s %1,%5\n" \
+          "se %0,%3"                                                   \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "0" ((USItype)(ah)),                                       \
+            "r" ((USItype)(bh)),                                       \
+            "1" ((USItype)(al)),                                       \
+            "r" ((USItype)(bl)))
+#define umul_ppmm(ph, pl, m0, m1) \
+  do {                                                                 \
+    USItype __m0 = (m0), __m1 = (m1);                                  \
+    __asm__ (                                                          \
+       "s       r2,r2    \n" \
+       "mts    r10,%2   \n" \
+       "m      r2,%3    \n" \
+       "m      r2,%3    \n" \
+       "m      r2,%3    \n" \
+       "m      r2,%3    \n" \
+       "m      r2,%3    \n" \
+       "m      r2,%3    \n" \
+       "m      r2,%3    \n" \
+       "m      r2,%3    \n" \
+       "m      r2,%3    \n" \
+       "m      r2,%3    \n" \
+       "m      r2,%3    \n" \
+       "m      r2,%3    \n" \
+       "m      r2,%3    \n" \
+       "m      r2,%3    \n" \
+       "m      r2,%3    \n" \
+       "m      r2,%3    \n" \
+       "cas    %0,r2,r0 \n" \
+       "mfs    r10,%1"                                                 \
+            : "=r" ((USItype)(ph)),                                    \
+              "=r" ((USItype)(pl))                                     \
+            : "%r" (__m0),                                             \
+               "r" (__m1)                                              \
+            : "r2");                                                   \
+    (ph) += ((((SItype) __m0 >> 31) & __m1)                            \
+            + (((SItype) __m1 >> 31) & __m0));                         \
+  } while (0)
+#define UMUL_TIME 20
+#define UDIV_TIME 200
+#define count_leading_zeros(count, x) \
+  do {                                                                 \
+    if ((x) >= 0x10000)                                                \
+      __asm__ ("clz     %0,%1"                                          \
+              : "=r" ((USItype)(count))                                \
+              : "r" ((USItype)(x) >> 16));                             \
+    else                                                               \
+      {                                                                \
+       __asm__ ("clz   %0,%1"                                          \
+                : "=r" ((USItype)(count))                              \
+                : "r" ((USItype)(x)));                                 \
+       (count) += 16;                                                  \
+      }                                                                \
+  } while (0)
+#endif /* RT/ROMP */
+
+
+/***************************************
+ **************  SH2  ******************
+ ***************************************/
+#if (defined (__sh2__) || defined(__sh3__) || defined(__SH4__) ) \
+    && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ (                                                            \
+        "dmulu.l %2,%3\n"  \
+       "sts    macl,%1\n" \
+       "sts    mach,%0"                                                \
+          : "=r" ((USItype)(w1)),                                      \
+            "=r" ((USItype)(w0))                                       \
+          : "r" ((USItype)(u)),                                        \
+            "r" ((USItype)(v))                                         \
+          : "macl", "mach")
+#define UMUL_TIME 5
+#endif
+
+/***************************************
+ **************  SPARC ****************
+ ***************************************/
+#if defined (__sparc__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("addcc %r4,%5,%1\n" \
+          "addx %r2,%3,%0"                                             \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "%rJ" ((USItype)(ah)),                                     \
+            "rI" ((USItype)(bh)),                                      \
+            "%rJ" ((USItype)(al)),                                     \
+            "rI" ((USItype)(bl))                                       \
+          __CLOBBER_CC)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subcc %r4,%5,%1\n" \
+          "subx %r2,%3,%0"                                             \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "rJ" ((USItype)(ah)),                                      \
+            "rI" ((USItype)(bh)),                                      \
+            "rJ" ((USItype)(al)),                                      \
+            "rI" ((USItype)(bl))                                       \
+          __CLOBBER_CC)
+#if defined (__sparc_v8__)
+/* Don't match immediate range because, 1) it is not often useful,
+   2) the 'I' flag thinks of the range as a 13 bit signed interval,
+   while we want to match a 13 bit interval, sign extended to 32 bits,
+   but INTERPRETED AS UNSIGNED.  */
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("umul %2,%3,%1;rd %%y,%0"                                    \
+          : "=r" ((USItype)(w1)),                                      \
+            "=r" ((USItype)(w0))                                       \
+          : "r" ((USItype)(u)),                                        \
+            "r" ((USItype)(v)))
+#define UMUL_TIME 5
+#ifndef SUPERSPARC     /* SuperSPARC's udiv only handles 53 bit dividends */
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  do {                                                                 \
+    USItype __q;                                                       \
+    __asm__ ("mov %1,%%y;nop;nop;nop;udiv %2,%3,%0"                     \
+            : "=r" ((USItype)(__q))                                    \
+            : "r" ((USItype)(n1)),                                     \
+              "r" ((USItype)(n0)),                                     \
+              "r" ((USItype)(d)));                                     \
+    (r) = (n0) - __q * (d);                                            \
+    (q) = __q;                                                         \
+  } while (0)
+#define UDIV_TIME 25
+#endif /* SUPERSPARC */
+#else /* ! __sparc_v8__ */
+#if defined (__sparclite__)
+/* This has hardware multiply but not divide.  It also has two additional
+   instructions scan (ffs from high bit) and divscc.  */
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("umul %2,%3,%1;rd %%y,%0"                                    \
+          : "=r" ((USItype)(w1)),                                      \
+            "=r" ((USItype)(w0))                                       \
+          : "r" ((USItype)(u)),                                        \
+            "r" ((USItype)(v)))
+#define UMUL_TIME 5
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  __asm__ ("! Inlined udiv_qrnnd                                     \n" \
+ "        wr   %%g0,%2,%%y     ! Not a delayed write for sparclite  \n" \
+ "        tst  %%g0                                                 \n" \
+ "        divscc       %3,%4,%%g1                                   \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%%g1                                 \n" \
+ "        divscc       %%g1,%4,%0                                   \n" \
+ "        rd   %%y,%1                                               \n" \
+ "        bl,a 1f                                                    \n" \
+ "        add  %1,%4,%1                                             \n" \
+ "1:   ! End of inline udiv_qrnnd"                                     \
+          : "=r" ((USItype)(q)),                                       \
+            "=r" ((USItype)(r))                                        \
+          : "r" ((USItype)(n1)),                                       \
+            "r" ((USItype)(n0)),                                       \
+            "rI" ((USItype)(d))                                        \
+          : "%g1" __AND_CLOBBER_CC)
+#define UDIV_TIME 37
+#define count_leading_zeros(count, x) \
+  __asm__ ("scan %1,0,%0"                                               \
+          : "=r" ((USItype)(x))                                        \
+          : "r" ((USItype)(count)))
+/* Early sparclites return 63 for an argument of 0, but they warn that future
+   implementations might change this.  Therefore, leave COUNT_LEADING_ZEROS_0
+   undefined.  */
+#endif /* __sparclite__ */
+#endif /* __sparc_v8__ */
+/* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd.  */
+#ifndef umul_ppmm
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("! Inlined umul_ppmm                                        \n" \
+ "        wr   %%g0,%2,%%y     ! SPARC has 0-3 delay insn after a wr  \n" \
+ "        sra  %3,31,%%g2      ! Don't move this insn                 \n" \
+ "        and  %2,%%g2,%%g2    ! Don't move this insn                 \n" \
+ "        andcc        %%g0,0,%%g1     ! Don't move this insn                 \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,%3,%%g1                                   \n" \
+ "        mulscc       %%g1,0,%%g1                                    \n" \
+ "        add  %%g1,%%g2,%0                                           \n" \
+ "        rd   %%y,%1"                                                 \
+          : "=r" ((USItype)(w1)),                                      \
+            "=r" ((USItype)(w0))                                       \
+          : "%rI" ((USItype)(u)),                                      \
+            "r" ((USItype)(v))                                         \
+          : "%g1", "%g2" __AND_CLOBBER_CC)
+#define UMUL_TIME 39           /* 39 instructions */
+#endif
+#ifndef udiv_qrnnd
+#ifndef LONGLONG_STANDALONE
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  do { USItype __r;                                                    \
+    (q) = __udiv_qrnnd (&__r, (n1), (n0), (d));                        \
+    (r) = __r;                                                         \
+  } while (0)
+extern USItype __udiv_qrnnd ();
+#define UDIV_TIME 140
+#endif /* LONGLONG_STANDALONE */
+#endif /* udiv_qrnnd */
+#endif /* __sparc__ */
+
+
+/***************************************
+ **************  VAX  ******************
+ ***************************************/
+#if defined (__vax__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("addl2 %5,%1\n" \
+          "adwc %3,%0"                                                 \
+          : "=g" ((USItype)(sh)),                                      \
+            "=&g" ((USItype)(sl))                                      \
+          : "%0" ((USItype)(ah)),                                      \
+            "g" ((USItype)(bh)),                                       \
+            "%1" ((USItype)(al)),                                      \
+            "g" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("subl2 %5,%1\n" \
+          "sbwc %3,%0"                                                 \
+          : "=g" ((USItype)(sh)),                                      \
+            "=&g" ((USItype)(sl))                                      \
+          : "0" ((USItype)(ah)),                                       \
+            "g" ((USItype)(bh)),                                       \
+            "1" ((USItype)(al)),                                       \
+            "g" ((USItype)(bl)))
+#define umul_ppmm(xh, xl, m0, m1) \
+  do {                                                                 \
+    union {UDItype __ll;                                               \
+          struct {USItype __l, __h;} __i;                              \
+         } __xx;                                                       \
+    USItype __m0 = (m0), __m1 = (m1);                                  \
+    __asm__ ("emul %1,%2,$0,%0"                                         \
+            : "=g" (__xx.__ll)                                         \
+            : "g" (__m0),                                              \
+              "g" (__m1));                                             \
+    (xh) = __xx.__i.__h; (xl) = __xx.__i.__l;                          \
+    (xh) += ((((SItype) __m0 >> 31) & __m1)                            \
+            + (((SItype) __m1 >> 31) & __m0));                         \
+  } while (0)
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+  do {                                                                 \
+    union {DItype __ll;                                                \
+          struct {SItype __l, __h;} __i;                               \
+         } __xx;                                                       \
+    __xx.__i.__h = n1; __xx.__i.__l = n0;                              \
+    __asm__ ("ediv %3,%2,%0,%1"                                         \
+            : "=g" (q), "=g" (r)                                       \
+            : "g" (__xx.__ll), "g" (d));                               \
+  } while (0)
+#endif /* __vax__ */
+
+
+/***************************************
+ **************  Z8000 ****************
+ ***************************************/
+#if defined (__z8000__) && W_TYPE_SIZE == 16
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("add %H1,%H5\n\tadc  %H0,%H3"                                \
+          : "=r" ((unsigned int)(sh)),                                 \
+            "=&r" ((unsigned int)(sl))                                 \
+          : "%0" ((unsigned int)(ah)),                                 \
+            "r" ((unsigned int)(bh)),                                  \
+            "%1" ((unsigned int)(al)),                                 \
+            "rQR" ((unsigned int)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("sub %H1,%H5\n\tsbc  %H0,%H3"                                \
+          : "=r" ((unsigned int)(sh)),                                 \
+            "=&r" ((unsigned int)(sl))                                 \
+          : "0" ((unsigned int)(ah)),                                  \
+            "r" ((unsigned int)(bh)),                                  \
+            "1" ((unsigned int)(al)),                                  \
+            "rQR" ((unsigned int)(bl)))
+#define umul_ppmm(xh, xl, m0, m1) \
+  do {                                                                 \
+    union {long int __ll;                                              \
+          struct {unsigned int __h, __l;} __i;                         \
+         } __xx;                                                       \
+    unsigned int __m0 = (m0), __m1 = (m1);                             \
+    __asm__ ("mult      %S0,%H3"                                        \
+            : "=r" (__xx.__i.__h),                                     \
+              "=r" (__xx.__i.__l)                                      \
+            : "%1" (__m0),                                             \
+              "rQR" (__m1));                                           \
+    (xh) = __xx.__i.__h; (xl) = __xx.__i.__l;                          \
+    (xh) += ((((signed int) __m0 >> 15) & __m1)                        \
+            + (((signed int) __m1 >> 15) & __m0));                     \
+  } while (0)
+#endif /* __z8000__ */
+
+#endif /* __GNUC__ */
+
+
+/***************************************
+ ***********  Generic Versions ********
+ ***************************************/
+#if !defined (umul_ppmm) && defined (__umulsidi3)
+#define umul_ppmm(ph, pl, m0, m1) \
+  {                                                                    \
+    UDWtype __ll = __umulsidi3 (m0, m1);                               \
+    ph = (UWtype) (__ll >> W_TYPE_SIZE);                               \
+    pl = (UWtype) __ll;                                                \
+  }
+#endif
+
+#if !defined (__umulsidi3)
+#define __umulsidi3(u, v) \
+  ({UWtype __hi, __lo;                                                 \
+    umul_ppmm (__hi, __lo, u, v);                                      \
+    ((UDWtype) __hi << W_TYPE_SIZE) | __lo; })
+#endif
+
+/* If this machine has no inline assembler, use C macros.  */
+
+#if !defined (add_ssaaaa)
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  do {                                                                 \
+    UWtype __x;                                                        \
+    __x = (al) + (bl);                                                 \
+    (sh) = (ah) + (bh) + (__x < (al));                                 \
+    (sl) = __x;                                                        \
+  } while (0)
+#endif
+
+#if !defined (sub_ddmmss)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  do {                                                                 \
+    UWtype __x;                                                        \
+    __x = (al) - (bl);                                                 \
+    (sh) = (ah) - (bh) - (__x > (al));                                 \
+    (sl) = __x;                                                        \
+  } while (0)
+#endif
+
+#if !defined (umul_ppmm)
+#define umul_ppmm(w1, w0, u, v)                                        \
+  do {                                                                 \
+    UWtype __x0, __x1, __x2, __x3;                                     \
+    UHWtype __ul, __vl, __uh, __vh;                                    \
+    UWtype __u = (u), __v = (v);                                       \
+                                                                       \
+    __ul = __ll_lowpart (__u);                                         \
+    __uh = __ll_highpart (__u);                                        \
+    __vl = __ll_lowpart (__v);                                         \
+    __vh = __ll_highpart (__v);                                        \
+                                                                       \
+    __x0 = (UWtype) __ul * __vl;                                       \
+    __x1 = (UWtype) __ul * __vh;                                       \
+    __x2 = (UWtype) __uh * __vl;                                       \
+    __x3 = (UWtype) __uh * __vh;                                       \
+                                                                       \
+    __x1 += __ll_highpart (__x0);/* this can't give carry */            \
+    __x1 += __x2;              /* but this indeed can */               \
+    if (__x1 < __x2)           /* did we get it? */                    \
+      __x3 += __ll_B;          /* yes, add it in the proper pos. */    \
+                                                                       \
+    (w1) = __x3 + __ll_highpart (__x1);                                \
+    (w0) = (__ll_lowpart (__x1) << W_TYPE_SIZE/2) + __ll_lowpart (__x0);\
+  } while (0)
+#endif
+
+#if !defined (umul_ppmm)
+#define smul_ppmm(w1, w0, u, v)                                        \
+  do {                                                                 \
+    UWtype __w1;                                                       \
+    UWtype __m0 = (u), __m1 = (v);                                     \
+    umul_ppmm (__w1, w0, __m0, __m1);                                  \
+    (w1) = __w1 - (-(__m0 >> (W_TYPE_SIZE - 1)) & __m1)                \
+               - (-(__m1 >> (W_TYPE_SIZE - 1)) & __m0);                \
+  } while (0)
+#endif
+
+/* Define this unconditionally, so it can be used for debugging.  */
+#define __udiv_qrnnd_c(q, r, n1, n0, d) \
+  do {                                                                 \
+    UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m;                    \
+    __d1 = __ll_highpart (d);                                          \
+    __d0 = __ll_lowpart (d);                                           \
+                                                                       \
+    __r1 = (n1) % __d1;                                                \
+    __q1 = (n1) / __d1;                                                \
+    __m = (UWtype) __q1 * __d0;                                        \
+    __r1 = __r1 * __ll_B | __ll_highpart (n0);                         \
+    if (__r1 < __m)                                                    \
+      {                                                                \
+       __q1--, __r1 += (d);                                            \
+       if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
+         if (__r1 < __m)                                               \
+           __q1--, __r1 += (d);                                        \
+      }                                                                \
+    __r1 -= __m;                                                       \
+                                                                       \
+    __r0 = __r1 % __d1;                                                \
+    __q0 = __r1 / __d1;                                                \
+    __m = (UWtype) __q0 * __d0;                                        \
+    __r0 = __r0 * __ll_B | __ll_lowpart (n0);                          \
+    if (__r0 < __m)                                                    \
+      {                                                                \
+       __q0--, __r0 += (d);                                            \
+       if (__r0 >= (d))                                                \
+         if (__r0 < __m)                                               \
+           __q0--, __r0 += (d);                                        \
+      }                                                                \
+    __r0 -= __m;                                                       \
+                                                                       \
+    (q) = (UWtype) __q1 * __ll_B | __q0;                               \
+    (r) = __r0;                                                        \
+  } while (0)
+
+/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through
+   __udiv_w_sdiv (defined in libgcc or elsewhere).  */
+#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd)
+#define udiv_qrnnd(q, r, nh, nl, d) \
+  do {                                                                 \
+    UWtype __r;                                                        \
+    (q) = __MPN(udiv_w_sdiv) (&__r, nh, nl, d);                        \
+    (r) = __r;                                                         \
+  } while (0)
+#endif
+
+/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c.  */
+#if !defined (udiv_qrnnd)
+#define UDIV_NEEDS_NORMALIZATION 1
+#define udiv_qrnnd __udiv_qrnnd_c
+#endif
+
+#undef count_leading_zeros
+#if !defined (count_leading_zeros)
+extern
+#ifdef __STDC__
+const
+#endif
+unsigned char __clz_tab[];
+#define count_leading_zeros(count, x) \
+  do {                                                                 \
+    UWtype __xr = (x);                                                 \
+    UWtype __a;                                                        \
+                                                                       \
+    if (W_TYPE_SIZE <= 32)                                             \
+      {                                                                \
+       __a = __xr < ((UWtype) 1 << 2*__BITS4)                          \
+         ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4)              \
+         : (__xr < ((UWtype) 1 << 3*__BITS4) ?  2*__BITS4 : 3*__BITS4);\
+      }                                                                \
+    else                                                               \
+      {                                                                \
+       for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8)                  \
+         if (((__xr >> __a) & 0xff) != 0)                              \
+           break;                                                      \
+      }                                                                \
+                                                                       \
+    (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a);            \
+  } while (0)
+/* This version gives a well-defined value for zero. */
+#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE
+#endif
+
+#if !defined (count_trailing_zeros)
+/* Define count_trailing_zeros using count_leading_zeros.  The latter might be
+   defined in asm, but if it is not, the C version above is good enough.  */
+#define count_trailing_zeros(count, x) \
+  do {                                                                 \
+    UWtype __ctz_x = (x);                                              \
+    UWtype __ctz_c;                                                    \
+    count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x);                 \
+    (count) = W_TYPE_SIZE - 1 - __ctz_c;                               \
+  } while (0)
+#endif
+
+#ifndef UDIV_NEEDS_NORMALIZATION
+#define UDIV_NEEDS_NORMALIZATION 0
+#endif
diff --git a/crypto/mpi/mpi-add.c b/crypto/mpi/mpi-add.c
new file mode 100644 (file)
index 0000000..2004206
--- /dev/null
@@ -0,0 +1,258 @@
+/* mpi-add.c  -  MPI functions
+ *     Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ *     Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#include "mpi-internal.h"
+
+/****************
+ * Add the unsigned integer V to the mpi-integer U and store the
+ * result in W. U and V may be the same.
+ */
+int
+mpi_add_ui(MPI w, const MPI u, unsigned long v )
+{
+    mpi_ptr_t wp, up;
+    mpi_size_t usize, wsize;
+    int usign, wsign;
+
+    usize = u->nlimbs;
+    usign = u->sign;
+    wsign = 0;
+
+    /* If not space for W (and possible carry), increase space.  */
+    wsize = usize + 1;
+    if( w->alloced < wsize )
+           if (mpi_resize(w, wsize) < 0)
+                   return -ENOMEM;
+
+    /* These must be after realloc (U may be the same as W).  */
+    up = u->d;
+    wp = w->d;
+
+    if( !usize ) {  /* simple */
+       wp[0] = v;
+       wsize = v? 1:0;
+    }
+    else if( !usign ) {  /* mpi is not negative */
+       mpi_limb_t cy;
+       cy = mpihelp_add_1(wp, up, usize, v);
+       wp[usize] = cy;
+       wsize = usize + cy;
+    }
+    else {  /* The signs are different.  Need exact comparison to determine
+            * which operand to subtract from which.  */
+       if( usize == 1 && up[0] < v ) {
+           wp[0] = v - up[0];
+           wsize = 1;
+       }
+       else {
+           mpihelp_sub_1(wp, up, usize, v);
+           /* Size can decrease with at most one limb. */
+           wsize = usize - (wp[usize-1]==0);
+           wsign = 1;
+       }
+    }
+
+    w->nlimbs = wsize;
+    w->sign   = wsign;
+    return 0;
+}
+
+
+int
+mpi_add(MPI w, MPI u, MPI v)
+{
+    mpi_ptr_t wp, up, vp;
+    mpi_size_t usize, vsize, wsize;
+    int usign, vsign, wsign;
+
+    if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */
+       usize = v->nlimbs;
+       usign = v->sign;
+       vsize = u->nlimbs;
+       vsign = u->sign;
+       wsize = usize + 1;
+       if (RESIZE_IF_NEEDED(w, wsize) < 0)
+               return -ENOMEM;
+       /* These must be after realloc (u or v may be the same as w).  */
+       up    = v->d;
+       vp    = u->d;
+    }
+    else {
+       usize = u->nlimbs;
+       usign = u->sign;
+       vsize = v->nlimbs;
+       vsign = v->sign;
+       wsize = usize + 1;
+       if (RESIZE_IF_NEEDED(w, wsize) < 0)
+               return -ENOMEM;
+       /* These must be after realloc (u or v may be the same as w).  */
+       up    = u->d;
+       vp    = v->d;
+    }
+    wp = w->d;
+    wsign = 0;
+
+    if( !vsize ) {  /* simple */
+        MPN_COPY(wp, up, usize );
+       wsize = usize;
+       wsign = usign;
+    }
+    else if( usign != vsign ) { /* different sign */
+       /* This test is right since USIZE >= VSIZE */
+       if( usize != vsize ) {
+           mpihelp_sub(wp, up, usize, vp, vsize);
+           wsize = usize;
+           MPN_NORMALIZE(wp, wsize);
+           wsign = usign;
+       }
+       else if( mpihelp_cmp(up, vp, usize) < 0 ) {
+           mpihelp_sub_n(wp, vp, up, usize);
+           wsize = usize;
+           MPN_NORMALIZE(wp, wsize);
+           if( !usign )
+               wsign = 1;
+       }
+       else {
+           mpihelp_sub_n(wp, up, vp, usize);
+           wsize = usize;
+           MPN_NORMALIZE(wp, wsize);
+           if( usign )
+               wsign = 1;
+       }
+    }
+    else { /* U and V have same sign. Add them. */
+       mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize);
+       wp[usize] = cy;
+       wsize = usize + cy;
+       if( usign )
+           wsign = 1;
+    }
+
+    w->nlimbs = wsize;
+    w->sign = wsign;
+    return 0;
+}
+
+
+/****************
+ * Subtract the unsigned integer V from the mpi-integer U and store the
+ * result in W.
+ */
+int
+mpi_sub_ui(MPI w, MPI u, unsigned long v )
+{
+    mpi_ptr_t wp, up;
+    mpi_size_t usize, wsize;
+    int usign, wsign;
+
+    usize = u->nlimbs;
+    usign = u->sign;
+    wsign = 0;
+
+    /* If not space for W (and possible carry), increase space.  */
+    wsize = usize + 1;
+    if( w->alloced < wsize )
+           if (mpi_resize(w, wsize) < 0)
+                   return -ENOMEM;
+
+    /* These must be after realloc (U may be the same as W).  */
+    up = u->d;
+    wp = w->d;
+
+    if( !usize ) {  /* simple */
+       wp[0] = v;
+       wsize = v? 1:0;
+       wsign = 1;
+    }
+    else if( usign ) { /* mpi and v are negative */
+       mpi_limb_t cy;
+       cy = mpihelp_add_1(wp, up, usize, v);
+       wp[usize] = cy;
+       wsize = usize + cy;
+    }
+    else {  /* The signs are different.  Need exact comparison to determine
+            * which operand to subtract from which.  */
+       if( usize == 1 && up[0] < v ) {
+           wp[0] = v - up[0];
+           wsize = 1;
+           wsign = 1;
+       }
+       else {
+           mpihelp_sub_1(wp, up, usize, v);
+           /* Size can decrease with at most one limb. */
+           wsize = usize - (wp[usize-1]==0);
+       }
+    }
+
+    w->nlimbs = wsize;
+    w->sign   = wsign;
+    return 0;
+}
+
+int
+mpi_sub(MPI w, MPI u, MPI v)
+{
+       int rc;
+
+    if( w == v ) {
+           MPI vv;
+       if (mpi_copy(&vv, v) < 0)
+               return -ENOMEM;
+       vv->sign = !vv->sign;
+       rc = mpi_add( w, u, vv );
+       mpi_free(vv);
+    }
+    else {
+       /* fixme: this is not thread-save (we temp. modify v) */
+       v->sign = !v->sign;
+       rc = mpi_add( w, u, v );
+       v->sign = !v->sign;
+    }
+    return rc;
+}
+
+
+int
+mpi_addm( MPI w, MPI u, MPI v, MPI m)
+{
+       if (mpi_add(w, u, v) < 0 ||
+           mpi_fdiv_r( w, w, m ) < 0)
+               return -ENOMEM;
+       return 0;
+}
+
+int
+mpi_subm( MPI w, MPI u, MPI v, MPI m)
+{
+       if (mpi_sub(w, u, v) < 0 ||
+           mpi_fdiv_r( w, w, m ) < 0)
+               return -ENOMEM;
+       return 0;
+}
+
diff --git a/crypto/mpi/mpi-bit.c b/crypto/mpi/mpi-bit.c
new file mode 100644 (file)
index 0000000..f155cc2
--- /dev/null
@@ -0,0 +1,245 @@
+/* mpi-bit.c  -  MPI bit level fucntions
+ * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "mpi-internal.h"
+#include "longlong.h"
+
+const unsigned char __clz_tab[] = {
+       0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+       6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+       8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+       8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+       8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+       8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+};
+
+#define A_LIMB_1 ((mpi_limb_t) 1)
+
+
+/****************
+ * Sometimes we have MSL (most significant limbs) which are 0;
+ * this is for some reasons not good, so this function removes them.
+ */
+void
+mpi_normalize( MPI a )
+{
+    for( ; a->nlimbs && !a->d[a->nlimbs-1]; a->nlimbs-- )
+       ;
+}
+
+
+
+/****************
+ * Return the number of bits in A.
+ */
+unsigned
+mpi_get_nbits( MPI a )
+{
+    unsigned n;
+
+    mpi_normalize( a );
+
+    if( a->nlimbs ) {
+       mpi_limb_t alimb = a->d[a->nlimbs-1];
+       if( alimb ) {
+         count_leading_zeros( n, alimb );
+       }
+       else
+           n = BITS_PER_MPI_LIMB;
+       n = BITS_PER_MPI_LIMB - n + (a->nlimbs-1) * BITS_PER_MPI_LIMB;
+    }
+    else
+       n = 0;
+    return n;
+}
+
+
+/****************
+ * Test whether bit N is set.
+ */
+int
+mpi_test_bit( MPI a, unsigned n )
+{
+    unsigned limbno, bitno;
+    mpi_limb_t limb;
+
+    limbno = n / BITS_PER_MPI_LIMB;
+    bitno  = n % BITS_PER_MPI_LIMB;
+
+    if( limbno >= a->nlimbs )
+       return 0; /* too far left: this is a 0 */
+    limb = a->d[limbno];
+    return (limb & (A_LIMB_1 << bitno))? 1: 0;
+}
+
+
+/****************
+ * Set bit N of A.
+ */
+int
+mpi_set_bit( MPI a, unsigned n )
+{
+    unsigned limbno, bitno;
+
+    limbno = n / BITS_PER_MPI_LIMB;
+    bitno  = n % BITS_PER_MPI_LIMB;
+
+    if( limbno >= a->nlimbs ) { /* resize */
+       if( a->alloced >= limbno )
+           if (mpi_resize(a, limbno+1 ) < 0) return -ENOMEM;
+       a->nlimbs = limbno+1;
+    }
+    a->d[limbno] |= (A_LIMB_1<<bitno);
+    return 0;
+}
+
+/****************
+ * Set bit N of A. and clear all bits above
+ */
+int
+mpi_set_highbit( MPI a, unsigned n )
+{
+    unsigned limbno, bitno;
+
+    limbno = n / BITS_PER_MPI_LIMB;
+    bitno  = n % BITS_PER_MPI_LIMB;
+
+    if( limbno >= a->nlimbs ) { /* resize */
+       if( a->alloced >= limbno )
+           if (mpi_resize(a, limbno+1 ) < 0) return -ENOMEM;
+       a->nlimbs = limbno+1;
+    }
+    a->d[limbno] |= (A_LIMB_1<<bitno);
+    for( bitno++; bitno < BITS_PER_MPI_LIMB; bitno++ )
+       a->d[limbno] &= ~(A_LIMB_1 << bitno);
+    a->nlimbs = limbno+1;
+    return 0;
+}
+
+/****************
+ * clear bit N of A and all bits above
+ */
+void
+mpi_clear_highbit( MPI a, unsigned n )
+{
+    unsigned limbno, bitno;
+
+    limbno = n / BITS_PER_MPI_LIMB;
+    bitno  = n % BITS_PER_MPI_LIMB;
+
+    if( limbno >= a->nlimbs )
+       return; /* not allocated, so need to clear bits :-) */
+
+    for( ; bitno < BITS_PER_MPI_LIMB; bitno++ )
+       a->d[limbno] &= ~(A_LIMB_1 << bitno);
+    a->nlimbs = limbno+1;
+}
+
+/****************
+ * Clear bit N of A.
+ */
+void
+mpi_clear_bit( MPI a, unsigned n )
+{
+    unsigned limbno, bitno;
+
+    limbno = n / BITS_PER_MPI_LIMB;
+    bitno  = n % BITS_PER_MPI_LIMB;
+
+    if( limbno >= a->nlimbs )
+       return; /* don't need to clear this bit, it's to far to left */
+    a->d[limbno] &= ~(A_LIMB_1 << bitno);
+}
+
+
+/****************
+ * Shift A by N bits to the right
+ * FIXME: should use alloc_limb if X and A are same.
+ */
+int
+mpi_rshift( MPI x, MPI a, unsigned n )
+{
+    mpi_ptr_t xp;
+    mpi_size_t xsize;
+
+    xsize = a->nlimbs;
+    x->sign = a->sign;
+    if (RESIZE_IF_NEEDED(x, (size_t)xsize) < 0) return -ENOMEM;
+    xp = x->d;
+
+    if( xsize ) {
+       mpihelp_rshift( xp, a->d, xsize, n);
+       MPN_NORMALIZE( xp, xsize);
+    }
+    x->nlimbs = xsize;
+    return 0;
+}
+
+
+/****************
+ * Shift A by COUNT limbs to the left
+ * This is used only within the MPI library
+ */
+int
+mpi_lshift_limbs( MPI a, unsigned int count )
+{
+    mpi_ptr_t ap = a->d;
+    int n = a->nlimbs;
+    int i;
+
+    if( !count || !n )
+       return 0;
+
+    if (RESIZE_IF_NEEDED( a, n+count ) < 0) return -ENOMEM;
+
+    for( i = n-1; i >= 0; i-- )
+       ap[i+count] = ap[i];
+    for(i=0; i < count; i++ )
+       ap[i] = 0;
+    a->nlimbs += count;
+    return 0;
+}
+
+
+/****************
+ * Shift A by COUNT limbs to the right
+ * This is used only within the MPI library
+ */
+void
+mpi_rshift_limbs( MPI a, unsigned int count )
+{
+    mpi_ptr_t ap = a->d;
+    mpi_size_t n = a->nlimbs;
+    unsigned int i;
+
+    if( count >= n ) {
+       a->nlimbs = 0;
+       return;
+    }
+
+    for( i = 0; i < n - count; i++ )
+       ap[i] = ap[i+count];
+    ap[i] = 0;
+    a->nlimbs -= count;
+}
+
+
diff --git a/crypto/mpi/mpi-cmp.c b/crypto/mpi/mpi-cmp.c
new file mode 100644 (file)
index 0000000..c183cd5
--- /dev/null
@@ -0,0 +1,71 @@
+/* mpi-cmp.c  -  MPI functions
+ * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "mpi-internal.h"
+
+int
+mpi_cmp_ui( MPI u, unsigned long v )
+{
+    mpi_limb_t limb = v;
+
+    mpi_normalize( u );
+    if( !u->nlimbs && !limb )
+       return 0;
+    if( u->sign )
+       return -1;
+    if( u->nlimbs > 1 )
+       return 1;
+
+    if( u->d[0] == limb )
+       return 0;
+    else if( u->d[0] > limb )
+       return 1;
+    else
+       return -1;
+}
+
+int
+mpi_cmp( MPI u, MPI v )
+{
+    mpi_size_t usize, vsize;
+    int cmp;
+
+    mpi_normalize( u );
+    mpi_normalize( v );
+    usize = u->nlimbs;
+    vsize = v->nlimbs;
+    if( !u->sign && v->sign )
+       return 1;
+    if( u->sign && !v->sign )
+       return -1;
+    if( usize != vsize && !u->sign && !v->sign )
+       return usize - vsize;
+    if( usize != vsize && u->sign && v->sign )
+       return vsize + usize;
+    if( !usize )
+       return 0;
+    if( !(cmp=mpihelp_cmp( u->d, v->d, usize )) )
+       return 0;
+    if( (cmp < 0?1:0) == (u->sign?1:0))
+       return 1;
+    return -1;
+}
+
+
diff --git a/crypto/mpi/mpi-div.c b/crypto/mpi/mpi-div.c
new file mode 100644 (file)
index 0000000..dee9146
--- /dev/null
@@ -0,0 +1,345 @@
+/* mpi-div.c  -  MPI functions
+ *     Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+ *     Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#include <linux/string.h>
+#include "mpi-internal.h"
+#include "longlong.h"
+
+
+int
+mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor )
+{
+       int rc = -ENOMEM;
+       int divisor_sign = divisor->sign;
+       MPI temp_divisor = NULL;
+
+       /* We need the original value of the divisor after the remainder has been
+        * preliminary calculated.      We have to copy it to temporary space if it's
+        * the same variable as REM.  */
+       if( rem == divisor ) {
+               if (mpi_copy( &temp_divisor, divisor ) < 0) goto nomem;
+               divisor = temp_divisor;
+       }
+
+       if (mpi_tdiv_qr(NULL, rem, dividend, divisor ) < 0) goto nomem;
+       if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs )
+               if (mpi_add( rem, rem, divisor) < 0) goto nomem;
+
+       rc = 0;
+
+ nomem:
+       if( temp_divisor )
+               mpi_free(temp_divisor);
+       return rc;
+}
+
+
+/****************
+ * Division rounding the quotient towards -infinity.
+ * The remainder gets the same sign as the denominator.
+ * rem is optional
+ */
+
+ulong
+mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor )
+{
+    mpi_limb_t rlimb;
+
+    rlimb = mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor );
+    if( rlimb && dividend->sign )
+       rlimb = divisor - rlimb;
+
+    if( rem ) {
+       rem->d[0] = rlimb;
+       rem->nlimbs = rlimb? 1:0;
+    }
+    return rlimb;
+}
+
+
+int
+mpi_fdiv_q( MPI quot, MPI dividend, MPI divisor )
+{
+    MPI tmp = mpi_alloc( mpi_get_nlimbs(quot) );
+    if (!tmp)
+           return -ENOMEM;
+    mpi_fdiv_qr( quot, tmp, dividend, divisor);
+    mpi_free(tmp);
+    return 0;
+}
+
+int
+mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor )
+{
+    int divisor_sign = divisor->sign;
+    MPI temp_divisor = NULL;
+
+    if( quot == divisor || rem == divisor ) {
+       if (mpi_copy( &temp_divisor, divisor ) < 0);
+       return -ENOMEM;
+       divisor = temp_divisor;
+    }
+
+    if (mpi_tdiv_qr( quot, rem, dividend, divisor ) < 0)
+           goto nomem;
+
+    if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) {
+           if (mpi_sub_ui( quot, quot, 1 ) < 0)
+                   goto nomem;
+           if (mpi_add( rem, rem, divisor) < 0)
+                   goto nomem;
+    }
+
+    if( temp_divisor )
+       mpi_free(temp_divisor);
+
+    return 0;
+
+ nomem:
+    mpi_free(temp_divisor);
+    return -ENOMEM;
+}
+
+
+/* If den == quot, den needs temporary storage.
+ * If den == rem, den needs temporary storage.
+ * If num == quot, num needs temporary storage.
+ * If den has temporary storage, it can be normalized while being copied,
+ *   i.e no extra storage should be allocated.
+ */
+
+int
+mpi_tdiv_r( MPI rem, MPI num, MPI den)
+{
+    return mpi_tdiv_qr(NULL, rem, num, den );
+}
+
+int
+mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
+{
+       int rc = -ENOMEM;
+       mpi_ptr_t np, dp;
+       mpi_ptr_t qp, rp;
+       mpi_size_t nsize = num->nlimbs;
+       mpi_size_t dsize = den->nlimbs;
+       mpi_size_t qsize, rsize;
+       mpi_size_t sign_remainder = num->sign;
+       mpi_size_t sign_quotient = num->sign ^ den->sign;
+       unsigned normalization_steps;
+       mpi_limb_t q_limb;
+       mpi_ptr_t marker[5];
+       int markidx=0;
+
+       memset(marker,0,sizeof(marker));
+
+       /* Ensure space is enough for quotient and remainder.
+        * We need space for an extra limb in the remainder, because it's
+        * up-shifted (normalized) below.  */
+       rsize = nsize + 1;
+       if (mpi_resize( rem, rsize) < 0) goto nomem;
+
+       qsize = rsize - dsize;    /* qsize cannot be bigger than this.  */
+       if( qsize <= 0 ) {
+               if( num != rem ) {
+                       rem->nlimbs = num->nlimbs;
+                       rem->sign = num->sign;
+                       MPN_COPY(rem->d, num->d, nsize);
+               }
+               if( quot ) {
+                       /* This needs to follow the assignment to rem, in case the
+                        * numerator and quotient are the same.  */
+                       quot->nlimbs = 0;
+                       quot->sign = 0;
+               }
+               return 0;
+       }
+
+       if( quot )
+               if (mpi_resize( quot, qsize) < 0) goto nomem;
+
+       /* Read pointers here, when reallocation is finished.  */
+       np = num->d;
+       dp = den->d;
+       rp = rem->d;
+
+       /* Optimize division by a single-limb divisor.  */
+       if( dsize == 1 ) {
+               mpi_limb_t rlimb;
+               if( quot ) {
+                       qp = quot->d;
+                       rlimb = mpihelp_divmod_1( qp, np, nsize, dp[0] );
+                       qsize -= qp[qsize - 1] == 0;
+                       quot->nlimbs = qsize;
+                       quot->sign = sign_quotient;
+               }
+               else
+                       rlimb = mpihelp_mod_1( np, nsize, dp[0] );
+               rp[0] = rlimb;
+               rsize = rlimb != 0?1:0;
+               rem->nlimbs = rsize;
+               rem->sign = sign_remainder;
+               return 0;
+       }
+
+
+       if( quot ) {
+               qp = quot->d;
+               /* Make sure QP and NP point to different objects.  Otherwise the
+                * numerator would be gradually overwritten by the quotient limbs.  */
+               if(qp == np) { /* Copy NP object to temporary space.  */
+                       np = marker[markidx++] = mpi_alloc_limb_space(nsize);
+                       MPN_COPY(np, qp, nsize);
+               }
+       }
+       else /* Put quotient at top of remainder. */
+               qp = rp + dsize;
+
+       count_leading_zeros( normalization_steps, dp[dsize - 1] );
+
+       /* Normalize the denominator, i.e. make its most significant bit set by
+        * shifting it NORMALIZATION_STEPS bits to the left.  Also shift the
+        * numerator the same number of steps (to keep the quotient the same!).
+        */
+       if( normalization_steps ) {
+               mpi_ptr_t tp;
+               mpi_limb_t nlimb;
+
+               /* Shift up the denominator setting the most significant bit of
+                * the most significant word.  Use temporary storage not to clobber
+                * the original contents of the denominator.  */
+               tp = marker[markidx++] = mpi_alloc_limb_space(dsize);
+               if (!tp) goto nomem;
+               mpihelp_lshift( tp, dp, dsize, normalization_steps );
+               dp = tp;
+
+               /* Shift up the numerator, possibly introducing a new most
+                * significant word.  Move the shifted numerator in the remainder
+                * meanwhile.  */
+               nlimb = mpihelp_lshift(rp, np, nsize, normalization_steps);
+               if( nlimb ) {
+                       rp[nsize] = nlimb;
+                       rsize = nsize + 1;
+               }
+               else
+                       rsize = nsize;
+       }
+       else {
+               /* The denominator is already normalized, as required.  Copy it to
+                * temporary space if it overlaps with the quotient or remainder.  */
+               if( dp == rp || (quot && (dp == qp))) {
+                       mpi_ptr_t tp;
+
+                       tp = marker[markidx++] = mpi_alloc_limb_space(dsize);
+                       if (!tp) goto nomem;
+                       MPN_COPY( tp, dp, dsize );
+                       dp = tp;
+               }
+
+               /* Move the numerator to the remainder.  */
+               if( rp != np )
+                       MPN_COPY(rp, np, nsize);
+
+               rsize = nsize;
+       }
+
+       q_limb = mpihelp_divrem( qp, 0, rp, rsize, dp, dsize );
+
+       if( quot ) {
+               qsize = rsize - dsize;
+               if(q_limb) {
+                       qp[qsize] = q_limb;
+                       qsize += 1;
+               }
+
+               quot->nlimbs = qsize;
+               quot->sign = sign_quotient;
+       }
+
+       rsize = dsize;
+       MPN_NORMALIZE (rp, rsize);
+
+       if( normalization_steps && rsize ) {
+               mpihelp_rshift(rp, rp, rsize, normalization_steps);
+               rsize -= rp[rsize - 1] == 0?1:0;
+       }
+
+       rem->nlimbs = rsize;
+       rem->sign       = sign_remainder;
+
+       rc = 0;
+ nomem:
+       while( markidx )
+               mpi_free_limb_space(marker[--markidx]);
+       return rc;
+}
+
+int
+mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count )
+{
+    mpi_size_t usize, wsize;
+    mpi_size_t limb_cnt;
+
+    usize = u->nlimbs;
+    limb_cnt = count / BITS_PER_MPI_LIMB;
+    wsize = usize - limb_cnt;
+    if( limb_cnt >= usize )
+       w->nlimbs = 0;
+    else {
+       mpi_ptr_t wp;
+       mpi_ptr_t up;
+
+       if (RESIZE_IF_NEEDED( w, wsize ) < 0)
+               return -ENOMEM;
+       wp = w->d;
+       up = u->d;
+
+       count %= BITS_PER_MPI_LIMB;
+       if( count ) {
+           mpihelp_rshift( wp, up + limb_cnt, wsize, count );
+           wsize -= !wp[wsize - 1];
+       }
+       else {
+           MPN_COPY_INCR( wp, up + limb_cnt, wsize);
+       }
+
+       w->nlimbs = wsize;
+    }
+    return 0;
+}
+
+/****************
+ * Check whether dividend is divisible by divisor
+ * (note: divisor must fit into a limb)
+ */
+int
+mpi_divisible_ui(MPI dividend, ulong divisor )
+{
+    return !mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor );
+}
+
diff --git a/crypto/mpi/mpi-gcd.c b/crypto/mpi/mpi-gcd.c
new file mode 100644 (file)
index 0000000..2841b9f
--- /dev/null
@@ -0,0 +1,60 @@
+/* mpi-gcd.c  -  MPI functions
+ * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "mpi-internal.h"
+
+/****************
+ * Find the greatest common divisor G of A and B.
+ * Return: true if this 1, false in all other cases
+ */
+int
+mpi_gcd( MPI g, const MPI xa, const MPI xb )
+{
+    MPI a = NULL, b = NULL;
+
+    if (mpi_copy(&a, xa) < 0)
+           goto nomem;
+
+    if (mpi_copy(&b, xb) < 0)
+           goto nomem;
+
+    /* TAOCP Vol II, 4.5.2, Algorithm A */
+    a->sign = 0;
+    b->sign = 0;
+    while( mpi_cmp_ui( b, 0 ) ) {
+           if (mpi_fdiv_r( g, a, b ) < 0) /* g used as temorary variable */
+                   goto nomem;
+           if (mpi_set(a,b) < 0)
+                   goto nomem;
+           if (mpi_set(b,g) < 0)
+                   goto nomem;
+    }
+    if (mpi_set(g, a) < 0)
+           goto nomem;
+
+    mpi_free(a);
+    mpi_free(b);
+    return !mpi_cmp_ui( g, 1);
+
+ nomem:
+    mpi_free(a);
+    mpi_free(b);
+    return -ENOMEM;
+}
diff --git a/crypto/mpi/mpi-inline.c b/crypto/mpi/mpi-inline.c
new file mode 100644 (file)
index 0000000..da53e2d
--- /dev/null
@@ -0,0 +1,33 @@
+/* mpi-inline.c
+ * Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+/* put the inline functions as real functions into the lib */
+#define G10_MPI_INLINE_DECL
+
+#include "mpi-internal.h"
+
+/* always include the header becuase it is only
+ * included by mpi-internal if __GCC__ is defined but we
+ * need it here in all cases and the above definition of
+ * of the macro allows us to do so
+ */
+#include "mpi-inline.h"
+
diff --git a/crypto/mpi/mpi-inline.h b/crypto/mpi/mpi-inline.h
new file mode 100644 (file)
index 0000000..02481b6
--- /dev/null
@@ -0,0 +1,128 @@
+/* mpi-inline.h  -  Internal to the Multi Precision Integers
+ *     Copyright (C) 1994, 1996, 1998, 1999 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#ifndef G10_MPI_INLINE_H
+#define G10_MPI_INLINE_H
+
+#ifndef G10_MPI_INLINE_DECL
+  #define G10_MPI_INLINE_DECL  extern __inline__
+#endif
+
+G10_MPI_INLINE_DECL  mpi_limb_t
+mpihelp_add_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
+              mpi_size_t s1_size, mpi_limb_t s2_limb)
+{
+    mpi_limb_t x;
+
+    x = *s1_ptr++;
+    s2_limb += x;
+    *res_ptr++ = s2_limb;
+    if( s2_limb < x ) { /* sum is less than the left operand: handle carry */
+       while( --s1_size ) {
+           x = *s1_ptr++ + 1;  /* add carry */
+           *res_ptr++ = x;     /* and store */
+           if( x )             /* not 0 (no overflow): we can stop */
+               goto leave;
+       }
+       return 1; /* return carry (size of s1 to small) */
+    }
+
+  leave:
+    if( res_ptr != s1_ptr ) { /* not the same variable */
+       mpi_size_t i;          /* copy the rest */
+       for( i=0; i < s1_size-1; i++ )
+           res_ptr[i] = s1_ptr[i];
+    }
+    return 0; /* no carry */
+}
+
+
+
+G10_MPI_INLINE_DECL mpi_limb_t
+mpihelp_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
+                              mpi_ptr_t s2_ptr, mpi_size_t s2_size)
+{
+    mpi_limb_t cy = 0;
+
+    if( s2_size )
+       cy = mpihelp_add_n( res_ptr, s1_ptr, s2_ptr, s2_size );
+
+    if( s1_size - s2_size )
+       cy = mpihelp_add_1( res_ptr + s2_size, s1_ptr + s2_size,
+                           s1_size - s2_size, cy);
+    return cy;
+}
+
+
+G10_MPI_INLINE_DECL mpi_limb_t
+mpihelp_sub_1(mpi_ptr_t res_ptr,  mpi_ptr_t s1_ptr,
+             mpi_size_t s1_size, mpi_limb_t s2_limb )
+{
+    mpi_limb_t x;
+
+    x = *s1_ptr++;
+    s2_limb = x - s2_limb;
+    *res_ptr++ = s2_limb;
+    if( s2_limb > x ) {
+       while( --s1_size ) {
+           x = *s1_ptr++;
+           *res_ptr++ = x - 1;
+           if( x )
+               goto leave;
+       }
+       return 1;
+    }
+
+  leave:
+    if( res_ptr != s1_ptr ) {
+       mpi_size_t i;
+       for( i=0; i < s1_size-1; i++ )
+           res_ptr[i] = s1_ptr[i];
+    }
+    return 0;
+}
+
+
+
+G10_MPI_INLINE_DECL   mpi_limb_t
+mpihelp_sub( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
+                               mpi_ptr_t s2_ptr, mpi_size_t s2_size)
+{
+    mpi_limb_t cy = 0;
+
+    if( s2_size )
+       cy = mpihelp_sub_n(res_ptr, s1_ptr, s2_ptr, s2_size);
+
+    if( s1_size - s2_size )
+       cy = mpihelp_sub_1(res_ptr + s2_size, s1_ptr + s2_size,
+                                     s1_size - s2_size, cy);
+    return cy;
+}
+
+
+#endif /*G10_MPI_INLINE_H*/
diff --git a/crypto/mpi/mpi-internal.h b/crypto/mpi/mpi-internal.h
new file mode 100644 (file)
index 0000000..9ed7166
--- /dev/null
@@ -0,0 +1,265 @@
+/* mpi-internal.h  -  Internal to the Multi Precision Integers
+ *     Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+ *     Copyright (C) 1998, 2000 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#ifndef G10_MPI_INTERNAL_H
+#define G10_MPI_INTERNAL_H
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/crypto/mpi.h>
+#include <asm/errno.h>
+
+#define log_debug printk
+#define log_bug printk
+
+#define assert(x) do { \
+               if (!x) log_bug("failed assertion\n"); \
+              } while(0);
+
+/* If KARATSUBA_THRESHOLD is not already defined, define it to a
+ * value which is good on most machines.  */
+
+/* tested 4, 16, 32 and 64, where 16 gave the best performance when
+ * checking a 768 and a 1024 bit ElGamal signature.
+ * (wk 22.12.97) */
+#ifndef KARATSUBA_THRESHOLD
+    #define KARATSUBA_THRESHOLD 16
+#endif
+
+/* The code can't handle KARATSUBA_THRESHOLD smaller than 2.  */
+#if KARATSUBA_THRESHOLD < 2
+    #undef KARATSUBA_THRESHOLD
+    #define KARATSUBA_THRESHOLD 2
+#endif
+
+
+typedef mpi_limb_t *mpi_ptr_t; /* pointer to a limb */
+typedef int mpi_size_t;        /* (must be a signed type) */
+
+#define ABS(x) (x >= 0 ? x : -x)
+#define MIN(l,o) ((l) < (o) ? (l) : (o))
+#define MAX(h,i) ((h) > (i) ? (h) : (i))
+
+static inline int RESIZE_IF_NEEDED(MPI a, unsigned b)
+{
+       if (a->alloced < b)
+               return mpi_resize(a,b);
+       return 0;
+}
+
+/* Copy N limbs from S to D.  */
+#define MPN_COPY( d, s, n) \
+    do {                               \
+       mpi_size_t _i;                  \
+       for( _i = 0; _i < (n); _i++ )   \
+           (d)[_i] = (s)[_i];          \
+    } while(0)
+
+#define MPN_COPY_INCR( d, s, n)        \
+    do {                               \
+       mpi_size_t _i;                  \
+       for( _i = 0; _i < (n); _i++ )   \
+           (d)[_i] = (d)[_i];          \
+    } while (0)
+
+#define MPN_COPY_DECR( d, s, n ) \
+    do {                               \
+       mpi_size_t _i;                  \
+       for( _i = (n)-1; _i >= 0; _i--) \
+          (d)[_i] = (s)[_i];           \
+    } while(0)
+
+/* Zero N limbs at D */
+#define MPN_ZERO(d, n) \
+    do {                                 \
+       int  _i;                          \
+       for( _i = 0; _i < (n); _i++ )  \
+           (d)[_i] = 0;                    \
+    } while (0)
+
+#define MPN_NORMALIZE(d, n)  \
+    do {                      \
+       while( (n) > 0 ) {     \
+           if( (d)[(n)-1] ) \
+               break;         \
+           (n)--;             \
+       }                      \
+    } while(0)
+
+#define MPN_NORMALIZE_NOT_ZERO(d, n) \
+    do {                                   \
+       for(;;) {                           \
+           if( (d)[(n)-1] )                \
+               break;                      \
+           (n)--;                          \
+       }                                   \
+    } while(0)
+
+#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \
+    do {                                               \
+       if( (size) < KARATSUBA_THRESHOLD )              \
+           mul_n_basecase (prodp, up, vp, size);       \
+       else                                            \
+           mul_n (prodp, up, vp, size, tspace);        \
+    } while (0);
+
+
+/* Divide the two-limb number in (NH,,NL) by D, with DI being the largest
+ * limb not larger than (2**(2*BITS_PER_MP_LIMB))/D - (2**BITS_PER_MP_LIMB).
+ * If this would yield overflow, DI should be the largest possible number
+ * (i.e., only ones).  For correct operation, the most significant bit of D
+ * has to be set.  Put the quotient in Q and the remainder in R.
+ */
+#define UDIV_QRNND_PREINV(q, r, nh, nl, d, di) \
+    do {                                                           \
+       mpi_limb_t _q, _ql, _r;                                     \
+       mpi_limb_t _xh, _xl;                                        \
+       umul_ppmm (_q, _ql, (nh), (di));                            \
+       _q += (nh);     /* DI is 2**BITS_PER_MPI_LIMB too small */  \
+       umul_ppmm (_xh, _xl, _q, (d));                              \
+       sub_ddmmss (_xh, _r, (nh), (nl), _xh, _xl);                 \
+       if( _xh ) {                                                 \
+           sub_ddmmss (_xh, _r, _xh, _r, 0, (d));                  \
+           _q++;                                                   \
+           if( _xh) {                                              \
+               sub_ddmmss (_xh, _r, _xh, _r, 0, (d));              \
+               _q++;                                               \
+           }                                                       \
+       }                                                           \
+       if( _r >= (d) ) {                                           \
+           _r -= (d);                                              \
+           _q++;                                                   \
+       }                                                           \
+       (r) = _r;                                                   \
+       (q) = _q;                                                   \
+    } while (0)
+
+
+/*-- mpiutil.c --*/
+mpi_ptr_t mpi_alloc_limb_space( unsigned nlimbs );
+void mpi_free_limb_space( mpi_ptr_t a );
+void mpi_assign_limb_space( MPI a, mpi_ptr_t ap, unsigned nlimbs );
+
+/*-- mpi-bit.c --*/
+void mpi_rshift_limbs( MPI a, unsigned int count );
+int mpi_lshift_limbs( MPI a, unsigned int count );
+
+
+/*-- mpihelp-add.c --*/
+mpi_limb_t mpihelp_add_1(mpi_ptr_t res_ptr,  mpi_ptr_t s1_ptr,
+                        mpi_size_t s1_size, mpi_limb_t s2_limb );
+mpi_limb_t mpihelp_add_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
+                         mpi_ptr_t s2_ptr,  mpi_size_t size);
+mpi_limb_t mpihelp_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
+                      mpi_ptr_t s2_ptr, mpi_size_t s2_size);
+
+/*-- mpihelp-sub.c --*/
+mpi_limb_t mpihelp_sub_1( mpi_ptr_t res_ptr,  mpi_ptr_t s1_ptr,
+                         mpi_size_t s1_size, mpi_limb_t s2_limb );
+mpi_limb_t mpihelp_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
+                         mpi_ptr_t s2_ptr, mpi_size_t size);
+mpi_limb_t mpihelp_sub(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
+                      mpi_ptr_t s2_ptr, mpi_size_t s2_size);
+
+/*-- mpihelp-cmp.c --*/
+int mpihelp_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size );
+
+/*-- mpihelp-mul.c --*/
+
+struct karatsuba_ctx {
+    struct karatsuba_ctx *next;
+    mpi_ptr_t tspace;
+    mpi_size_t tspace_size;
+    mpi_ptr_t tp;
+    mpi_size_t tp_size;
+};
+
+void mpihelp_release_karatsuba_ctx( struct karatsuba_ctx *ctx );
+
+mpi_limb_t mpihelp_addmul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
+                            mpi_size_t s1_size, mpi_limb_t s2_limb);
+mpi_limb_t mpihelp_submul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
+                            mpi_size_t s1_size, mpi_limb_t s2_limb);
+int mpihelp_mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp,
+                                                  mpi_size_t size);
+int mpihelp_mul( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize,
+                mpi_ptr_t vp, mpi_size_t vsize, mpi_limb_t *_result);
+void mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size );
+void mpih_sqr_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size,
+                                               mpi_ptr_t tspace);
+
+int mpihelp_mul_karatsuba_case( mpi_ptr_t prodp,
+                                mpi_ptr_t up, mpi_size_t usize,
+                                mpi_ptr_t vp, mpi_size_t vsize,
+                                struct karatsuba_ctx *ctx );
+
+
+/*-- mpihelp-mul_1.c (or xxx/cpu/ *.S) --*/
+mpi_limb_t mpihelp_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
+                         mpi_size_t s1_size, mpi_limb_t s2_limb);
+
+/*-- mpihelp-div.c --*/
+mpi_limb_t mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size,
+                                                mpi_limb_t divisor_limb);
+mpi_limb_t mpihelp_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs,
+                          mpi_ptr_t np, mpi_size_t nsize,
+                          mpi_ptr_t dp, mpi_size_t dsize);
+mpi_limb_t mpihelp_divmod_1( mpi_ptr_t quot_ptr,
+                            mpi_ptr_t dividend_ptr, mpi_size_t dividend_size,
+                            mpi_limb_t divisor_limb);
+
+/*-- mpihelp-shift.c --*/
+mpi_limb_t mpihelp_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
+                                                          unsigned cnt);
+mpi_limb_t mpihelp_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
+                                                          unsigned cnt);
+
+
+/* Define stuff for longlong.h.  */
+#define W_TYPE_SIZE BITS_PER_MPI_LIMB
+  typedef mpi_limb_t   UWtype;
+  typedef unsigned int UHWtype;
+#if defined (__GNUC__)
+  typedef unsigned int UQItype   __attribute__ ((mode (QI)));
+  typedef         int SItype     __attribute__ ((mode (SI)));
+  typedef unsigned int USItype   __attribute__ ((mode (SI)));
+  typedef         int DItype     __attribute__ ((mode (DI)));
+  typedef unsigned int UDItype   __attribute__ ((mode (DI)));
+#else
+  typedef unsigned char UQItype;
+  typedef         long SItype;
+  typedef unsigned long USItype;
+#endif
+
+#ifdef __GNUC__
+  #include "mpi-inline.h"
+#endif
+
+#endif /*G10_MPI_INTERNAL_H*/
diff --git a/crypto/mpi/mpi-inv.c b/crypto/mpi/mpi-inv.c
new file mode 100644 (file)
index 0000000..0e0f282
--- /dev/null
@@ -0,0 +1,148 @@
+/* mpi-inv.c  -  MPI functions
+ * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "mpi-internal.h"
+
+
+/****************
+ * Calculate the multiplicative inverse X of A mod N
+ * That is: Find the solution x for
+ *             1 = (a*x) mod n
+ */
+int
+mpi_invm( MPI x, const MPI a, const MPI n )
+{
+       /* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X)
+        * modified according to Michael Penk's solution for Exercice 35
+        * with further enhancement */
+       MPI u = NULL, v = NULL;
+       MPI u1 = NULL, u2 = NULL, u3 = NULL;
+       MPI v1 = NULL, v2 = NULL, v3 = NULL;
+       MPI t1 = NULL, t2 = NULL, t3 = NULL;
+       unsigned k;
+       int sign;
+       int odd = 0;
+       int rc = -ENOMEM;
+
+       if (mpi_copy(&u, a) < 0) goto cleanup;
+       if (mpi_copy(&v, n) < 0) goto cleanup;
+
+       for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) {
+               if (mpi_rshift(u, u, 1) < 0) goto cleanup;
+               if (mpi_rshift(v, v, 1) < 0) goto cleanup;
+       }
+       odd = mpi_test_bit(v,0);
+
+       u1 = mpi_alloc_set_ui(1); if (!u1) goto cleanup;
+       if( !odd ) {
+               u2 = mpi_alloc_set_ui(0);
+               if (!u2) goto cleanup;
+       }
+       if (mpi_copy(&u3, u) < 0) goto cleanup;
+       if (mpi_copy(&v1, v) < 0) goto cleanup;
+       if( !odd ) {
+               v2 = mpi_alloc( mpi_get_nlimbs(u) );  if (!v2) goto cleanup;
+               if (mpi_sub( v2, u1, u ) < 0) goto cleanup; /* U is used as const 1 */
+       }
+       if (mpi_copy(&v3, v) < 0) goto cleanup;
+       if( mpi_test_bit(u, 0) ) { /* u is odd */
+               t1 = mpi_alloc_set_ui(0); if (!t1) goto cleanup;
+               if( !odd ) {
+                       t2 = mpi_alloc_set_ui(1); if (!t2) goto cleanup;
+                       t2->sign = 1; 
+               }
+               if (mpi_copy(&t3, v) < 0) goto cleanup;
+               t3->sign = !t3->sign;
+               goto Y4;
+       }
+       else {
+               t1 = mpi_alloc_set_ui(1); if (!t1) goto cleanup;
+               if( !odd ) {
+                       t2 = mpi_alloc_set_ui(0); if (!t2) goto cleanup;
+               }
+               if (mpi_copy(&t3, u) < 0) goto cleanup;
+       }
+       do {
+               do {
+                       if( !odd ) {
+                               if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */
+                                       if (mpi_add(t1, t1, v) < 0) goto cleanup;
+                                       if (mpi_sub(t2, t2, u) < 0) goto cleanup;
+                               }
+                               if (mpi_rshift(t1, t1, 1) < 0) goto cleanup;
+                               if (mpi_rshift(t2, t2, 1) < 0) goto cleanup;
+                               if (mpi_rshift(t3, t3, 1) < 0) goto cleanup;
+                       }
+                       else {
+                               if( mpi_test_bit(t1, 0) )
+                                       if (mpi_add(t1, t1, v) < 0) goto cleanup;
+                               if (mpi_rshift(t1, t1, 1) < 0) goto cleanup;
+                               if (mpi_rshift(t3, t3, 1) < 0) goto cleanup;
+                       }
+               Y4:
+                       ;
+               } while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */
+
+               if( !t3->sign ) {
+                       if (mpi_set(u1, t1) < 0) goto cleanup;
+                       if( !odd )
+                               if (mpi_set(u2, t2) < 0) goto cleanup;
+                       if (mpi_set(u3, t3) < 0) goto cleanup;
+               }
+               else {
+                       if (mpi_sub(v1, v, t1) < 0) goto cleanup;
+                       sign = u->sign; u->sign = !u->sign;
+                       if( !odd )
+                               if (mpi_sub(v2, u, t2) < 0) goto cleanup;
+                       u->sign = sign;
+                       sign = t3->sign; t3->sign = !t3->sign;
+                       if (mpi_set(v3, t3) < 0) goto cleanup;
+                       t3->sign = sign;
+               }
+               if (mpi_sub(t1, u1, v1) < 0) goto cleanup;
+               if( !odd )
+                       if (mpi_sub(t2, u2, v2) < 0) goto cleanup;
+               if (mpi_sub(t3, u3, v3) < 0) goto cleanup;
+               if( t1->sign ) {
+                       if (mpi_add(t1, t1, v) < 0) goto cleanup;
+                       if( !odd )
+                               if (mpi_sub(t2, t2, u) < 0) goto cleanup;
+               }
+       } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */
+       /* mpi_lshift( u3, k ); */
+       rc = mpi_set(x, u1);
+
+ cleanup:
+       mpi_free(u1);
+       mpi_free(v1);
+       mpi_free(t1);
+       if( !odd ) {
+               mpi_free(u2);
+               mpi_free(v2);
+               mpi_free(t2);
+       }
+       mpi_free(u3);
+       mpi_free(v3);
+       mpi_free(t3);
+
+       mpi_free(u);
+       mpi_free(v);
+       return rc;
+}
diff --git a/crypto/mpi/mpi-mpow.c b/crypto/mpi/mpi-mpow.c
new file mode 100644 (file)
index 0000000..eb6d3c7
--- /dev/null
@@ -0,0 +1,113 @@
+/* mpi-mpow.c  -  MPI functions
+ * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "mpi-internal.h"
+#include "longlong.h"
+
+
+static int
+build_index(const MPI *exparray, int k, int i, int t )
+{
+    int j, bitno;
+    int index = 0;
+
+    bitno = t-i;
+    for(j=k-1; j >= 0; j-- ) {
+       index <<= 1;
+       if( mpi_test_bit( exparray[j], bitno ) )
+           index |= 1;
+    }
+    return index;
+}
+
+/****************
+ * RES = (BASE[0] ^ EXP[0]) *  (BASE[1] ^ EXP[1]) * ... * mod M
+ */
+int
+mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI m)
+{
+       int rc = -ENOMEM;
+       int k;  /* number of elements */
+       int t;  /* bit size of largest exponent */
+       int i, j, idx;
+       MPI *G = NULL;  /* table with precomputed values of size 2^k */
+       MPI tmp = NULL;
+
+       for(k=0; basearray[k]; k++ )
+               ;
+       if (!k) { printk("mpi_mulpowm: assert(k) failed\n"); BUG(); }
+       for(t=0, i=0; (tmp=exparray[i]); i++ ) {
+               j = mpi_get_nbits(tmp);
+               if( j > t )
+                       t = j;
+       }
+       if (i!=k) { printk("mpi_mulpowm: assert(i==k) failed\n"); BUG(); }
+       if (!t)   { printk("mpi_mulpowm: assert(t) failed\n"); BUG(); }
+       if (k>=10) { printk("mpi_mulpowm: assert(k<10) failed\n"); BUG(); }
+
+       G = kmalloc( (1<<k) * sizeof *G, GFP_KERNEL );
+       if (!G) goto nomem;
+       memset(G,0,(1<<k) * sizeof *G);
+       /* and calculate */
+       tmp =  mpi_alloc( mpi_get_nlimbs(m)+1 ); if (!tmp) goto nomem;
+       if (mpi_set_ui( res, 1 ) < 0) goto nomem;
+       for(i = 1; i <= t; i++ ) {
+               if (mpi_mulm(tmp, res, res, m ) < 0) goto nomem;
+               idx = build_index( exparray, k, i, t );
+               if (!(idx >= 0 && idx < (1<<k))) {
+                       printk("mpi_mulpowm: assert(idx >= 0 && idx < (1<<k)) failed\n");
+                       BUG();
+               }
+               if( !G[idx] ) {
+                       if( !idx ) {
+                               G[0] = mpi_alloc_set_ui( 1 );
+                               if (!G[0]) goto nomem;
+                       }
+                       else {
+                               for(j=0; j < k; j++ ) {
+                                       if( (idx & (1<<j) ) ) {
+                                               if( !G[idx] ) {
+                                                       if (mpi_copy( &G[idx], basearray[j] ) < 0)
+                                                               goto nomem;
+                                               }
+                                               else {
+                                                       if (mpi_mulm(G[idx],G[idx],basearray[j],m) < 0)
+                                                               goto nomem;
+                                               }
+                                       }
+                               }
+                               if( !G[idx] ) {
+                                       G[idx] = mpi_alloc(0);
+                                       if (!G[idx]) goto nomem;
+                               }
+                       }
+               }
+               if (mpi_mulm(res, tmp, G[idx], m ) < 0) goto nomem;
+       }
+
+       rc = 0;
+ nomem:
+       /* cleanup */
+       mpi_free(tmp);
+       for(i=0; i < (1<<k); i++ )
+               mpi_free(G[i]);
+       kfree(G);
+       return rc;
+}
diff --git a/crypto/mpi/mpi-mul.c b/crypto/mpi/mpi-mul.c
new file mode 100644 (file)
index 0000000..14fd2a4
--- /dev/null
@@ -0,0 +1,202 @@
+/* mpi-mul.c  -  MPI functions
+ *     Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+ *     Copyright (C) 1998, 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#include "mpi-internal.h"
+
+
+int
+mpi_mul_ui( MPI prod, MPI mult, unsigned long small_mult )
+{
+    mpi_size_t size, prod_size;
+    mpi_ptr_t  prod_ptr;
+    mpi_limb_t cy;
+    int sign;
+
+    size = mult->nlimbs;
+    sign = mult->sign;
+
+    if( !size || !small_mult ) {
+       prod->nlimbs = 0;
+       prod->sign = 0;
+       return 0;
+    }
+
+    prod_size = size + 1;
+    if( prod->alloced < prod_size )
+           if (mpi_resize( prod, prod_size ) < 0)
+                   return -ENOMEM;
+    prod_ptr = prod->d;
+
+    cy = mpihelp_mul_1( prod_ptr, mult->d, size, (mpi_limb_t)small_mult );
+    if( cy )
+       prod_ptr[size++] = cy;
+    prod->nlimbs = size;
+    prod->sign = sign;
+    return 0;
+}
+
+
+int
+mpi_mul_2exp( MPI w, MPI u, unsigned long cnt)
+{
+    mpi_size_t usize, wsize, limb_cnt;
+    mpi_ptr_t wp;
+    mpi_limb_t wlimb;
+    int usign, wsign;
+
+    usize = u->nlimbs;
+    usign = u->sign;
+
+    if( !usize ) {
+       w->nlimbs = 0;
+       w->sign = 0;
+       return 0;
+    }
+
+    limb_cnt = cnt / BITS_PER_MPI_LIMB;
+    wsize = usize + limb_cnt + 1;
+    if( w->alloced < wsize )
+           if (mpi_resize(w, wsize ) < 0)
+                   return -ENOMEM;
+    wp = w->d;
+    wsize = usize + limb_cnt;
+    wsign = usign;
+
+    cnt %= BITS_PER_MPI_LIMB;
+    if( cnt ) {
+       wlimb = mpihelp_lshift( wp + limb_cnt, u->d, usize, cnt );
+       if( wlimb ) {
+           wp[wsize] = wlimb;
+           wsize++;
+       }
+    }
+    else {
+       MPN_COPY_DECR( wp + limb_cnt, u->d, usize );
+    }
+
+    /* Zero all whole limbs at low end.  Do it here and not before calling
+     * mpn_lshift, not to lose for U == W.  */
+    MPN_ZERO( wp, limb_cnt );
+
+    w->nlimbs = wsize;
+    w->sign = wsign;
+    return 0;
+}
+
+int
+mpi_mul( MPI w, MPI u, MPI v)
+{
+       int rc = -ENOMEM;
+       mpi_size_t usize, vsize, wsize;
+       mpi_ptr_t up, vp, wp;
+       mpi_limb_t cy;
+       int usign, vsign, sign_product;
+       int assign_wp=0;
+       mpi_ptr_t tmp_limb=NULL;
+
+
+       if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */
+               usize = v->nlimbs;
+               usign = v->sign;
+               up    = v->d;
+               vsize = u->nlimbs;
+               vsign = u->sign;
+               vp    = u->d;
+       }
+       else {
+               usize = u->nlimbs;
+               usign = u->sign;
+               up    = u->d;
+               vsize = v->nlimbs;
+               vsign = v->sign;
+               vp    = v->d;
+       }
+       sign_product = usign ^ vsign;
+       wp = w->d;
+
+       /* Ensure W has space enough to store the result.  */
+       wsize = usize + vsize;
+       if( w->alloced < (size_t)wsize ) {
+               if( wp == up || wp == vp ) {
+                       wp = mpi_alloc_limb_space(wsize);
+                       if (!wp) goto nomem;
+                       assign_wp = 1;
+               }
+               else {
+                       if (mpi_resize(w, wsize ) < 0) goto nomem;
+                       wp = w->d;
+               }
+       }
+       else { /* Make U and V not overlap with W.      */
+               if( wp == up ) {
+                       /* W and U are identical.  Allocate temporary space for U.      */
+                       up = tmp_limb = mpi_alloc_limb_space( usize);
+                       if (!up) goto nomem;
+                       /* Is V identical too?  Keep it identical with U.  */
+                       if( wp == vp )
+                               vp = up;
+                       /* Copy to the temporary space.  */
+                       MPN_COPY( up, wp, usize );
+               }
+               else if( wp == vp ) {
+                       /* W and V are identical.  Allocate temporary space for V.      */
+                       vp = tmp_limb = mpi_alloc_limb_space( vsize);
+                       if (!vp) goto nomem;
+                       /* Copy to the temporary space.  */
+                       MPN_COPY( vp, wp, vsize );
+               }
+       }
+
+       if( !vsize )
+               wsize = 0;
+       else {
+               if (mpihelp_mul( wp, up, usize, vp, vsize, &cy) < 0)
+                       goto nomem;
+               wsize -= cy? 0:1;
+       }
+
+       if( assign_wp )
+               mpi_assign_limb_space( w, wp, wsize );
+
+       w->nlimbs = wsize;
+       w->sign = sign_product;
+       rc = 0;
+ nomem:
+       if( tmp_limb )
+               mpi_free_limb_space( tmp_limb );
+       return rc;
+}
+
+int
+mpi_mulm( MPI w, MPI u, MPI v, MPI m)
+{
+       if (mpi_mul(w, u, v) < 0)
+               return -ENOMEM;
+       return mpi_fdiv_r( w, w, m );
+}
diff --git a/crypto/mpi/mpi-pow.c b/crypto/mpi/mpi-pow.c
new file mode 100644 (file)
index 0000000..fa0efa5
--- /dev/null
@@ -0,0 +1,312 @@
+/* mpi-pow.c  -  MPI functions
+ *     Copyright (C) 1994, 1996, 1998, 2000 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#include <linux/string.h>
+#include "mpi-internal.h"
+#include "longlong.h"
+
+
+/****************
+ * RES = BASE ^ EXP mod MOD
+ */
+int
+mpi_powm( MPI res, MPI base, MPI exp, MPI mod)
+{
+    mpi_ptr_t mp_marker=NULL, bp_marker=NULL, ep_marker=NULL;
+    mpi_ptr_t xp_marker=NULL;
+    mpi_ptr_t tspace = NULL;
+    mpi_ptr_t  rp, ep, mp, bp;
+    mpi_size_t esize, msize, bsize, rsize;
+    int        esign, msign, bsign, rsign;
+    mpi_size_t size;
+    int mod_shift_cnt;
+    int negative_result;
+    int assign_rp=0;
+    mpi_size_t tsize=0;   /* to avoid compiler warning */
+                         /* fixme: we should check that the warning is void*/
+    int rc = -ENOMEM;
+
+    esize = exp->nlimbs;
+    msize = mod->nlimbs;
+    size = 2 * msize;
+    esign = exp->sign;
+    msign = mod->sign;
+
+    rp = res->d;
+    ep = exp->d;
+
+    if( !msize )
+       msize = 1 / msize;          /* provoke a signal */
+
+    if( !esize ) {
+       /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0
+        * depending on if MOD equals 1.  */
+       rp[0] = 1;
+       res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1;
+       res->sign = 0;
+       goto leave;
+    }
+
+    /* Normalize MOD (i.e. make its most significant bit set) as required by
+     * mpn_divrem.  This will make the intermediate values in the calculation
+     * slightly larger, but the correct result is obtained after a final
+     * reduction using the original MOD value. */
+    mp = mp_marker = mpi_alloc_limb_space(msize);
+    if (!mp)
+           goto enomem;
+    count_leading_zeros( mod_shift_cnt, mod->d[msize-1] );
+    if( mod_shift_cnt )
+       mpihelp_lshift( mp, mod->d, msize, mod_shift_cnt );
+    else
+       MPN_COPY( mp, mod->d, msize );
+
+    bsize = base->nlimbs;
+    bsign = base->sign;
+    if( bsize > msize ) { /* The base is larger than the module. Reduce it. */
+       /* Allocate (BSIZE + 1) with space for remainder and quotient.
+        * (The quotient is (bsize - msize + 1) limbs.)  */
+       bp = bp_marker = mpi_alloc_limb_space( bsize + 1);
+       if (!bp)
+               goto enomem;
+       MPN_COPY( bp, base->d, bsize );
+       /* We don't care about the quotient, store it above the remainder,
+        * at BP + MSIZE.  */
+       mpihelp_divrem( bp + msize, 0, bp, bsize, mp, msize );
+       bsize = msize;
+       /* Canonicalize the base, since we are going to multiply with it
+        * quite a few times.  */
+       MPN_NORMALIZE( bp, bsize );
+    }
+    else
+       bp = base->d;
+
+    if( !bsize ) {
+       res->nlimbs = 0;
+       res->sign = 0;
+       goto leave;
+    }
+
+    if( res->alloced < size ) {
+       /* We have to allocate more space for RES.  If any of the input
+        * parameters are identical to RES, defer deallocation of the old
+        * space.  */
+       if( rp == ep || rp == mp || rp == bp ) {
+           rp = mpi_alloc_limb_space(size);
+           if (!rp)
+                   goto enomem;
+           assign_rp = 1;
+       }
+       else {
+               if (mpi_resize( res, size ) < 0)
+                       goto enomem;
+           rp = res->d;
+       }
+    }
+    else { /* Make BASE, EXP and MOD not overlap with RES.  */
+       if( rp == bp ) {
+           /* RES and BASE are identical.  Allocate temp. space for BASE.  */
+               BUG_ON(bp_marker);
+           bp = bp_marker = mpi_alloc_limb_space(bsize);
+           if (!bp)
+                   goto enomem;
+           MPN_COPY(bp, rp, bsize);
+       }
+       if( rp == ep ) {
+           /* RES and EXP are identical.  Allocate temp. space for EXP.  */
+           ep = ep_marker = mpi_alloc_limb_space(esize);
+           if (!ep)
+                   goto enomem;  
+           MPN_COPY(ep, rp, esize);
+       }
+       if( rp == mp ) {
+           /* RES and MOD are identical.  Allocate temporary space for MOD.*/
+           BUG_ON(mp_marker);
+           mp = mp_marker = mpi_alloc_limb_space(msize);
+           if (!mp)
+                   goto enomem;
+           MPN_COPY(mp, rp, msize);
+       }
+    }
+
+    MPN_COPY( rp, bp, bsize );
+    rsize = bsize;
+    rsign = bsign;
+
+    {
+       mpi_size_t i;
+       mpi_ptr_t xp;
+       int c;
+       mpi_limb_t e;
+       mpi_limb_t carry_limb;
+       struct karatsuba_ctx karactx;
+
+       xp = xp_marker = mpi_alloc_limb_space(2 * (msize + 1));
+       if (xp)
+               goto enomem;
+
+       memset( &karactx, 0, sizeof karactx );
+       negative_result = (ep[0] & 1) && base->sign;
+
+       i = esize - 1;
+       e = ep[i];
+       count_leading_zeros (c, e);
+       e = (e << c) << 1;     /* shift the exp bits to the left, lose msb */
+       c = BITS_PER_MPI_LIMB - 1 - c;
+
+       /* Main loop.
+        *
+        * Make the result be pointed to alternately by XP and RP.  This
+        * helps us avoid block copying, which would otherwise be necessary
+        * with the overlap restrictions of mpihelp_divmod. With 50% probability
+        * the result after this loop will be in the area originally pointed
+        * by RP (==RES->d), and with 50% probability in the area originally
+        * pointed to by XP.
+        */
+
+       for(;;) {
+           while( c ) {
+               mpi_ptr_t tp;
+               mpi_size_t xsize;
+
+               /*if (mpihelp_mul_n(xp, rp, rp, rsize) < 0) goto enomem */
+               if( rsize < KARATSUBA_THRESHOLD )
+                   mpih_sqr_n_basecase( xp, rp, rsize );
+               else {
+                   if( !tspace ) {
+                       tsize = 2 * rsize;
+                       tspace = mpi_alloc_limb_space(tsize);
+                       if (!tspace)
+                               goto enomem;
+                   }
+                   else if( tsize < (2*rsize) ) {
+                       mpi_free_limb_space( tspace );
+                       tsize = 2 * rsize;
+                       tspace = mpi_alloc_limb_space(tsize);
+                       if (!tspace)
+                               goto enomem;
+                   }
+                   mpih_sqr_n( xp, rp, rsize, tspace );
+               }
+
+               xsize = 2 * rsize;
+               if( xsize > msize ) {
+                   mpihelp_divrem(xp + msize, 0, xp, xsize, mp, msize);
+                   xsize = msize;
+               }
+
+               tp = rp; rp = xp; xp = tp;
+               rsize = xsize;
+
+               if( (mpi_limb_signed_t)e < 0 ) {
+                   /*mpihelp_mul( xp, rp, rsize, bp, bsize );*/
+                   if( bsize < KARATSUBA_THRESHOLD ) {
+                           mpi_limb_t tmp;
+                           if (mpihelp_mul( xp, rp, rsize, bp, bsize, &tmp ) < 0)
+                                   goto enomem;
+                   }
+                   else {
+                           if (mpihelp_mul_karatsuba_case(
+                                       xp, rp, rsize, bp, bsize, &karactx ) < 0)
+                                   goto enomem;
+                   }
+
+                   xsize = rsize + bsize;
+                   if( xsize > msize ) {
+                       mpihelp_divrem(xp + msize, 0, xp, xsize, mp, msize);
+                       xsize = msize;
+                   }
+
+                   tp = rp; rp = xp; xp = tp;
+                   rsize = xsize;
+               }
+               e <<= 1;
+               c--;
+           }
+
+           i--;
+           if( i < 0 )
+               break;
+           e = ep[i];
+           c = BITS_PER_MPI_LIMB;
+       }
+
+       /* We shifted MOD, the modulo reduction argument, left MOD_SHIFT_CNT
+        * steps.  Adjust the result by reducing it with the original MOD.
+        *
+        * Also make sure the result is put in RES->d (where it already
+        * might be, see above).
+        */
+       if( mod_shift_cnt ) {
+           carry_limb = mpihelp_lshift( res->d, rp, rsize, mod_shift_cnt);
+           rp = res->d;
+           if( carry_limb ) {
+               rp[rsize] = carry_limb;
+               rsize++;
+           }
+       }
+       else {
+           MPN_COPY( res->d, rp, rsize);
+           rp = res->d;
+       }
+
+       if( rsize >= msize ) {
+           mpihelp_divrem(rp + msize, 0, rp, rsize, mp, msize);
+           rsize = msize;
+       }
+
+       /* Remove any leading zero words from the result.  */
+       if( mod_shift_cnt )
+           mpihelp_rshift( rp, rp, rsize, mod_shift_cnt);
+       MPN_NORMALIZE (rp, rsize);
+
+       mpihelp_release_karatsuba_ctx( &karactx );
+    }
+
+    if( negative_result && rsize ) {
+       if( mod_shift_cnt )
+           mpihelp_rshift( mp, mp, msize, mod_shift_cnt);
+       mpihelp_sub( rp, mp, msize, rp, rsize);
+       rsize = msize;
+       rsign = msign;
+       MPN_NORMALIZE(rp, rsize);
+    }
+    res->nlimbs = rsize;
+    res->sign = rsign;
+
+ leave:
+    rc = 0;
+ enomem:
+    if( assign_rp ) mpi_assign_limb_space( res, rp, size );
+    if( mp_marker ) mpi_free_limb_space( mp_marker );
+    if( bp_marker ) mpi_free_limb_space( bp_marker );
+    if( ep_marker ) mpi_free_limb_space( ep_marker );
+    if( xp_marker ) mpi_free_limb_space( xp_marker );
+    if( tspace )    mpi_free_limb_space( tspace );
+    return rc;
+}
+
diff --git a/crypto/mpi/mpi-scan.c b/crypto/mpi/mpi-scan.c
new file mode 100644 (file)
index 0000000..0f080fb
--- /dev/null
@@ -0,0 +1,129 @@
+/* mpi-scan.c  -  MPI functions
+ * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "mpi-internal.h"
+#include "longlong.h"
+
+/****************
+ * Scan through an mpi and return byte for byte. a -1 is returned to indicate
+ * the end of the mpi. Scanning is done from the lsb to the msb, returned
+ * values are in the range of 0 .. 255.
+ *
+ * FIXME: This code is VERY ugly!
+ */
+int
+mpi_getbyte( const MPI a, unsigned idx )
+{
+    int i, j;
+    unsigned n;
+    mpi_ptr_t ap;
+    mpi_limb_t limb;
+
+    ap = a->d;
+    for(n=0,i=0; i < a->nlimbs; i++ ) {
+       limb = ap[i];
+       for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ )
+           if( n == idx )
+               return (limb >> j*8) & 0xff;
+    }
+    return -1;
+}
+
+
+/****************
+ * Put a value at position IDX into A. idx counts from lsb to msb
+ */
+void
+mpi_putbyte( MPI a, unsigned idx, int xc )
+{
+    int i, j;
+    unsigned n;
+    mpi_ptr_t ap;
+    mpi_limb_t limb, c;
+
+    c = xc & 0xff;
+    ap = a->d;
+    for(n=0,i=0; i < a->alloced; i++ ) {
+       limb = ap[i];
+       for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ )
+           if( n == idx ) {
+             #if BYTES_PER_MPI_LIMB == 4
+               if( j == 0 )
+                   limb = (limb & 0xffffff00) | c;
+               else if( j == 1 )
+                   limb = (limb & 0xffff00ff) | (c<<8);
+               else if( j == 2 )
+                   limb = (limb & 0xff00ffff) | (c<<16);
+               else
+                   limb = (limb & 0x00ffffff) | (c<<24);
+             #elif BYTES_PER_MPI_LIMB == 8
+               if( j == 0 )
+                   limb = (limb & 0xffffffffffffff00) | c;
+               else if( j == 1 )
+                   limb = (limb & 0xffffffffffff00ff) | (c<<8);
+               else if( j == 2 )
+                   limb = (limb & 0xffffffffff00ffff) | (c<<16);
+               else if( j == 3 )
+                   limb = (limb & 0xffffffff00ffffff) | (c<<24);
+               else if( j == 4 )
+                   limb = (limb & 0xffffff00ffffffff) | (c<<32);
+               else if( j == 5 )
+                   limb = (limb & 0xffff00ffffffffff) | (c<<40);
+               else if( j == 6 )
+                   limb = (limb & 0xff00ffffffffffff) | (c<<48);
+               else
+                   limb = (limb & 0x00ffffffffffffff) | (c<<56);
+             #else
+                #error please enhance this function, its ugly - i know.
+             #endif
+               if( a->nlimbs <= i )
+                   a->nlimbs = i+1;
+               ap[i] = limb;
+               return;
+           }
+    }
+    log_bug("index out of range\n");
+}
+
+
+/****************
+ * Count the number of zerobits at the low end of A
+ */
+unsigned
+mpi_trailing_zeros( const MPI a )
+{
+    unsigned n, count = 0;
+
+    for(n=0; n < a->nlimbs; n++ ) {
+       if( a->d[n] ) {
+           unsigned nn;
+           mpi_limb_t alimb = a->d[n];
+
+           count_trailing_zeros( nn, alimb );
+           count += nn;
+           break;
+       }
+       count += BITS_PER_MPI_LIMB;
+    }
+    return count;
+
+}
+
+
diff --git a/crypto/mpi/mpicoder.c b/crypto/mpi/mpicoder.c
new file mode 100644 (file)
index 0000000..14bfcc6
--- /dev/null
@@ -0,0 +1,359 @@
+/* mpicoder.c  -  Coder for the external representation of MPIs
+ * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "mpi-internal.h"
+
+#define DIM(v) (sizeof(v)/sizeof((v)[0]))
+#define MAX_EXTERN_MPI_BITS 16384
+
+
+static uint8_t asn[15] = /* Object ID is 1.3.14.3.2.26 */
+  { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
+    0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
+
+
+MPI
+do_encode_md(const void *sha_buffer, unsigned nbits)
+{
+  int nframe = (nbits+7) / 8;
+  uint8_t *frame, *fr_pt;
+  int i = 0, n;
+  size_t asnlen = DIM(asn);
+  MPI a = MPI_NULL;
+
+  if(SHA1_DIGEST_LENGTH + asnlen + 4  > nframe )
+    printk("MPI: can't encode a %d bit MD into a %d bits frame\n",
+         (int)(SHA1_DIGEST_LENGTH*8), (int)nbits);
+
+  /* We encode the MD in this way:
+   *
+   *      0  A PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
+   *
+   * PAD consists of FF bytes.
+   */
+  frame = kmalloc(nframe, GFP_KERNEL);
+  if (!frame)
+         return MPI_NULL;
+  n = 0;
+  frame[n++] = 0;
+  frame[n++] = 1; /* block type */
+  i = nframe - SHA1_DIGEST_LENGTH - asnlen -3 ;
+  
+  if(i <= 1) {
+    printk("MPI: message digest encoding failed\n");
+    kfree(frame);
+    return a;
+  }
+
+  memset( frame+n, 0xff, i ); n += i;
+  frame[n++] = 0;
+  memcpy( frame+n, &asn, asnlen ); n += asnlen;
+  memcpy( frame+n, sha_buffer, SHA1_DIGEST_LENGTH ); n += SHA1_DIGEST_LENGTH;
+  
+  i = nframe;
+  fr_pt = frame;
+
+  if (n != nframe) {
+    printk("MPI: message digest encoding failed, frame length is wrong\n");
+    kfree(frame);
+    return a;
+  }
+  
+  a = mpi_alloc( (nframe+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB );
+  mpi_set_buffer( a, frame, nframe, 0 );
+  kfree(frame);
+
+  return a;
+}
+
+
+MPI
+mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
+{
+  const uint8_t *buffer = xbuffer;
+  int i, j;
+  unsigned nbits, nbytes, nlimbs, nread=0;
+  mpi_limb_t a;
+  MPI val = MPI_NULL;
+
+  if( *ret_nread < 2 )
+    goto leave;
+  nbits = buffer[0] << 8 | buffer[1];
+
+  if( nbits > MAX_EXTERN_MPI_BITS ) {
+    printk("MPI: mpi too large (%u bits)\n", nbits);
+    goto leave;
+  }
+  buffer += 2;
+  nread = 2;
+
+  nbytes = (nbits+7) / 8;
+  nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
+  val = mpi_alloc( nlimbs );
+  if (!val)
+         return MPI_NULL;
+  i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
+  i %= BYTES_PER_MPI_LIMB;
+  val->nbits = nbits;
+  j= val->nlimbs = nlimbs;
+  val->sign = 0;
+  for( ; j > 0; j-- ) {
+    a = 0;
+    for(; i < BYTES_PER_MPI_LIMB; i++ ) {
+      if( ++nread > *ret_nread ) {
+       printk("MPI: mpi larger than buffer nread=%d ret_nread=%d\n", nread, *ret_nread);
+       goto leave;
+      }
+      a <<= 8;
+      a |= *buffer++;
+    }
+    i = 0;
+    val->d[j-1] = a;
+  }
+
+ leave:
+  *ret_nread = nread;
+  return val;
+}
+
+
+/****************
+ * Make an mpi from a character string.
+ */
+int
+mpi_fromstr(MPI val, const char *str)
+{
+    int hexmode=0, sign=0, prepend_zero=0, i, j, c, c1, c2;
+    unsigned nbits, nbytes, nlimbs;
+    mpi_limb_t a;
+
+    if( *str == '-' ) {
+       sign = 1;
+       str++;
+    }
+    if( *str == '0' && str[1] == 'x' )
+       hexmode = 1;
+    else
+       return -EINVAL; /* other bases are not yet supported */
+    str += 2;
+
+    nbits = strlen(str)*4;
+    if( nbits % 8 )
+       prepend_zero = 1;
+    nbytes = (nbits+7) / 8;
+    nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
+    if( val->alloced < nlimbs )
+           if (!mpi_resize(val, nlimbs ))
+                   return -ENOMEM;
+    i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
+    i %= BYTES_PER_MPI_LIMB;
+    j= val->nlimbs = nlimbs;
+    val->sign = sign;
+    for( ; j > 0; j-- ) {
+       a = 0;
+       for(; i < BYTES_PER_MPI_LIMB; i++ ) {
+           if( prepend_zero ) {
+               c1 = '0';
+               prepend_zero = 0;
+           }
+           else
+               c1 = *str++;
+           assert(c1);
+           c2 = *str++;
+           assert(c2);
+           if( c1 >= '0' && c1 <= '9' )
+               c = c1 - '0';
+           else if( c1 >= 'a' && c1 <= 'f' )
+               c = c1 - 'a' + 10;
+           else if( c1 >= 'A' && c1 <= 'F' )
+               c = c1 - 'A' + 10;
+           else {
+               mpi_clear(val);
+               return 1;
+           }
+           c <<= 4;
+           if( c2 >= '0' && c2 <= '9' )
+               c |= c2 - '0';
+           else if( c2 >= 'a' && c2 <= 'f' )
+               c |= c2 - 'a' + 10;
+           else if( c2 >= 'A' && c2 <= 'F' )
+               c |= c2 - 'A' + 10;
+           else {
+               mpi_clear(val);
+               return 1;
+           }
+           a <<= 8;
+           a |= c;
+       }
+       i = 0;
+
+       val->d[j-1] = a;
+    }
+
+    return 0;
+}
+
+
+/****************
+ * Special function to get the low 8 bytes from an mpi.
+ * This can be used as a keyid; KEYID is an 2 element array.
+ * Return the low 4 bytes.
+ */
+u32
+mpi_get_keyid( const MPI a, u32 *keyid )
+{
+#if BYTES_PER_MPI_LIMB == 4
+    if( keyid ) {
+       keyid[0] = a->nlimbs >= 2? a->d[1] : 0;
+       keyid[1] = a->nlimbs >= 1? a->d[0] : 0;
+    }
+    return a->nlimbs >= 1? a->d[0] : 0;
+#elif BYTES_PER_MPI_LIMB == 8
+    if( keyid ) {
+       keyid[0] = a->nlimbs? (u32)(a->d[0] >> 32) : 0;
+       keyid[1] = a->nlimbs? (u32)(a->d[0] & 0xffffffff) : 0;
+    }
+    return a->nlimbs? (u32)(a->d[0] & 0xffffffff) : 0;
+#else
+  #error Make this function work with other LIMB sizes
+#endif
+}
+
+
+/****************
+ * Return an allocated buffer with the MPI (msb first).
+ * NBYTES receives the length of this buffer. Caller must free the
+ * return string (This function does return a 0 byte buffer with NBYTES
+ * set to zero if the value of A is zero. If sign is not NULL, it will
+ * be set to the sign of the A.
+ */
+void *
+mpi_get_buffer( MPI a, unsigned *nbytes, int *sign )
+{
+    uint8_t *p, *buffer;
+    mpi_limb_t alimb;
+    int i;
+    unsigned int n;
+
+    if( sign )
+       *sign = a->sign;
+    *nbytes = n = a->nlimbs * BYTES_PER_MPI_LIMB;
+    if (!n)
+      n++; /* avoid zero length allocation */
+    p = buffer = kmalloc(n, GFP_KERNEL);
+
+    for(i=a->nlimbs-1; i >= 0; i-- ) {
+       alimb = a->d[i];
+#if BYTES_PER_MPI_LIMB == 4
+       *p++ = alimb >> 24;
+       *p++ = alimb >> 16;
+       *p++ = alimb >>  8;
+       *p++ = alimb      ;
+#elif BYTES_PER_MPI_LIMB == 8
+       *p++ = alimb >> 56;
+       *p++ = alimb >> 48;
+       *p++ = alimb >> 40;
+       *p++ = alimb >> 32;
+       *p++ = alimb >> 24;
+       *p++ = alimb >> 16;
+       *p++ = alimb >>  8;
+       *p++ = alimb      ;
+#else
+#error please implement for this limb size.
+#endif
+    }
+
+    /* this is sub-optimal but we need to do the shift operation
+     * because the caller has to free the returned buffer */
+    for(p=buffer; !*p && *nbytes; p++, --*nbytes )
+      ;
+    if( p != buffer )
+      memmove(buffer,p, *nbytes);
+
+    return buffer;
+}
+
+
+/****************
+ * Use BUFFER to update MPI.
+ */
+int
+mpi_set_buffer( MPI a, const void *xbuffer, unsigned nbytes, int sign )
+{
+    const uint8_t *buffer = xbuffer, *p;
+    mpi_limb_t alimb;
+    int nlimbs;
+    int i;
+
+    nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
+    if (RESIZE_IF_NEEDED(a, nlimbs) < 0)
+           return -ENOMEM;
+    a->sign = sign;
+
+    for(i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; ) {
+      #if BYTES_PER_MPI_LIMB == 4
+       alimb  = (mpi_limb_t)*p-- ;
+       alimb |= (mpi_limb_t)*p-- <<  8 ;
+       alimb |= (mpi_limb_t)*p-- << 16 ;
+       alimb |= (mpi_limb_t)*p-- << 24 ;
+      #elif BYTES_PER_MPI_LIMB == 8
+       alimb  = (mpi_limb_t)*p--       ;
+       alimb |= (mpi_limb_t)*p-- <<  8 ;
+       alimb |= (mpi_limb_t)*p-- << 16 ;
+       alimb |= (mpi_limb_t)*p-- << 24 ;
+       alimb |= (mpi_limb_t)*p-- << 32 ;
+       alimb |= (mpi_limb_t)*p-- << 40 ;
+       alimb |= (mpi_limb_t)*p-- << 48 ;
+       alimb |= (mpi_limb_t)*p-- << 56 ;
+      #else
+       #error please implement for this limb size.
+      #endif
+       a->d[i++] = alimb;
+    }
+    if( p >= buffer ) {
+      #if BYTES_PER_MPI_LIMB == 4
+       alimb  = *p--       ;
+       if( p >= buffer ) alimb |= (mpi_limb_t)*p-- <<  8 ;
+       if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 16 ;
+       if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 24 ;
+      #elif BYTES_PER_MPI_LIMB == 8
+       alimb  = (mpi_limb_t)*p-- ;
+       if( p >= buffer ) alimb |= (mpi_limb_t)*p-- <<  8 ;
+       if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 16 ;
+       if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 24 ;
+       if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 32 ;
+       if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 40 ;
+       if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 48 ;
+       if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 56 ;
+      #else
+       #error please implement for this limb size.
+      #endif
+       a->d[i++] = alimb;
+    }
+    a->nlimbs = i;
+
+    if (i != nlimbs) {
+           printk("MPI: mpi_set_buffer: Assertion failed (%d != %d)", i, nlimbs);
+           BUG();
+    }
+    return 0;
+}
+
diff --git a/crypto/mpi/mpih-cmp.c b/crypto/mpi/mpih-cmp.c
new file mode 100644 (file)
index 0000000..0ffd64e
--- /dev/null
@@ -0,0 +1,58 @@
+/* mpihelp-sub.c  -  MPI helper functions
+ *     Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+ *     Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#include "mpi-internal.h"
+
+/****************
+ * Compare OP1_PTR/OP1_SIZE with OP2_PTR/OP2_SIZE.
+ * There are no restrictions on the relative sizes of
+ * the two arguments.
+ * Return 1 if OP1 > OP2, 0 if they are equal, and -1 if OP1 < OP2.
+ */
+int
+mpihelp_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size )
+{
+    mpi_size_t i;
+    mpi_limb_t op1_word, op2_word;
+
+    for( i = size - 1; i >= 0 ; i--) {
+       op1_word = op1_ptr[i];
+       op2_word = op2_ptr[i];
+       if( op1_word != op2_word )
+           goto diff;
+    }
+    return 0;
+
+  diff:
+    /* This can *not* be simplified to
+     *  op2_word - op2_word
+     * since that expression might give signed overflow.  */
+    return (op1_word > op2_word) ? 1 : -1;
+}
+
diff --git a/crypto/mpi/mpih-div.c b/crypto/mpi/mpih-div.c
new file mode 100644 (file)
index 0000000..e4e80fe
--- /dev/null
@@ -0,0 +1,534 @@
+/* mpihelp-div.c  -  MPI helper functions
+ *     Copyright (C) 1994, 1996 Free Software Foundation, Inc.
+ *     Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#include "mpi-internal.h"
+#include "longlong.h"
+
+#ifndef UMUL_TIME
+  #define UMUL_TIME 1
+#endif
+#ifndef UDIV_TIME
+  #define UDIV_TIME UMUL_TIME
+#endif
+
+/* FIXME: We should be using invert_limb (or invert_normalized_limb)
+ * here (not udiv_qrnnd).
+ */
+
+mpi_limb_t
+mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size,
+                                     mpi_limb_t divisor_limb)
+{
+    mpi_size_t i;
+    mpi_limb_t n1, n0, r;
+    int dummy;
+
+    /* Botch: Should this be handled at all?  Rely on callers? */
+    if( !dividend_size )
+       return 0;
+
+    /* If multiplication is much faster than division, and the
+     * dividend is large, pre-invert the divisor, and use
+     * only multiplications in the inner loop.
+     *
+     * This test should be read:
+     *  Does it ever help to use udiv_qrnnd_preinv?
+     *    && Does what we save compensate for the inversion overhead?
+     */
+    if( UDIV_TIME > (2 * UMUL_TIME + 6)
+       && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) {
+       int normalization_steps;
+
+       count_leading_zeros( normalization_steps, divisor_limb );
+       if( normalization_steps ) {
+           mpi_limb_t divisor_limb_inverted;
+
+           divisor_limb <<= normalization_steps;
+
+           /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB.  The
+            * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the
+            * most significant bit (with weight 2**N) implicit.
+            *
+            * Special case for DIVISOR_LIMB == 100...000.
+            */
+           if( !(divisor_limb << 1) )
+               divisor_limb_inverted = ~(mpi_limb_t)0;
+           else
+               udiv_qrnnd(divisor_limb_inverted, dummy,
+                          -divisor_limb, 0, divisor_limb);
+
+           n1 = dividend_ptr[dividend_size - 1];
+           r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps);
+
+           /* Possible optimization:
+            * if (r == 0
+            * && divisor_limb > ((n1 << normalization_steps)
+            *                 | (dividend_ptr[dividend_size - 2] >> ...)))
+            * ...one division less...
+            */
+           for( i = dividend_size - 2; i >= 0; i--) {
+               n0 = dividend_ptr[i];
+               UDIV_QRNND_PREINV(dummy, r, r,
+                                  ((n1 << normalization_steps)
+                         | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))),
+                         divisor_limb, divisor_limb_inverted);
+               n1 = n0;
+           }
+           UDIV_QRNND_PREINV(dummy, r, r,
+                             n1 << normalization_steps,
+                             divisor_limb, divisor_limb_inverted);
+           return r >> normalization_steps;
+       }
+       else {
+           mpi_limb_t divisor_limb_inverted;
+
+           /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB.  The
+            * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the
+            * most significant bit (with weight 2**N) implicit.
+            *
+            * Special case for DIVISOR_LIMB == 100...000.
+            */
+           if( !(divisor_limb << 1) )
+               divisor_limb_inverted = ~(mpi_limb_t)0;
+           else
+               udiv_qrnnd(divisor_limb_inverted, dummy,
+                           -divisor_limb, 0, divisor_limb);
+
+           i = dividend_size - 1;
+           r = dividend_ptr[i];
+
+           if( r >= divisor_limb )
+               r = 0;
+           else
+               i--;
+
+           for( ; i >= 0; i--) {
+               n0 = dividend_ptr[i];
+               UDIV_QRNND_PREINV(dummy, r, r,
+                                 n0, divisor_limb, divisor_limb_inverted);
+           }
+           return r;
+       }
+    }
+    else {
+       if( UDIV_NEEDS_NORMALIZATION ) {
+           int normalization_steps;
+
+           count_leading_zeros(normalization_steps, divisor_limb);
+           if( normalization_steps ) {
+               divisor_limb <<= normalization_steps;
+
+               n1 = dividend_ptr[dividend_size - 1];
+               r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps);
+
+               /* Possible optimization:
+                * if (r == 0
+                * && divisor_limb > ((n1 << normalization_steps)
+                *                 | (dividend_ptr[dividend_size - 2] >> ...)))
+                * ...one division less...
+                */
+               for(i = dividend_size - 2; i >= 0; i--) {
+                   n0 = dividend_ptr[i];
+                   udiv_qrnnd (dummy, r, r,
+                               ((n1 << normalization_steps)
+                        | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))),
+                        divisor_limb);
+                   n1 = n0;
+               }
+               udiv_qrnnd (dummy, r, r,
+                           n1 << normalization_steps,
+                           divisor_limb);
+               return r >> normalization_steps;
+           }
+       }
+       /* No normalization needed, either because udiv_qrnnd doesn't require
+        * it, or because DIVISOR_LIMB is already normalized.  */
+       i = dividend_size - 1;
+       r = dividend_ptr[i];
+
+       if(r >= divisor_limb)
+           r = 0;
+       else
+           i--;
+
+       for(; i >= 0; i--) {
+           n0 = dividend_ptr[i];
+           udiv_qrnnd (dummy, r, r, n0, divisor_limb);
+       }
+       return r;
+    }
+}
+
+/* Divide num (NP/NSIZE) by den (DP/DSIZE) and write
+ * the NSIZE-DSIZE least significant quotient limbs at QP
+ * and the DSIZE long remainder at NP. If QEXTRA_LIMBS is
+ * non-zero, generate that many fraction bits and append them after the
+ * other quotient limbs.
+ * Return the most significant limb of the quotient, this is always 0 or 1.
+ *
+ * Preconditions:
+ * 0. NSIZE >= DSIZE.
+ * 1. The most significant bit of the divisor must be set.
+ * 2. QP must either not overlap with the input operands at all, or
+ *    QP + DSIZE >= NP must hold true. (This means that it's
+ *    possible to put the quotient in the high part of NUM, right after the
+ *    remainder in NUM.
+ * 3. NSIZE >= DSIZE, even if QEXTRA_LIMBS is non-zero.
+ */
+
+mpi_limb_t
+mpihelp_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs,
+               mpi_ptr_t np, mpi_size_t nsize,
+               mpi_ptr_t dp, mpi_size_t dsize)
+{
+    mpi_limb_t most_significant_q_limb = 0;
+
+    switch(dsize) {
+      case 0:
+       /* We are asked to divide by zero, so go ahead and do it!  (To make
+          the compiler not remove this statement, return the value.)  */
+       return 1 / dsize;
+
+      case 1:
+       {
+           mpi_size_t i;
+           mpi_limb_t n1;
+           mpi_limb_t d;
+
+           d = dp[0];
+           n1 = np[nsize - 1];
+
+           if( n1 >= d ) {
+               n1 -= d;
+               most_significant_q_limb = 1;
+           }
+
+           qp += qextra_limbs;
+           for( i = nsize - 2; i >= 0; i--)
+               udiv_qrnnd( qp[i], n1, n1, np[i], d );
+           qp -= qextra_limbs;
+
+           for( i = qextra_limbs - 1; i >= 0; i-- )
+               udiv_qrnnd (qp[i], n1, n1, 0, d);
+
+           np[0] = n1;
+       }
+       break;
+
+      case 2:
+       {
+           mpi_size_t i;
+           mpi_limb_t n1, n0, n2;
+           mpi_limb_t d1, d0;
+
+           np += nsize - 2;
+           d1 = dp[1];
+           d0 = dp[0];
+           n1 = np[1];
+           n0 = np[0];
+
+           if( n1 >= d1 && (n1 > d1 || n0 >= d0) ) {
+               sub_ddmmss (n1, n0, n1, n0, d1, d0);
+               most_significant_q_limb = 1;
+           }
+
+           for( i = qextra_limbs + nsize - 2 - 1; i >= 0; i-- ) {
+               mpi_limb_t q;
+               mpi_limb_t r;
+
+               if( i >= qextra_limbs )
+                   np--;
+               else
+                   np[0] = 0;
+
+               if( n1 == d1 ) {
+                   /* Q should be either 111..111 or 111..110.  Need special
+                    * treatment of this rare case as normal division would
+                    * give overflow.  */
+                   q = ~(mpi_limb_t)0;
+
+                   r = n0 + d1;
+                   if( r < d1 ) {   /* Carry in the addition? */
+                       add_ssaaaa( n1, n0, r - d0, np[0], 0, d0 );
+                       qp[i] = q;
+                       continue;
+                   }
+                   n1 = d0 - (d0 != 0?1:0);
+                   n0 = -d0;
+               }
+               else {
+                   udiv_qrnnd (q, r, n1, n0, d1);
+                   umul_ppmm (n1, n0, d0, q);
+               }
+
+               n2 = np[0];
+             q_test:
+               if( n1 > r || (n1 == r && n0 > n2) ) {
+                   /* The estimated Q was too large.  */
+                   q--;
+                   sub_ddmmss (n1, n0, n1, n0, 0, d0);
+                   r += d1;
+                   if( r >= d1 )    /* If not carry, test Q again.  */
+                       goto q_test;
+               }
+
+               qp[i] = q;
+               sub_ddmmss (n1, n0, r, n2, n1, n0);
+           }
+           np[1] = n1;
+           np[0] = n0;
+       }
+       break;
+
+      default:
+       {
+           mpi_size_t i;
+           mpi_limb_t dX, d1, n0;
+
+           np += nsize - dsize;
+           dX = dp[dsize - 1];
+           d1 = dp[dsize - 2];
+           n0 = np[dsize - 1];
+
+           if( n0 >= dX ) {
+               if(n0 > dX || mpihelp_cmp(np, dp, dsize - 1) >= 0 ) {
+                   mpihelp_sub_n(np, np, dp, dsize);
+                   n0 = np[dsize - 1];
+                   most_significant_q_limb = 1;
+               }
+           }
+
+           for( i = qextra_limbs + nsize - dsize - 1; i >= 0; i--) {
+               mpi_limb_t q;
+               mpi_limb_t n1, n2;
+               mpi_limb_t cy_limb;
+
+               if( i >= qextra_limbs ) {
+                   np--;
+                   n2 = np[dsize];
+               }
+               else {
+                   n2 = np[dsize - 1];
+                   MPN_COPY_DECR (np + 1, np, dsize - 1);
+                   np[0] = 0;
+               }
+
+               if( n0 == dX ) {
+                   /* This might over-estimate q, but it's probably not worth
+                    * the extra code here to find out.  */
+                   q = ~(mpi_limb_t)0;
+               }
+               else {
+                   mpi_limb_t r;
+
+                   udiv_qrnnd(q, r, n0, np[dsize - 1], dX);
+                   umul_ppmm(n1, n0, d1, q);
+
+                   while( n1 > r || (n1 == r && n0 > np[dsize - 2])) {
+                       q--;
+                       r += dX;
+                       if( r < dX ) /* I.e. "carry in previous addition?" */
+                           break;
+                       n1 -= n0 < d1;
+                       n0 -= d1;
+                   }
+               }
+
+               /* Possible optimization: We already have (q * n0) and (1 * n1)
+                * after the calculation of q.  Taking advantage of that, we
+                * could make this loop make two iterations less.  */
+               cy_limb = mpihelp_submul_1(np, dp, dsize, q);
+
+               if( n2 != cy_limb ) {
+                   mpihelp_add_n(np, np, dp, dsize);
+                   q--;
+               }
+
+               qp[i] = q;
+               n0 = np[dsize - 1];
+           }
+       }
+    }
+
+    return most_significant_q_limb;
+}
+
+
+/****************
+ * Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB.
+ * Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR.
+ * Return the single-limb remainder.
+ * There are no constraints on the value of the divisor.
+ *
+ * QUOT_PTR and DIVIDEND_PTR might point to the same limb.
+ */
+
+mpi_limb_t
+mpihelp_divmod_1( mpi_ptr_t quot_ptr,
+                 mpi_ptr_t dividend_ptr, mpi_size_t dividend_size,
+                 mpi_limb_t divisor_limb)
+{
+    mpi_size_t i;
+    mpi_limb_t n1, n0, r;
+    int dummy;
+
+    if( !dividend_size )
+       return 0;
+
+    /* If multiplication is much faster than division, and the
+     * dividend is large, pre-invert the divisor, and use
+     * only multiplications in the inner loop.
+     *
+     * This test should be read:
+     * Does it ever help to use udiv_qrnnd_preinv?
+     * && Does what we save compensate for the inversion overhead?
+     */
+    if( UDIV_TIME > (2 * UMUL_TIME + 6)
+       && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) {
+       int normalization_steps;
+
+       count_leading_zeros( normalization_steps, divisor_limb );
+       if( normalization_steps ) {
+           mpi_limb_t divisor_limb_inverted;
+
+           divisor_limb <<= normalization_steps;
+
+           /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB.  The
+            * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the
+            * most significant bit (with weight 2**N) implicit.
+            */
+           /* Special case for DIVISOR_LIMB == 100...000.  */
+           if( !(divisor_limb << 1) )
+               divisor_limb_inverted = ~(mpi_limb_t)0;
+           else
+               udiv_qrnnd(divisor_limb_inverted, dummy,
+                          -divisor_limb, 0, divisor_limb);
+
+           n1 = dividend_ptr[dividend_size - 1];
+           r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps);
+
+           /* Possible optimization:
+            * if (r == 0
+            * && divisor_limb > ((n1 << normalization_steps)
+            *                 | (dividend_ptr[dividend_size - 2] >> ...)))
+            * ...one division less...
+            */
+           for( i = dividend_size - 2; i >= 0; i--) {
+               n0 = dividend_ptr[i];
+               UDIV_QRNND_PREINV( quot_ptr[i + 1], r, r,
+                                  ((n1 << normalization_steps)
+                        | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))),
+                             divisor_limb, divisor_limb_inverted);
+               n1 = n0;
+           }
+           UDIV_QRNND_PREINV( quot_ptr[0], r, r,
+                              n1 << normalization_steps,
+                              divisor_limb, divisor_limb_inverted);
+           return r >> normalization_steps;
+       }
+       else {
+           mpi_limb_t divisor_limb_inverted;
+
+           /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB.  The
+            * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the
+            * most significant bit (with weight 2**N) implicit.
+            */
+           /* Special case for DIVISOR_LIMB == 100...000.  */
+           if( !(divisor_limb << 1) )
+               divisor_limb_inverted = ~(mpi_limb_t) 0;
+           else
+               udiv_qrnnd(divisor_limb_inverted, dummy,
+                          -divisor_limb, 0, divisor_limb);
+
+           i = dividend_size - 1;
+           r = dividend_ptr[i];
+
+           if( r >= divisor_limb )
+               r = 0;
+           else
+               quot_ptr[i--] = 0;
+
+           for( ; i >= 0; i-- ) {
+               n0 = dividend_ptr[i];
+               UDIV_QRNND_PREINV( quot_ptr[i], r, r,
+                                  n0, divisor_limb, divisor_limb_inverted);
+           }
+           return r;
+       }
+    }
+    else {
+       if(UDIV_NEEDS_NORMALIZATION) {
+           int normalization_steps;
+
+           count_leading_zeros (normalization_steps, divisor_limb);
+           if( normalization_steps ) {
+               divisor_limb <<= normalization_steps;
+
+               n1 = dividend_ptr[dividend_size - 1];
+               r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps);
+
+               /* Possible optimization:
+                * if (r == 0
+                * && divisor_limb > ((n1 << normalization_steps)
+                *                 | (dividend_ptr[dividend_size - 2] >> ...)))
+                * ...one division less...
+                */
+               for( i = dividend_size - 2; i >= 0; i--) {
+                   n0 = dividend_ptr[i];
+                   udiv_qrnnd (quot_ptr[i + 1], r, r,
+                            ((n1 << normalization_steps)
+                        | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))),
+                               divisor_limb);
+                   n1 = n0;
+               }
+               udiv_qrnnd (quot_ptr[0], r, r,
+                           n1 << normalization_steps,
+                           divisor_limb);
+               return r >> normalization_steps;
+           }
+       }
+       /* No normalization needed, either because udiv_qrnnd doesn't require
+        * it, or because DIVISOR_LIMB is already normalized.  */
+       i = dividend_size - 1;
+       r = dividend_ptr[i];
+
+       if(r >= divisor_limb)
+           r = 0;
+       else
+           quot_ptr[i--] = 0;
+
+       for(; i >= 0; i--) {
+           n0 = dividend_ptr[i];
+           udiv_qrnnd( quot_ptr[i], r, r, n0, divisor_limb );
+       }
+       return r;
+    }
+}
+
+
diff --git a/crypto/mpi/mpih-mul.c b/crypto/mpi/mpih-mul.c
new file mode 100644 (file)
index 0000000..c4eaca7
--- /dev/null
@@ -0,0 +1,547 @@
+/* mpihelp-mul.c  -  MPI helper functions
+ * Copyright (C) 1994, 1996, 1998, 1999,
+ *               2000 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#include <linux/string.h>
+#include "mpi-internal.h"
+#include "longlong.h"
+
+
+
+#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \
+    do {                                               \
+       if( (size) < KARATSUBA_THRESHOLD )              \
+           mul_n_basecase (prodp, up, vp, size);       \
+       else                                            \
+           mul_n (prodp, up, vp, size, tspace);        \
+    } while (0);
+
+#define MPN_SQR_N_RECURSE(prodp, up, size, tspace) \
+    do {                                           \
+       if ((size) < KARATSUBA_THRESHOLD)           \
+           mpih_sqr_n_basecase (prodp, up, size);       \
+       else                                        \
+           mpih_sqr_n (prodp, up, size, tspace);        \
+    } while (0);
+
+
+
+
+/* Multiply the natural numbers u (pointed to by UP) and v (pointed to by VP),
+ * both with SIZE limbs, and store the result at PRODP.  2 * SIZE limbs are
+ * always stored.  Return the most significant limb.
+ *
+ * Argument constraints:
+ * 1. PRODP != UP and PRODP != VP, i.e. the destination
+ *    must be distinct from the multiplier and the multiplicand.
+ *
+ *
+ * Handle simple cases with traditional multiplication.
+ *
+ * This is the most critical code of multiplication.  All multiplies rely
+ * on this, both small and huge.  Small ones arrive here immediately.  Huge
+ * ones arrive here as this is the base case for Karatsuba's recursive
+ * algorithm below.
+ */
+
+static mpi_limb_t
+mul_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up,
+                                mpi_ptr_t vp, mpi_size_t size)
+{
+    mpi_size_t i;
+    mpi_limb_t cy;
+    mpi_limb_t v_limb;
+
+    /* Multiply by the first limb in V separately, as the result can be
+     * stored (not added) to PROD.  We also avoid a loop for zeroing.  */
+    v_limb = vp[0];
+    if( v_limb <= 1 ) {
+       if( v_limb == 1 )
+           MPN_COPY( prodp, up, size );
+       else
+           MPN_ZERO( prodp, size );
+       cy = 0;
+    }
+    else
+       cy = mpihelp_mul_1( prodp, up, size, v_limb );
+
+    prodp[size] = cy;
+    prodp++;
+
+    /* For each iteration in the outer loop, multiply one limb from
+     * U with one limb from V, and add it to PROD.  */
+    for( i = 1; i < size; i++ ) {
+       v_limb = vp[i];
+       if( v_limb <= 1 ) {
+           cy = 0;
+           if( v_limb == 1 )
+              cy = mpihelp_add_n(prodp, prodp, up, size);
+       }
+       else
+           cy = mpihelp_addmul_1(prodp, up, size, v_limb);
+
+       prodp[size] = cy;
+       prodp++;
+    }
+
+    return cy;
+}
+
+
+static void
+mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp,
+                       mpi_size_t size, mpi_ptr_t tspace )
+{
+    if( size & 1 ) {
+      /* The size is odd, and the code below doesn't handle that.
+       * Multiply the least significant (size - 1) limbs with a recursive
+       * call, and handle the most significant limb of S1 and S2
+       * separately.
+       * A slightly faster way to do this would be to make the Karatsuba
+       * code below behave as if the size were even, and let it check for
+       * odd size in the end.  I.e., in essence move this code to the end.
+       * Doing so would save us a recursive call, and potentially make the
+       * stack grow a lot less.
+       */
+      mpi_size_t esize = size - 1;      /* even size */
+      mpi_limb_t cy_limb;
+
+      MPN_MUL_N_RECURSE( prodp, up, vp, esize, tspace );
+      cy_limb = mpihelp_addmul_1( prodp + esize, up, esize, vp[esize] );
+      prodp[esize + esize] = cy_limb;
+      cy_limb = mpihelp_addmul_1( prodp + esize, vp, size, up[esize] );
+      prodp[esize + size] = cy_limb;
+    }
+    else {
+       /* Anatolij Alekseevich Karatsuba's divide-and-conquer algorithm.
+        *
+        * Split U in two pieces, U1 and U0, such that
+        * U = U0 + U1*(B**n),
+        * and V in V1 and V0, such that
+        * V = V0 + V1*(B**n).
+        *
+        * UV is then computed recursively using the identity
+        *
+        *        2n   n          n                     n
+        * UV = (B  + B )U V  +  B (U -U )(V -V )  +  (B + 1)U V
+        *                1 1        1  0   0  1              0 0
+        *
+        * Where B = 2**BITS_PER_MP_LIMB.
+        */
+       mpi_size_t hsize = size >> 1;
+       mpi_limb_t cy;
+       int negflg;
+
+       /* Product H.      ________________  ________________
+        *                |_____U1 x V1____||____U0 x V0_____|
+        * Put result in upper part of PROD and pass low part of TSPACE
+        * as new TSPACE.
+        */
+       MPN_MUL_N_RECURSE(prodp + size, up + hsize, vp + hsize, hsize, tspace);
+
+       /* Product M.      ________________
+        *                |_(U1-U0)(V0-V1)_|
+        */
+       if( mpihelp_cmp(up + hsize, up, hsize) >= 0 ) {
+           mpihelp_sub_n(prodp, up + hsize, up, hsize);
+           negflg = 0;
+       }
+       else {
+           mpihelp_sub_n(prodp, up, up + hsize, hsize);
+           negflg = 1;
+       }
+       if( mpihelp_cmp(vp + hsize, vp, hsize) >= 0 ) {
+           mpihelp_sub_n(prodp + hsize, vp + hsize, vp, hsize);
+           negflg ^= 1;
+       }
+       else {
+           mpihelp_sub_n(prodp + hsize, vp, vp + hsize, hsize);
+           /* No change of NEGFLG.  */
+       }
+       /* Read temporary operands from low part of PROD.
+        * Put result in low part of TSPACE using upper part of TSPACE
+        * as new TSPACE.
+        */
+       MPN_MUL_N_RECURSE(tspace, prodp, prodp + hsize, hsize, tspace + size);
+
+       /* Add/copy product H. */
+       MPN_COPY (prodp + hsize, prodp + size, hsize);
+       cy = mpihelp_add_n( prodp + size, prodp + size,
+                           prodp + size + hsize, hsize);
+
+       /* Add product M (if NEGFLG M is a negative number) */
+       if(negflg)
+           cy -= mpihelp_sub_n(prodp + hsize, prodp + hsize, tspace, size);
+       else
+           cy += mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, size);
+
+       /* Product L.      ________________  ________________
+        *                |________________||____U0 x V0_____|
+        * Read temporary operands from low part of PROD.
+        * Put result in low part of TSPACE using upper part of TSPACE
+        * as new TSPACE.
+        */
+       MPN_MUL_N_RECURSE(tspace, up, vp, hsize, tspace + size);
+
+       /* Add/copy Product L (twice) */
+
+       cy += mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, size);
+       if( cy )
+         mpihelp_add_1(prodp + hsize + size, prodp + hsize + size, hsize, cy);
+
+       MPN_COPY(prodp, tspace, hsize);
+       cy = mpihelp_add_n(prodp + hsize, prodp + hsize, tspace + hsize, hsize);
+       if( cy )
+           mpihelp_add_1(prodp + size, prodp + size, size, 1);
+    }
+}
+
+
+void
+mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size )
+{
+    mpi_size_t i;
+    mpi_limb_t cy_limb;
+    mpi_limb_t v_limb;
+
+    /* Multiply by the first limb in V separately, as the result can be
+     * stored (not added) to PROD.  We also avoid a loop for zeroing.  */
+    v_limb = up[0];
+    if( v_limb <= 1 ) {
+       if( v_limb == 1 )
+           MPN_COPY( prodp, up, size );
+       else
+           MPN_ZERO(prodp, size);
+       cy_limb = 0;
+    }
+    else
+       cy_limb = mpihelp_mul_1( prodp, up, size, v_limb );
+
+    prodp[size] = cy_limb;
+    prodp++;
+
+    /* For each iteration in the outer loop, multiply one limb from
+     * U with one limb from V, and add it to PROD.  */
+    for( i=1; i < size; i++) {
+       v_limb = up[i];
+       if( v_limb <= 1 ) {
+           cy_limb = 0;
+           if( v_limb == 1 )
+               cy_limb = mpihelp_add_n(prodp, prodp, up, size);
+       }
+       else
+           cy_limb = mpihelp_addmul_1(prodp, up, size, v_limb);
+
+       prodp[size] = cy_limb;
+       prodp++;
+    }
+}
+
+
+void
+mpih_sqr_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size, mpi_ptr_t tspace)
+{
+    if( size & 1 ) {
+       /* The size is odd, and the code below doesn't handle that.
+        * Multiply the least significant (size - 1) limbs with a recursive
+        * call, and handle the most significant limb of S1 and S2
+        * separately.
+        * A slightly faster way to do this would be to make the Karatsuba
+        * code below behave as if the size were even, and let it check for
+        * odd size in the end.  I.e., in essence move this code to the end.
+        * Doing so would save us a recursive call, and potentially make the
+        * stack grow a lot less.
+        */
+       mpi_size_t esize = size - 1;       /* even size */
+       mpi_limb_t cy_limb;
+
+       MPN_SQR_N_RECURSE( prodp, up, esize, tspace );
+       cy_limb = mpihelp_addmul_1( prodp + esize, up, esize, up[esize] );
+       prodp[esize + esize] = cy_limb;
+       cy_limb = mpihelp_addmul_1( prodp + esize, up, size, up[esize] );
+
+       prodp[esize + size] = cy_limb;
+    }
+    else {
+       mpi_size_t hsize = size >> 1;
+       mpi_limb_t cy;
+
+       /* Product H.      ________________  ________________
+        *                |_____U1 x U1____||____U0 x U0_____|
+        * Put result in upper part of PROD and pass low part of TSPACE
+        * as new TSPACE.
+        */
+       MPN_SQR_N_RECURSE(prodp + size, up + hsize, hsize, tspace);
+
+       /* Product M.      ________________
+        *                |_(U1-U0)(U0-U1)_|
+        */
+       if( mpihelp_cmp( up + hsize, up, hsize) >= 0 )
+           mpihelp_sub_n( prodp, up + hsize, up, hsize);
+       else
+           mpihelp_sub_n (prodp, up, up + hsize, hsize);
+
+       /* Read temporary operands from low part of PROD.
+        * Put result in low part of TSPACE using upper part of TSPACE
+        * as new TSPACE.  */
+       MPN_SQR_N_RECURSE(tspace, prodp, hsize, tspace + size);
+
+       /* Add/copy product H  */
+       MPN_COPY(prodp + hsize, prodp + size, hsize);
+       cy = mpihelp_add_n(prodp + size, prodp + size,
+                          prodp + size + hsize, hsize);
+
+       /* Add product M (if NEGFLG M is a negative number).  */
+       cy -= mpihelp_sub_n (prodp + hsize, prodp + hsize, tspace, size);
+
+       /* Product L.      ________________  ________________
+        *                |________________||____U0 x U0_____|
+        * Read temporary operands from low part of PROD.
+        * Put result in low part of TSPACE using upper part of TSPACE
+        * as new TSPACE.  */
+       MPN_SQR_N_RECURSE (tspace, up, hsize, tspace + size);
+
+       /* Add/copy Product L (twice).  */
+       cy += mpihelp_add_n (prodp + hsize, prodp + hsize, tspace, size);
+       if( cy )
+           mpihelp_add_1(prodp + hsize + size, prodp + hsize + size,
+                                                           hsize, cy);
+
+       MPN_COPY(prodp, tspace, hsize);
+       cy = mpihelp_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize);
+       if( cy )
+           mpihelp_add_1 (prodp + size, prodp + size, size, 1);
+    }
+}
+
+
+/* This should be made into an inline function in gmp.h.  */
+int
+mpihelp_mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size)
+{
+    if( up == vp ) {
+       if( size < KARATSUBA_THRESHOLD )
+           mpih_sqr_n_basecase( prodp, up, size );
+       else {
+           mpi_ptr_t tspace;
+           tspace = mpi_alloc_limb_space( 2 * size );
+           if (!tspace)
+                   return -ENOMEM;
+           mpih_sqr_n( prodp, up, size, tspace );
+           mpi_free_limb_space( tspace );
+       }
+    }
+    else {
+       if( size < KARATSUBA_THRESHOLD )
+           mul_n_basecase( prodp, up, vp, size );
+       else {
+           mpi_ptr_t tspace;
+           tspace = mpi_alloc_limb_space( 2 * size );
+           if (!tspace)
+                   return -ENOMEM;
+           mul_n (prodp, up, vp, size, tspace);
+           mpi_free_limb_space( tspace );
+       }
+    }
+
+    return 0;
+}
+
+
+
+int
+mpihelp_mul_karatsuba_case( mpi_ptr_t prodp,
+                           mpi_ptr_t up, mpi_size_t usize,
+                           mpi_ptr_t vp, mpi_size_t vsize,
+                           struct karatsuba_ctx *ctx )
+{
+    mpi_limb_t cy;
+
+    if( !ctx->tspace || ctx->tspace_size < vsize ) {
+       if( ctx->tspace )
+           mpi_free_limb_space( ctx->tspace );
+       ctx->tspace = mpi_alloc_limb_space( 2 * vsize);
+       if (!ctx->tspace)
+               return -ENOMEM;
+       ctx->tspace_size = vsize;
+    }
+
+    MPN_MUL_N_RECURSE( prodp, up, vp, vsize, ctx->tspace );
+
+    prodp += vsize;
+    up += vsize;
+    usize -= vsize;
+    if( usize >= vsize ) {
+       if( !ctx->tp || ctx->tp_size < vsize ) {
+           if( ctx->tp )
+               mpi_free_limb_space( ctx->tp );
+           ctx->tp = mpi_alloc_limb_space( 2 * vsize );
+           if (!ctx->tp) {
+                   if( ctx->tspace )
+                           mpi_free_limb_space( ctx->tspace );
+                   ctx->tspace = NULL;
+                   return -ENOMEM;
+           }
+           ctx->tp_size = vsize;
+       }
+
+       do {
+           MPN_MUL_N_RECURSE( ctx->tp, up, vp, vsize, ctx->tspace );
+           cy = mpihelp_add_n( prodp, prodp, ctx->tp, vsize );
+           mpihelp_add_1( prodp + vsize, ctx->tp + vsize, vsize, cy );
+           prodp += vsize;
+           up += vsize;
+           usize -= vsize;
+       } while( usize >= vsize );
+    }
+
+    if( usize ) {
+       if( usize < KARATSUBA_THRESHOLD ) {
+               mpi_limb_t tmp;
+               if (mpihelp_mul( ctx->tspace, vp, vsize, up, usize, &tmp) < 0)
+                       return -ENOMEM;
+       }
+       else {
+           if( !ctx->next ) {
+               ctx->next = kmalloc( sizeof *ctx, GFP_KERNEL );
+               if (!ctx->next)
+                       return -ENOMEM;
+               memset(ctx->next, 0, sizeof(ctx));
+           }
+           if (mpihelp_mul_karatsuba_case( ctx->tspace,
+                                           vp, vsize,
+                                           up, usize,
+                                           ctx->next ) < 0)
+                   return -ENOMEM;
+       }
+
+       cy = mpihelp_add_n( prodp, prodp, ctx->tspace, vsize);
+       mpihelp_add_1( prodp + vsize, ctx->tspace + vsize, usize, cy );
+    }
+
+    return 0;
+}
+
+
+void
+mpihelp_release_karatsuba_ctx( struct karatsuba_ctx *ctx )
+{
+    struct karatsuba_ctx *ctx2;
+
+    if( ctx->tp )
+       mpi_free_limb_space( ctx->tp );
+    if( ctx->tspace )
+       mpi_free_limb_space( ctx->tspace );
+    for( ctx=ctx->next; ctx; ctx = ctx2 ) {
+       ctx2 = ctx->next;
+       if( ctx->tp )
+           mpi_free_limb_space( ctx->tp );
+       if( ctx->tspace )
+           mpi_free_limb_space( ctx->tspace );
+       kfree( ctx );
+    }
+}
+
+/* Multiply the natural numbers u (pointed to by UP, with USIZE limbs)
+ * and v (pointed to by VP, with VSIZE limbs), and store the result at
+ * PRODP.  USIZE + VSIZE limbs are always stored, but if the input
+ * operands are normalized.  Return the most significant limb of the
+ * result.
+ *
+ * NOTE: The space pointed to by PRODP is overwritten before finished
+ * with U and V, so overlap is an error.
+ *
+ * Argument constraints:
+ * 1. USIZE >= VSIZE.
+ * 2. PRODP != UP and PRODP != VP, i.e. the destination
+ *    must be distinct from the multiplier and the multiplicand.
+ */
+
+int
+mpihelp_mul( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize,
+            mpi_ptr_t vp, mpi_size_t vsize,
+            mpi_limb_t *_result)
+{
+    mpi_ptr_t prod_endp = prodp + usize + vsize - 1;
+    mpi_limb_t cy;
+    struct karatsuba_ctx ctx;
+
+    if( vsize < KARATSUBA_THRESHOLD ) {
+       mpi_size_t i;
+       mpi_limb_t v_limb;
+
+       if( !vsize ) {
+               *_result = 0;
+               return 0;
+       }
+
+       /* Multiply by the first limb in V separately, as the result can be
+        * stored (not added) to PROD.  We also avoid a loop for zeroing.  */
+       v_limb = vp[0];
+       if( v_limb <= 1 ) {
+           if( v_limb == 1 )
+               MPN_COPY( prodp, up, usize );
+           else
+               MPN_ZERO( prodp, usize );
+           cy = 0;
+       }
+       else
+           cy = mpihelp_mul_1( prodp, up, usize, v_limb );
+
+       prodp[usize] = cy;
+       prodp++;
+
+       /* For each iteration in the outer loop, multiply one limb from
+        * U with one limb from V, and add it to PROD.  */
+       for( i = 1; i < vsize; i++ ) {
+           v_limb = vp[i];
+           if( v_limb <= 1 ) {
+               cy = 0;
+               if( v_limb == 1 )
+                  cy = mpihelp_add_n(prodp, prodp, up, usize);
+           }
+           else
+               cy = mpihelp_addmul_1(prodp, up, usize, v_limb);
+
+           prodp[usize] = cy;
+           prodp++;
+       }
+
+       *_result = cy;
+       return 0;
+    }
+
+    memset( &ctx, 0, sizeof ctx );
+    if (mpihelp_mul_karatsuba_case( prodp, up, usize, vp, vsize, &ctx ) < 0)
+           return -ENOMEM;
+    mpihelp_release_karatsuba_ctx( &ctx );
+    *_result = *prod_endp;
+    return 0;
+}
+
+
diff --git a/crypto/mpi/mpiutil.c b/crypto/mpi/mpiutil.c
new file mode 100644 (file)
index 0000000..5bec431
--- /dev/null
@@ -0,0 +1,214 @@
+/* mpiutil.ac  -  Utility functions for MPI
+ * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "mpi-internal.h"
+
+
+/****************
+ * Note:  It was a bad idea to use the number of limbs to allocate
+ *       because on a alpha the limbs are large but we normally need
+ *       integers of n bits - So we should chnage this to bits (or bytes).
+ *
+ *       But mpi_alloc is used in a lot of places :-)
+ */
+MPI mpi_alloc(unsigned nlimbs)
+{
+       MPI a;
+
+       a = (MPI) kmalloc(sizeof *a,GFP_KERNEL);
+       if (!a)
+               return a;
+
+       if (nlimbs) {
+               a->d = mpi_alloc_limb_space(nlimbs);
+               if (!a->d) {
+                       kfree(a);
+                       return NULL;
+               }
+       }
+       else {
+               a->d = NULL;
+       }
+
+       a->alloced = nlimbs;
+       a->nlimbs = 0;
+       a->sign = 0;
+       a->flags = 0;
+       a->nbits = 0;
+       return a;
+}
+
+mpi_ptr_t mpi_alloc_limb_space( unsigned nlimbs )
+{
+    size_t len = nlimbs * sizeof(mpi_limb_t);
+
+    return kmalloc(len,GFP_KERNEL);
+}
+
+void mpi_free_limb_space( mpi_ptr_t a )
+{
+    if( !a )
+       return;
+
+    kfree(a);
+}
+
+
+void mpi_assign_limb_space(MPI a, mpi_ptr_t ap, unsigned nlimbs)
+{
+    mpi_free_limb_space(a->d);
+    a->d = ap;
+    a->alloced = nlimbs;
+}
+
+/****************
+ * Resize the array of A to NLIMBS. the additional space is cleared
+ * (set to 0) [done by m_realloc()]
+ */
+int mpi_resize(MPI a, unsigned nlimbs)
+{
+       void *p;
+
+       if (nlimbs <= a->alloced)
+               return 0; /* no need to do it */
+
+       if (a->d) {
+               p = kmalloc(nlimbs * sizeof(mpi_limb_t), GFP_KERNEL);
+               if (!p)
+                       return -ENOMEM;
+               memcpy(p, a->d, a->alloced * sizeof(mpi_limb_t));
+               kfree(a->d);
+               a->d = p;
+       } else {
+               a->d = kmalloc( nlimbs * sizeof(mpi_limb_t), GFP_KERNEL);
+               if (!a->d)
+                       return -ENOMEM;
+               memset(a->d, 0, nlimbs * sizeof(mpi_limb_t) );
+       }
+       a->alloced = nlimbs;
+       return 0;
+}
+
+void mpi_clear(MPI a)
+{
+       a->nlimbs = 0;
+       a->nbits = 0;
+       a->flags = 0;
+}
+
+void mpi_free(MPI a)
+{
+       if (!a)
+               return;
+
+       if (a->flags & 4)
+               kfree(a->d);
+       else {
+               mpi_free_limb_space(a->d);
+       }
+
+       if (a->flags & ~7 )
+               printk("invalid flag value in mpi\n");
+       kfree(a);
+}
+
+
+/****************
+ * Note: This copy function should not interpret the MPI
+ *      but copy it transparently.
+ */
+int mpi_copy(MPI *copied, const MPI a )
+{
+       size_t i;
+       MPI b;
+
+       *copied = MPI_NULL;
+
+       if ( a ) {
+               b = mpi_alloc( a->nlimbs );
+               if (!b)
+                       return -ENOMEM;
+
+               b->nlimbs = a->nlimbs;
+               b->sign = a->sign;
+               b->flags  = a->flags;
+               b->nbits = a->nbits;
+
+               for (i = 0; i < b->nlimbs; i++ )
+                       b->d[i] = a->d[i];
+
+               *copied = b;
+       }
+
+       return 0;
+}
+
+
+int mpi_set(MPI w, const MPI u)
+{
+       mpi_ptr_t wp, up;
+       mpi_size_t usize = u->nlimbs;
+       int usign = u->sign;
+
+       if (RESIZE_IF_NEEDED(w, (size_t) usize) < 0)
+               return -ENOMEM;
+
+       wp = w->d;
+       up = u->d;
+       MPN_COPY(wp, up, usize);
+       w->nlimbs = usize;
+       w->nbits = u->nbits;
+       w->flags = u->flags;
+       w->sign = usign;
+       return 0;
+}
+
+
+int mpi_set_ui(MPI w, unsigned long u)
+{
+       if (RESIZE_IF_NEEDED(w, 1) < 0)
+               return -ENOMEM;
+       w->d[0] = u;
+       w->nlimbs = u? 1:0;
+       w->sign = 0;
+       w->nbits = 0;
+       w->flags = 0;
+       return 0;
+}
+
+MPI mpi_alloc_set_ui(unsigned long u)
+{
+       MPI w = mpi_alloc(1);
+       if (!w)
+               return w;
+       w->d[0] = u;
+       w->nlimbs = u? 1:0;
+       w->sign = 0;
+       return w;
+}
+
+
+void mpi_swap(MPI a, MPI b)
+{
+       struct gcry_mpi tmp;
+
+       tmp = *a; *a = *b; *b = tmp;
+}
+
diff --git a/crypto/signature/Makefile b/crypto/signature/Makefile
new file mode 100644 (file)
index 0000000..4d1042e
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for the signature checker
+#
+
+obj-y := \
+       ksign.o \
+       ksign-parse.o \
+       ksign-keyring.o \
+       ksign-publickey.o \
+       dsa.o
diff --git a/crypto/signature/dsa.c b/crypto/signature/dsa.c
new file mode 100644 (file)
index 0000000..5b5c736
--- /dev/null
@@ -0,0 +1,98 @@
+/* dsa.c  -  DSA signature algorithm
+ *     Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/crypto/mpi.h>
+#include <asm/errno.h>
+#include "local.h"
+
+/*****************************************************************************/
+/*
+ * perform DSA algorithm signature verification
+ */
+int DSA_verify(const MPI datahash, const MPI sig[], const MPI pkey[])
+{
+       MPI p, q, g, y, r, s;
+       MPI w = NULL, u1 = NULL, u2 = NULL, v = NULL;
+       MPI base[3];
+       MPI exp[3];
+       int rc;
+
+       if (!datahash ||
+           !sig[0] || !sig[1] ||
+           !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3]
+           )
+               return -EINVAL;
+
+       p = pkey[0];    /* prime */
+       q = pkey[1];    /* group order */
+       g = pkey[2];    /* group generator */
+       y = pkey[3];    /* g^x mod p */
+       r = sig[0];
+       s = sig[1];
+
+       if (!(mpi_cmp_ui(r, 0) > 0 && mpi_cmp(r, q) < 0)) {
+               printk("DSA_verify assertion failed [0 < r < q]\n");
+               return -EPERM;
+       }
+
+       if (!(mpi_cmp_ui(s, 0) > 0 && mpi_cmp(s, q) < 0)) {
+               printk("DSA_verify assertion failed [0 < s < q]\n");
+               return -EPERM;
+       }
+
+       rc = -ENOMEM;
+       w  = mpi_alloc(mpi_get_nlimbs(q)); if (!w ) goto cleanup;
+       u1 = mpi_alloc(mpi_get_nlimbs(q)); if (!u1) goto cleanup;
+       u2 = mpi_alloc(mpi_get_nlimbs(q)); if (!u2) goto cleanup;
+       v  = mpi_alloc(mpi_get_nlimbs(p)); if (!v ) goto cleanup;
+
+       /* w = s^(-1) mod q */
+       if (mpi_invm(w, s, q) < 0)
+               goto cleanup;
+
+       /* u1 = (datahash * w) mod q */
+       if (mpi_mulm(u1, datahash, w, q) < 0)
+               goto cleanup;
+
+       /* u2 = r * w mod q  */
+       if (mpi_mulm(u2, r, w, q) < 0)
+               goto cleanup;
+
+       /* v =  g^u1 * y^u2 mod p mod q */
+       base[0] = g;    exp[0] = u1;
+       base[1] = y;    exp[1] = u2;
+       base[2] = NULL; exp[2] = NULL;
+
+       if (mpi_mulpowm(v, base, exp, p) < 0)
+               goto cleanup;
+
+       if (mpi_fdiv_r(v, v, q) < 0)
+               goto cleanup;
+
+       rc = mpi_cmp(v, r) == 0 ? 0 : -EPERM;
+
+ cleanup:
+       mpi_free(w);
+       mpi_free(u1);
+       mpi_free(u2);
+       mpi_free(v);
+       return rc;
+} /* end DSA_verify() */
diff --git a/crypto/signature/key.h b/crypto/signature/key.h
new file mode 100644 (file)
index 0000000..a1ecccb
--- /dev/null
@@ -0,0 +1,7 @@
+
+/* automatically generated by bin2hex */
+static unsigned char ksign_def_public_key[] __initdata =
+{
+       0x00, 0x09, 0x00, 0x00, 0x00, 0x00
+};
+
diff --git a/crypto/signature/ksign-keyring.c b/crypto/signature/ksign-keyring.c
new file mode 100644 (file)
index 0000000..a1bbd85
--- /dev/null
@@ -0,0 +1,112 @@
+/* ksign-keyring.c: public key cache
+ *
+ * Copyright (C) 2001 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This file is derived from part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <linux/rwsem.h>
+#include "local.h"
+
+static LIST_HEAD(keyring);
+static DECLARE_RWSEM(keyring_sem);
+
+static int add_keyblock_key(struct ksign_public_key *pk, void *data)
+{
+       printk("- Added public key %X%X\n", pk->keyid[0], pk->keyid[1]);
+
+       if (pk->expiredate && pk->expiredate < xtime.tv_sec)
+               printk("  - public key has expired\n");
+
+       if (pk->timestamp > xtime.tv_sec )
+               printk("  - key was been created %lu seconds in future\n",
+                      pk->timestamp - xtime.tv_sec);
+
+       atomic_inc(&pk->count);
+
+       down_write(&keyring_sem);
+       list_add_tail(&pk->link, &keyring);
+       up_write(&keyring_sem);
+
+       return 0;
+}
+
+static int add_keyblock_uid(struct ksign_user_id *uid, void *data)
+{
+       printk("- User ID: %s\n", uid->name);
+       return 1;
+}
+
+/*****************************************************************************/
+/*
+ *
+ */
+int ksign_load_keyring_from_buffer(const void *buffer, size_t size)
+{
+    printk("Loading keyring\n");
+
+    return ksign_parse_packets((const uint8_t *) buffer,
+                              size,
+                              NULL,
+                              add_keyblock_key,
+                              add_keyblock_uid,
+                              NULL);
+} /* end ksign_load_keyring_from_buffer() */
+
+/*****************************************************************************/
+/*
+ *
+ */
+struct ksign_public_key *ksign_get_public_key(const uint32_t *keyid)
+{
+       struct ksign_public_key *pk;
+
+       down_read(&keyring_sem);
+
+       list_for_each_entry(pk, &keyring, link) {
+               if (memcmp(pk->keyid, keyid, sizeof(pk->keyid)) == 0) {
+                       atomic_inc(&pk->count);
+                       goto found;
+               }
+       }
+
+ found:
+       up_read(&keyring_sem);
+
+       return pk;
+} /* end ksign_get_public_key() */
+
+/*****************************************************************************/
+/*
+ * clear the public key keyring
+ */
+void ksign_clear_keyring(void)
+{
+       struct ksign_public_key *pk;
+
+       down_write(&keyring_sem);
+
+       while (!list_empty(&keyring)) {
+               pk = list_entry(keyring.next, struct ksign_public_key, link);
+               list_del(&pk->link);
+
+               ksign_put_public_key(pk);
+       }
+
+       up_write(&keyring_sem);
+} /* end ksign_clear_keyring() */
diff --git a/crypto/signature/ksign-parse.c b/crypto/signature/ksign-parse.c
new file mode 100644 (file)
index 0000000..acc2d1f
--- /dev/null
@@ -0,0 +1,609 @@
+/* parse-packet.c  - read packets
+ * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <asm/errno.h>
+#include "local.h"
+
+static inline uint32_t buffer_to_u32(const uint8_t *buffer)
+{
+       uint32_t a;
+       a =  *buffer << 24;
+       a |= buffer[1] << 16;
+       a |= buffer[2] << 8;
+       a |= buffer[3];
+       return a;
+}
+
+static inline uint16_t read_16(const uint8_t **datap)
+{
+       uint16_t a;
+       a = *(*datap)++ << 8;
+       a |= *(*datap)++;
+       return a;
+}
+
+static inline uint32_t read_32(const uint8_t **datap)
+{
+       uint32_t a;
+       a =  *(*datap)++ << 24;
+       a |= *(*datap)++ << 16;
+       a |= *(*datap)++ << 8;
+       a |= *(*datap)++;
+       return a;
+}
+
+void ksign_free_signature(struct ksign_signature *sig)
+{
+       int i;
+
+       if (!sig)
+               return;
+
+       for (i = 0; i < DSA_NSIG; i++)
+               mpi_free(sig->data[i]);
+       kfree(sig->hashed_data);
+       kfree(sig->unhashed_data);
+       kfree(sig);
+}
+
+void ksign_free_public_key(struct ksign_public_key *pk)
+{
+       int i;
+
+       if (pk) {
+               for (i = 0; i < DSA_NPKEY; i++)
+                       mpi_free(pk->pkey[i]);
+               kfree(pk);
+       }
+}
+
+void ksign_free_user_id(struct ksign_user_id *uid)
+{
+       if (uid)
+               kfree(uid);
+}
+
+/*****************************************************************************/
+/*
+ *
+ */
+static void ksign_calc_pk_keyid(struct crypto_tfm *sha1,
+                               struct ksign_public_key *pk)
+{
+       unsigned n;
+       unsigned nb[DSA_NPKEY];
+       unsigned nn[DSA_NPKEY];
+       uint8_t *pp[DSA_NPKEY];
+       uint32_t a32;
+       int i;
+       int npkey = DSA_NPKEY;
+
+       crypto_digest_init(sha1);
+
+       n = pk->version < 4 ? 8 : 6;
+       for (i = 0; i < npkey; i++) {
+               nb[i] = mpi_get_nbits(pk->pkey[i]);
+               pp[i] = mpi_get_buffer( pk->pkey[i], nn + i, NULL);
+               n += 2 + nn[i];
+       }
+
+       SHA1_putc(sha1, 0x99);     /* ctb */
+       SHA1_putc(sha1, n >> 8);   /* 2 uint8_t length header */
+       SHA1_putc(sha1, n);
+
+       if( pk->version < 4)
+               SHA1_putc(sha1, 3);
+       else
+               SHA1_putc(sha1, 4);
+
+       a32 = pk->timestamp;
+       SHA1_putc(sha1, a32 >> 24 );
+       SHA1_putc(sha1, a32 >> 16 );
+       SHA1_putc(sha1, a32 >>  8 );
+       SHA1_putc(sha1, a32 >>  0 );
+
+       if (pk->version < 4) {
+               uint16_t a16;
+
+               if( pk->expiredate )
+                       a16 = (uint16_t) ((pk->expiredate - pk->timestamp) / 86400L);
+               else
+                       a16 = 0;
+               SHA1_putc(sha1, a16 >> 8);
+               SHA1_putc(sha1, a16 >> 0);
+       }
+
+       SHA1_putc(sha1, PUBKEY_ALGO_DSA);
+
+       for (i = 0; i < npkey; i++) {
+               SHA1_putc(sha1, nb[i] >> 8);
+               SHA1_putc(sha1, nb[i]);
+               SHA1_write(sha1, pp[i], nn[i]);
+               kfree(pp[i]);
+       }
+
+} /* end ksign_calc_pk_keyid() */
+
+/*****************************************************************************/
+/*
+ * parse a user ID embedded in a signature
+ */
+static int ksign_parse_user_id(const uint8_t *datap, const uint8_t *endp,
+                              ksign_user_id_actor_t uidfnx, void *fnxdata)
+{
+       struct ksign_user_id *uid;
+       int rc = 0;
+       int n;
+
+       if (!uidfnx)
+               return 0;
+
+       n = endp - datap;
+       uid = kmalloc(sizeof(*uid) + n + 1, GFP_KERNEL);
+       if (!uid)
+               return -ENOMEM;
+       uid->len = n;
+
+       memcpy(uid->name, datap, n);
+       uid->name[n] = 0;
+
+       rc = uidfnx(uid, fnxdata);
+       if (rc == 0)
+               return rc; /* uidfnx keeps the record */
+       if (rc == 1)
+               rc = 0;
+
+       ksign_free_user_id(uid);
+       return rc;
+} /* end ksign_parse_user_id() */
+
+/*****************************************************************************/
+/*
+ * extract a public key embedded in a signature
+ */
+static int ksign_parse_key(const uint8_t *datap, const uint8_t *endp,
+                          uint8_t *hdr, int hdrlen,
+                          ksign_public_key_actor_t pkfnx, void *fnxdata)
+{
+       struct ksign_public_key *pk;
+       struct crypto_tfm *sha1_tfm;
+       unsigned long timestamp, expiredate;
+       uint8_t sha1[SHA1_DIGEST_SIZE];
+       int i, version;
+       int is_v4 = 0;
+       int rc = 0;
+
+       if (endp - datap < 12) {
+               printk("ksign: public key packet too short\n");
+               return -EBADMSG;
+       }
+
+       version = *datap++;
+       switch (version) {
+       case 4:
+               is_v4 = 1;
+       case 2:
+       case 3:
+               break;
+       default:
+               printk("ksign: public key packet with unknown version %d\n",
+                      version);
+               return -EBADMSG;
+       }
+
+       timestamp = read_32(&datap);
+       if (is_v4)
+               expiredate = 0; /* have to get it from the selfsignature */
+       else {
+               unsigned short ndays;
+               ndays = read_16(&datap);
+               if (ndays)
+                       expiredate = timestamp + ndays * 86400L;
+               else
+                       expiredate = 0;
+       }
+
+       if (*datap++ != PUBKEY_ALGO_DSA) {
+               printk("ksign: public key packet with unknown version %d\n",
+                      version);
+               return 0;
+       }
+
+       /* extract the stuff from the DSA public key */
+       pk = kmalloc(sizeof(struct ksign_public_key), GFP_KERNEL);
+       if (!pk)
+               return -ENOMEM;
+
+       memset(pk, 0, sizeof(struct ksign_public_key));
+       atomic_set(&pk->count, 1);
+       pk->timestamp   = timestamp;
+       pk->expiredate  = expiredate;
+       pk->hdrbytes    = hdrlen;
+       pk->version     = version;
+
+       for (i = 0; i < DSA_NPKEY; i++) {
+               unsigned int remaining = endp - datap;
+               pk->pkey[i] = mpi_read_from_buffer(datap, &remaining);
+               datap += remaining;
+       }
+
+       rc = -ENOMEM;
+
+       sha1_tfm = crypto_alloc_tfm2("sha1", 0, 1);
+       if (!sha1_tfm)
+               goto cleanup;
+
+       ksign_calc_pk_keyid(sha1_tfm, pk);
+       crypto_digest_final(sha1_tfm, sha1);
+       crypto_free_tfm(sha1_tfm);
+
+       pk->keyid[0] = sha1[12] << 24 | sha1[13] << 16 | sha1[14] << 8 | sha1[15];
+       pk->keyid[1] = sha1[16] << 24 | sha1[17] << 16 | sha1[18] << 8 | sha1[19];
+
+       rc = 0;
+       if (pkfnx)
+               rc = pkfnx(pk, fnxdata);
+
+ cleanup:
+       ksign_put_public_key(pk);
+       return rc;
+} /* end ksign_parse_key() */
+
+/*****************************************************************************/
+/*
+ *
+ */
+static const uint8_t *ksign_find_sig_issuer(const uint8_t *buffer)
+{
+       size_t buflen;
+       size_t n;
+       int type;
+       int seq = 0;
+
+       if (!buffer)
+               return NULL;
+
+       buflen = read_16(&buffer);
+       while (buflen) {
+               n = *buffer++; buflen--;
+               if (n == 255) {
+                       if (buflen < 4)
+                               goto too_short;
+                       n = read_32(&buffer);
+                       buflen -= 4;
+               }
+               else if (n >= 192) {
+                       if(buflen < 2)
+                               goto too_short;
+                       n = ((n - 192) << 8) + *buffer + 192;
+                       buffer++;
+                       buflen--;
+               }
+
+               if (buflen < n)
+                       goto too_short;
+
+               type = *buffer & 0x7f;
+               if (!(++seq > 0))
+                       ;
+               else if (type == SIGSUBPKT_ISSUER) { /* found */
+                       buffer++;
+                       n--;
+                       if (n > buflen || n < 8)
+                               goto too_short;
+                       return buffer;
+               }
+
+               buffer += n;
+               buflen -= n;
+       }
+
+ too_short:
+       return NULL; /* end of subpackets; not found */
+} /* end ksign_find_sig_issuer() */
+
+/*****************************************************************************/
+/*
+ * extract signature data embedded in a signature
+ */
+static int ksign_parse_signature(const uint8_t *datap, const uint8_t *endp,
+                                ksign_signature_actor_t sigfnx, void *fnxdata)
+{
+       struct ksign_signature *sig;
+       size_t n;
+       int version, is_v4 = 0;
+       int rc;
+       int i;
+
+       if (endp - datap < 16) {
+               printk("ksign: signature packet too short\n");
+               return -EBADMSG;
+       }
+
+       version = *datap++;
+       switch (version) {
+       case 4:
+               is_v4 = 1;
+       case 3:
+       case 2:
+               break;
+       default:
+               printk("ksign: signature packet with unknown version %d\n", version);
+               return 0;
+       }
+
+       /* store information */
+       sig = kmalloc(sizeof(*sig), GFP_KERNEL);
+       if (!sig)
+               return -ENOMEM;
+
+       memset(sig, 0, sizeof(*sig));
+       sig->version = version;
+
+       if (!is_v4)
+               datap++; /* ignore md5 length */
+
+       sig->sig_class = *datap++;
+       if (!is_v4) {
+               sig->timestamp = read_32(&datap);
+               sig->keyid[0] = read_32(&datap);
+               sig->keyid[1] = read_32(&datap);
+       }
+
+       rc = 0;
+       if (*datap++ != PUBKEY_ALGO_DSA) {
+               printk("ksign: ignoring non-DSA signature\n");
+               goto leave;
+       }
+       if (*datap++ != DIGEST_ALGO_SHA1) {
+               printk("ksign: ignoring non-SHA1 signature\n");
+               goto leave;
+       }
+
+       rc = -EBADMSG;
+       if (is_v4) { /* read subpackets */
+               n = read_16(&datap); /* length of hashed data */
+               if (n > 10000) {
+                       printk("ksign: signature packet: hashed data too long\n");
+                       goto leave;
+               }
+               if (n) {
+                       if ((size_t)(endp - datap) < n) {
+                               printk("ksign: signature packet: available data too short\n");
+                               goto leave;
+                       }
+                       sig->hashed_data = kmalloc(n + 2, GFP_KERNEL);
+                       if (!sig->hashed_data) {
+                               rc = -ENOMEM;
+                               goto leave;
+                       }
+                       sig->hashed_data[0] = n >> 8;
+                       sig->hashed_data[1] = n;
+                       memcpy(sig->hashed_data + 2, datap, n);
+                       datap += n;
+               }
+
+               n = read_16(&datap); /* length of unhashed data */
+               if (n > 10000) {
+                       printk("ksign: signature packet: unhashed data too long\n");
+                       goto leave;
+               }
+               if (n) {
+                       if ((size_t) (endp - datap) < n) {
+                               printk("ksign: signature packet: available data too short\n");
+                               goto leave;
+                       }
+                       sig->unhashed_data = kmalloc(n + 2, GFP_KERNEL);
+                       if (!sig->unhashed_data) {
+                               rc = -ENOMEM;
+                               goto leave;
+                       }
+                       sig->unhashed_data[0] = n >> 8;
+                       sig->unhashed_data[1] = n;
+                       memcpy(sig->unhashed_data + 2, datap, n);
+                       datap += n;
+               }
+       }
+
+       if (endp - datap < 5) { /* sanity check */
+               printk("ksign: signature packet too short\n");
+               goto leave;
+       }
+
+       sig->digest_start[0] = *datap++;
+       sig->digest_start[1] = *datap++;
+
+       if (is_v4) {
+               const uint8_t *p;
+
+               p = ksign_find_sig_issuer(sig->hashed_data);
+               if (!p)
+                       p = ksign_find_sig_issuer(sig->unhashed_data);
+               if (!p)
+                       printk("ksign: signature packet without issuer\n");
+               else {
+                       sig->keyid[0] = buffer_to_u32(p);
+                       sig->keyid[1] = buffer_to_u32(p + 4);
+               }
+       }
+
+       for (i = 0; i < DSA_NSIG; i++) {
+               size_t remaining = endp - datap;
+               sig->data[i] = mpi_read_from_buffer(datap, &remaining);
+               datap += remaining;
+       }
+
+       rc = 0;
+       if (sigfnx) {
+               rc = sigfnx(sig, fnxdata);
+               if (rc == 0)
+                       return rc; /* sigfnx keeps the signature */
+               if (rc == 1)
+                       rc = 0;
+       }
+
+ leave:
+       ksign_free_signature(sig);
+       return rc;
+} /* end ksign_parse_signature() */
+
+/*****************************************************************************/
+/*
+ * parse the next packet and call appropriate handler function for known types
+ * - returns:
+ *     0 on EOF
+ *     1 if there might be more packets
+ *     -EBADMSG if the packet is in an invalid format
+ *     -ve on other error
+ */
+static int ksign_parse_one_packet(const uint8_t **datap,
+                                 const uint8_t *endp,
+                                 ksign_signature_actor_t sigfnx,
+                                 ksign_public_key_actor_t pkfnx,
+                                 ksign_user_id_actor_t uidfnx,
+                                 void *data)
+{
+       int rc, c, ctb, pkttype, lenuint8_ts;
+       unsigned long pktlen;
+       uint8_t hdr[8];
+       int hdrlen;
+
+       /* extract the next packet and dispatch it */
+       rc = 0;
+       if (*datap >= endp)
+               goto leave;
+       ctb = *(*datap)++;
+
+       rc = -EBADMSG;
+
+       hdrlen = 0;
+       hdr[hdrlen++] = ctb;
+       if (!(ctb & 0x80)) {
+               printk("ksign: invalid packet (ctb=%02x)\n", ctb);
+               goto leave;
+       }
+
+       pktlen = 0;
+       if (ctb & 0x40) {
+               pkttype = ctb & 0x3f;
+               if (*datap >= endp) {
+                       printk("ksign: 1st length byte missing\n");
+                       goto leave;
+               }
+               c = *(*datap)++;
+               hdr[hdrlen++] = c;
+
+               if (c < 192) {
+                       pktlen = c;
+               }
+               else if (c < 224) {
+                       pktlen = (c - 192) * 256;
+                       if (*datap >= endp) {
+                               printk("ksign: 2nd length uint8_t missing\n");
+                               goto leave;
+                       }
+                       c = *(*datap)++;
+                       hdr[hdrlen++] = c;
+                       pktlen += c + 192;
+               }
+               else if (c == 255) {
+                       if (*datap + 3 >= endp) {
+                               printk("ksign: 4 uint8_t length invalid\n");
+                               goto leave;
+                       }
+                       pktlen  = (hdr[hdrlen++] = *(*datap)++ << 24    );
+                       pktlen |= (hdr[hdrlen++] = *(*datap)++ << 16    );
+                       pktlen |= (hdr[hdrlen++] = *(*datap)++ <<  8    );
+                       pktlen |= (hdr[hdrlen++] = *(*datap)++ <<  0    );
+               }
+               else {
+                       pktlen = 0;/* to indicate partial length */
+               }
+       }
+       else {
+               pkttype = (ctb >> 2) & 0xf;
+               lenuint8_ts = ((ctb & 3) == 3) ? 0 : (1 << (ctb & 3));
+               if( !lenuint8_ts ) {
+                       pktlen = 0; /* don't know the value */
+               }
+               else {
+                       if (*datap + lenuint8_ts > endp) {
+                               printk("ksign: length uint8_ts missing\n");
+                               goto leave;
+                       }
+                       for( ; lenuint8_ts; lenuint8_ts-- ) {
+                               pktlen <<= 8;
+                               pktlen |= hdr[hdrlen++] = *(*datap)++;
+                       }
+               }
+       }
+
+       if (*datap + pktlen > endp) {
+               printk("ksign: packet length longer than available data\n");
+               goto leave;
+       }
+
+       /* deal with the next packet appropriately */
+       switch (pkttype) {
+       case PKT_PUBLIC_KEY:
+               rc = ksign_parse_key(*datap, *datap + pktlen, hdr, hdrlen, pkfnx, data);
+               break;
+       case PKT_SIGNATURE:
+               rc = ksign_parse_signature(*datap, *datap + pktlen, sigfnx, data);
+               break;
+       case PKT_USER_ID:
+               rc = ksign_parse_user_id(*datap, *datap + pktlen, uidfnx, data);
+               break;
+       default:
+               rc = 0; /* unknown packet */
+               break;
+       }
+
+       *datap += pktlen;
+ leave:
+       return rc;
+} /* end ksign_parse_one_packet() */
+
+/*****************************************************************************/
+/*
+ * parse the contents of a packet buffer, passing the signature, public key and
+ * user ID to the caller's callback functions
+ */
+int ksign_parse_packets(const uint8_t *buf,
+                       size_t size,
+                       ksign_signature_actor_t sigfnx,
+                       ksign_public_key_actor_t pkfnx,
+                       ksign_user_id_actor_t uidfnx,
+                       void *data)
+{
+       const uint8_t *datap, *endp;
+       int rc;
+
+       datap = buf;
+       endp = buf + size;
+       do {
+               rc = ksign_parse_one_packet(&datap, endp,
+                                           sigfnx, pkfnx, uidfnx, data);
+       } while (rc == 0 && datap < endp);
+
+       return rc;
+} /* end ksign_parse_packets() */
diff --git a/crypto/signature/ksign-publickey.c b/crypto/signature/ksign-publickey.c
new file mode 100644 (file)
index 0000000..762e2a8
--- /dev/null
@@ -0,0 +1,19 @@
+#include "local.h"
+
+#include "key.h"
+
+static int __init ksign_init(void)
+{
+       int rc;
+
+       printk("ksign: Installing public key data\n");
+
+       rc = ksign_load_keyring_from_buffer(ksign_def_public_key,
+                                           sizeof(ksign_def_public_key));
+       if (rc < 0)
+               printk("Unable to load default keyring: error=%d\n", -rc);
+
+       return rc;
+}
+
+module_init(ksign_init)
diff --git a/crypto/signature/ksign.c b/crypto/signature/ksign.c
new file mode 100644 (file)
index 0000000..32b0b63
--- /dev/null
@@ -0,0 +1,179 @@
+/* ksign.c: signature checker
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <asm/errno.h>
+#include "local.h"
+
+#if 0
+#define _debug(FMT, ...) printk(KERN_DEBUG FMT, ##__VA_ARGS__)
+#else
+#define _debug(FMT, ...) do { ; } while (0)
+#endif
+
+/*****************************************************************************/
+/*
+ * check the signature which is contained in SIG.
+ */
+static int ksign_signature_check(const struct ksign_signature *sig,
+                                struct crypto_tfm *sha1_tfm)
+{
+       struct ksign_public_key *pk;
+       uint8_t sha1[SHA1_DIGEST_SIZE];
+       MPI result = NULL;
+       int rc = 0, i;
+
+       pk = ksign_get_public_key(sig->keyid);
+       if (!pk) {
+               printk("ksign: module signed with unknown public key\n");
+               printk("- signature keyid: %08x%08x ver=%u\n",
+                      sig->keyid[0], sig->keyid[1], sig->version);
+               return -EPERM;
+       }
+
+       if (pk->timestamp > sig->timestamp)
+               printk("ksign:"
+                      " public key is %lu seconds newer than the signature\n",
+                      pk->timestamp - sig->timestamp);
+
+       /* complete the digest */
+       if (sig->version >= 4)
+               SHA1_putc(sha1_tfm, sig->version);
+       SHA1_putc(sha1_tfm, sig->sig_class);
+
+       if (sig->version < 4) {
+               u32 a = sig->timestamp;
+               SHA1_putc(sha1_tfm, (a >> 24) & 0xff);
+               SHA1_putc(sha1_tfm, (a >> 16) & 0xff);
+               SHA1_putc(sha1_tfm, (a >>  8) & 0xff);
+               SHA1_putc(sha1_tfm, (a >>  0) & 0xff);
+       }
+       else {
+               uint8_t buf[6];
+               size_t n;
+               SHA1_putc(sha1_tfm, PUBKEY_ALGO_DSA);
+               SHA1_putc(sha1_tfm, DIGEST_ALGO_SHA1);
+               if (sig->hashed_data) {
+                       n = (sig->hashed_data[0] << 8) | sig->hashed_data[1];
+                       SHA1_write(sha1_tfm, sig->hashed_data, n + 2);
+                       n += 6;
+               }
+               else {
+                       n = 6;
+               }
+
+               /* add some magic */
+               buf[0] = sig->version;
+               buf[1] = 0xff;
+               buf[2] = n >> 24;
+               buf[3] = n >> 16;
+               buf[4] = n >>  8;
+               buf[5] = n;
+               SHA1_write(sha1_tfm, buf, 6);
+       }
+
+       crypto_digest_final(sha1_tfm, sha1);
+       crypto_free_tfm(sha1_tfm);
+
+
+
+
+
+
+       rc = -ENOMEM;
+       result = mpi_alloc((SHA1_DIGEST_SIZE + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB);
+       if (!result)
+               goto cleanup;
+
+       rc = mpi_set_buffer(result, sha1, SHA1_DIGEST_SIZE, 0);
+       if (rc < 0)
+               goto cleanup;
+
+       rc = DSA_verify(result, sig->data, pk->pkey);
+
+ cleanup:
+       mpi_free(result);
+       ksign_put_public_key(pk);
+
+       return rc;
+} /* end ksign_signature_check() */
+
+/*****************************************************************************/
+/*
+ * examine the signatures that are parsed out of the signature data - we keep
+ * the first one that's appropriate and ignore the rest
+ * - return 0 if signature of interest (sig not freed by caller)
+ * - return 1 if no interest (caller frees)
+ */
+static int ksign_grab_signature(struct ksign_signature *sig, void *fnxdata)
+{
+       struct ksign_signature **_sig = fnxdata;
+
+       if (sig->sig_class != 0x00) {
+               _debug("ksign: standalone signature of class 0x%02x\n",
+                      sig->sig_class);
+               return 1;
+       }
+
+       if (*_sig)
+               return 1;
+
+       *_sig = sig;
+       return 0;
+} /* end ksign_grab_signature() */
+
+/*****************************************************************************/
+/*
+ * verify the signature of some data with one of the kernel's known public keys
+ * - the SHA1 context should be currently open with the signed data digested
+ *   into it so that more data can be appended
+ * - the SHA1 context is finalised and freed before returning
+ */
+int ksign_verify_signature(const char *sigdata, unsigned sig_size,
+                          struct crypto_tfm *sha1)
+{
+       struct ksign_signature *sig = NULL;
+       int retval;
+
+       /* parse the signature data to get the actual signature */
+       retval = ksign_parse_packets(sigdata, sig_size,
+                                    &ksign_grab_signature, NULL, NULL,
+                                    &sig);
+       if (retval < 0)
+               goto cleanup;
+
+       if (!sig) {
+               printk("Couldn't find valid DSA signature in module\n");
+               return -ENOENT;
+       }
+
+       _debug("signature keyid: %08x%08x ver=%u\n",
+              sig->keyid[0], sig->keyid[1], sig->version);
+
+       /* check the data SHA1 transformation against the public key */
+       retval = ksign_signature_check(sig, sha1);
+       if (retval == 0) {
+               _debug("ksign: Signature check succeeded\n");
+       }
+       else if (retval != -ENOMEM) {
+               _debug("ksign: Signature check failed\n");
+               retval = -EPERM;
+       }
+       else {
+               _debug("ksign: Signature check ENOMEM\n");
+       }
+
+ cleanup:
+       if (sig)
+               ksign_free_signature(sig);
+
+       return retval;
+} /* end ksign_verify_signature() */
diff --git a/crypto/signature/local.h b/crypto/signature/local.h
new file mode 100644 (file)
index 0000000..5d2fa52
--- /dev/null
@@ -0,0 +1,163 @@
+/* local.h: kernel signature checker internal defs
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * - Derived from GnuPG packet.h - packet definitions
+ *   - Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <linux/list.h>
+#include <linux/crypto.h>
+#include <linux/crypto/ksign.h>
+#include <linux/crypto/mpi.h>
+#include <asm/atomic.h>
+
+#define SHA1_DIGEST_SIZE       20
+
+#define PUBKEY_USAGE_SIG       1           /* key is good for signatures */
+#define PUBKEY_USAGE_ENC       2           /* key is good for encryption */
+
+#define PUBKEY_ALGO_DSA                17
+#define DSA_NPKEY              4       /* number of MPI's in DSA public key */
+#define DSA_NSIG               2       /* number of MPI's in DSA signature */
+
+#define DIGEST_ALGO_SHA1       2
+
+typedef enum {
+       PKT_NONE                        = 0,
+       PKT_SIGNATURE                   = 2,    /* secret key encrypted packet */
+       PKT_PUBLIC_KEY                  = 6,    /* public key */
+       PKT_USER_ID                     = 13,   /* user id packet */
+} pkttype_t;
+
+typedef enum {
+       SIGSUBPKT_TEST_CRITICAL         = -3,
+       SIGSUBPKT_NONE                  = 0,
+       SIGSUBPKT_SIG_CREATED           = 2,    /* signature creation time */
+       SIGSUBPKT_SIG_EXPIRE            = 3,    /* signature expiration time */
+       SIGSUBPKT_EXPORTABLE            = 4,    /* exportable */
+       SIGSUBPKT_TRUST                 = 5,    /* trust signature */
+       SIGSUBPKT_REGEXP                = 6,    /* regular expression */
+       SIGSUBPKT_REVOCABLE             = 7,    /* revocable */
+       SIGSUBPKT_KEY_EXPIRE            = 9,    /* key expiration time */
+       SIGSUBPKT_ARR                   = 10,   /* additional recipient request */
+       SIGSUBPKT_PREF_SYM              = 11,   /* preferred symmetric algorithms */
+       SIGSUBPKT_REV_KEY               = 12,   /* revocation key */
+       SIGSUBPKT_ISSUER                = 16,   /* issuer key ID */
+       SIGSUBPKT_NOTATION              = 20,   /* notation data */
+       SIGSUBPKT_PREF_HASH             = 21,   /* preferred hash algorithms */
+       SIGSUBPKT_PREF_COMPR            = 22,   /* preferred compression algorithms */
+       SIGSUBPKT_KS_FLAGS              = 23,   /* key server preferences */
+       SIGSUBPKT_PREF_KS               = 24,   /* preferred key server */
+       SIGSUBPKT_PRIMARY_UID           = 25,   /* primary user id */
+       SIGSUBPKT_POLICY                = 26,   /* policy URL */
+       SIGSUBPKT_KEY_FLAGS             = 27,   /* key flags */
+       SIGSUBPKT_SIGNERS_UID           = 28,   /* signer's user id */
+       SIGSUBPKT_REVOC_REASON          = 29,   /* reason for revocation */
+       SIGSUBPKT_PRIV_VERIFY_CACHE     = 101,  /* cache verification result */
+
+       SIGSUBPKT_FLAG_CRITICAL         = 128
+} sigsubpkttype_t;
+
+/*
+ * signature record
+ */
+struct ksign_signature
+{
+       uint32_t        keyid[2];               /* 64 bit keyid */
+       time_t          timestamp;              /* signature made */
+       uint8_t         version;
+       uint8_t         sig_class;              /* sig classification, append for MD calculation*/
+       uint8_t         *hashed_data;           /* all subpackets with hashed  data (v4 only) */
+       uint8_t         *unhashed_data;         /* ditto for unhashed data */
+       uint8_t         digest_start[2];        /* first 2 uint8_ts of the digest */
+       MPI             data[DSA_NSIG];
+};
+
+extern void ksign_free_signature(struct ksign_signature *sig);
+
+/*
+ * public key record
+ */
+struct ksign_public_key
+{
+       struct list_head link;
+       atomic_t        count;                  /* ref count */
+       time_t          timestamp;              /* key made */
+       time_t          expiredate;             /* expires at this date or 0 if not at all */
+       uint8_t         hdrbytes;               /* number of header bytes */
+       uint8_t         version;
+       int             is_valid;               /* key (especially subkey) is valid */
+       unsigned long   local_id;               /* internal use, valid if > 0 */
+       uint32_t        main_keyid[2];          /* keyid of the primary key */
+       uint32_t        keyid[2];               /* calculated by keyid_from_pk() */
+       MPI             pkey[DSA_NPKEY];
+};
+
+extern void ksign_free_public_key(struct ksign_public_key *pk);
+
+static inline void ksign_put_public_key(struct ksign_public_key *pk)
+{
+       if (atomic_dec_and_test(&pk->count))
+               ksign_free_public_key(pk);
+}
+
+extern int ksign_load_keyring_from_buffer(const void *buffer, size_t size);
+
+extern struct ksign_public_key *ksign_get_public_key(const uint32_t *keyid);
+
+/*
+ * user ID record
+ */
+struct ksign_user_id
+{
+       int             len;                    /* length of the name */
+       char            name[0];
+};
+
+extern void ksign_free_user_id(struct ksign_user_id *uid);
+
+/*
+ *
+ */
+typedef int (*ksign_signature_actor_t)(struct ksign_signature *, void *fnxdata);
+typedef int (*ksign_public_key_actor_t)(struct ksign_public_key *, void *fnxdata);
+typedef int (*ksign_user_id_actor_t)(struct ksign_user_id *, void *fnxdata);
+
+extern int ksign_parse_packets(const uint8_t *buf,
+                              size_t size,
+                              ksign_signature_actor_t sigfnx,
+                              ksign_public_key_actor_t pkfnx,
+                              ksign_user_id_actor_t uidfnx,
+                              void *data);
+
+extern int DSA_verify(const MPI datahash, const MPI sig[], const MPI pkey[]);
+
+/*
+ * fast access to the digest
+ * - we _know_ the data is locked into kernel memory, so we don't want to have
+ *   to kmap() it
+ */
+static inline void SHA1_putc(struct crypto_tfm *sha1, uint8_t ch)
+{
+       crypto_digest_update_kernel(sha1, &ch, 1);
+}
+
+static inline void SHA1_write(struct crypto_tfm *sha1, const void *s, size_t n)
+{
+       crypto_digest_update_kernel(sha1, s, n);
+}
diff --git a/drivers/char/lcd.h b/drivers/char/lcd.h
new file mode 100644 (file)
index 0000000..8aed498
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * LED, LCD and Button panel driver for Cobalt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 1997 by Andrew Bose
+ *
+ * Linux kernel version history:
+ *       March 2001: Ported from 2.0.34  by Liam Davies
+ *
+ */
+
+// function headers
+
+static int dqpoll(volatile unsigned long, volatile unsigned char );
+static int timeout(volatile unsigned long);
+
+#define LCD_CHARS_PER_LINE 40
+#define FLASH_SIZE 524288
+#define MAX_IDLE_TIME 120
+
+struct lcd_display {
+        unsigned long buttons;
+        int size1;
+        int size2;
+        unsigned char line1[LCD_CHARS_PER_LINE];
+        unsigned char line2[LCD_CHARS_PER_LINE];
+        unsigned char cursor_address;
+        unsigned char character;
+        unsigned char leds;
+        unsigned char *RomImage;
+};
+
+
+
+#define LCD_DRIVER     "Cobalt LCD Driver v2.10"
+
+#define kLCD_IR                0x0F000000
+#define kLCD_DR                0x0F000010
+#define kGPI           0x0D000000
+#define kLED           0x0C000000
+
+#define kDD_R00         0x00
+#define kDD_R01         0x27
+#define kDD_R10         0x40
+#define kDD_R11         0x67
+
+#define kLCD_Addr       0x00000080
+
+#define LCDTimeoutValue        0xfff
+
+
+// Flash definitions AMD 29F040
+#define kFlashBase     0x0FC00000
+
+#define kFlash_Addr1    0x5555
+#define kFlash_Addr2    0x2AAA
+#define kFlash_Data1    0xAA
+#define kFlash_Data2    0x55
+#define kFlash_Prog     0xA0
+#define kFlash_Erase3   0x80
+#define kFlash_Erase6   0x10
+#define kFlash_Read     0xF0
+
+#define kFlash_ID       0x90
+#define kFlash_VenAddr  0x00
+#define kFlash_DevAddr  0x01
+#define kFlash_VenID    0x01
+#define kFlash_DevID    0xA4    // 29F040
+//#define kFlash_DevID  0xAD    // 29F016
+
+
+// Macros
+
+#define LCDWriteData(x)        outl((x << 24), kLCD_DR)
+#define LCDWriteInst(x)        outl((x << 24), kLCD_IR)
+
+#define LCDReadData    (inl(kLCD_DR) >> 24)
+#define LCDReadInst    (inl(kLCD_IR) >> 24)
+
+#define GPIRead                (inl(kGPI) >> 24)
+
+#define LEDSet(x)      outb((char)x, kLED)
+
+#define WRITE_GAL(x,y) outl(y, 0x04000000 | (x))
+#define BusyCheck()    while ((LCDReadInst & 0x80) == 0x80)
+
+#define WRITE_FLASH(x,y) outb((char)y, kFlashBase | (x))
+#define READ_FLASH(x)  (inb(kFlashBase | (x)))
+
+
+
+/*
+ * Function command codes for io_ctl.
+ */
+#define LCD_On                 1
+#define LCD_Off                        2
+#define LCD_Clear              3
+#define LCD_Reset              4
+#define LCD_Cursor_Left                5
+#define LCD_Cursor_Right       6
+#define LCD_Disp_Left          7
+#define LCD_Disp_Right         8
+#define LCD_Get_Cursor         9
+#define LCD_Set_Cursor         10
+#define LCD_Home               11
+#define LCD_Read               12
+#define LCD_Write              13
+#define LCD_Cursor_Off         14
+#define LCD_Cursor_On          15
+#define LCD_Get_Cursor_Pos     16
+#define LCD_Set_Cursor_Pos     17
+#define LCD_Blink_Off           18
+
+#define LED_Set                        40
+#define LED_Bit_Set            41
+#define LED_Bit_Clear          42
+
+
+//  Button defs
+#define BUTTON_Read             50
+
+//  Flash command codes
+#define FLASH_Erase            60
+#define FLASH_Burn             61
+#define FLASH_Read             62
+
+
+// Ethernet LINK check hackaroo
+#define LINK_Check              90
+#define LINK_Check_2           91
+
+//  Button patterns  _B - single layer lcd boards
+
+#define BUTTON_NONE               0x3F
+#define BUTTON_NONE_B             0xFE
+
+#define BUTTON_Left               0x3B
+#define BUTTON_Left_B             0xFA
+
+#define BUTTON_Right              0x37
+#define BUTTON_Right_B            0xDE
+
+#define BUTTON_Up                 0x2F
+#define BUTTON_Up_B               0xF6
+
+#define BUTTON_Down               0x1F
+#define BUTTON_Down_B             0xEE
+
+#define BUTTON_Next               0x3D
+#define BUTTON_Next_B             0x7E
+
+#define BUTTON_Enter              0x3E
+#define BUTTON_Enter_B            0xBE
+
+#define BUTTON_Reset_B            0xFC
+
+
+// debounce constants
+
+#define BUTTON_SENSE            160000
+#define BUTTON_DEBOUNCE                5000
+
+
+//  Galileo register stuff
+
+#define kGal_DevBank2Cfg        0x1466DB33
+#define kGal_DevBank2PReg       0x464
+#define kGal_DevBank3Cfg        0x146FDFFB
+#define kGal_DevBank3PReg       0x468
+
+// Network
+
+#define kIPADDR                        1
+#define kNETMASK               2
+#define kGATEWAY               3
+#define kDNS                   4
+
+#define kClassA                        5
+#define kClassB                        6
+#define kClassC                        7
+
diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c
new file mode 100644 (file)
index 0000000..61457c5
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2002, 2003, 2004 Hewlett-Packard Co.
+ *     Khalid Aziz <khalid_aziz@hp.com>
+ *     Alex Williamson <alex.williamson@hp.com>
+ *     Bjorn Helgaas <bjorn.helgaas@hp.com>
+ *
+ * Parse the EFI PCDP table to locate the console device.
+ */
+
+#include <linux/acpi.h>
+#include <linux/console.h>
+#include <linux/efi.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <asm/io.h>
+#include <asm/serial.h>
+#include "pcdp.h"
+
+static inline int
+uart_irq_supported(int rev, struct pcdp_uart *uart)
+{
+       if (rev < 3)
+               return uart->pci_func & PCDP_UART_IRQ;
+       return uart->flags & PCDP_UART_IRQ;
+}
+
+static inline int
+uart_pci(int rev, struct pcdp_uart *uart)
+{
+       if (rev < 3)
+               return uart->pci_func & PCDP_UART_PCI;
+       return uart->flags & PCDP_UART_PCI;
+}
+
+static inline int
+uart_active_high_low(int rev, struct pcdp_uart *uart)
+{
+       if (uart_pci(rev, uart) || uart->flags & PCDP_UART_ACTIVE_LOW)
+               return ACPI_ACTIVE_LOW;
+       return ACPI_ACTIVE_HIGH;
+}
+
+static inline int
+uart_edge_level(int rev, struct pcdp_uart *uart)
+{
+       if (uart_pci(rev, uart))
+               return ACPI_LEVEL_SENSITIVE;
+       if (rev < 3 || uart->flags & PCDP_UART_EDGE_SENSITIVE)
+               return ACPI_EDGE_SENSITIVE;
+       return ACPI_LEVEL_SENSITIVE;
+}
+
+static void __init
+setup_serial_console(int rev, struct pcdp_uart *uart)
+{
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+       struct uart_port port;
+       static char options[16];
+       int mapsize = 64;
+
+       memset(&port, 0, sizeof(port));
+       port.uartclk = uart->clock_rate;
+       if (!port.uartclk)      /* some FW doesn't supply this */
+               port.uartclk = BASE_BAUD * 16;
+
+       if (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
+               port.mapbase = uart->addr.address;
+               port.membase = ioremap(port.mapbase, mapsize);
+               if (!port.membase) {
+                       printk(KERN_ERR "%s: couldn't ioremap 0x%lx-0x%lx\n",
+                               __FUNCTION__, port.mapbase, port.mapbase + mapsize);
+                       return;
+               }
+               port.iotype = UPIO_MEM;
+       } else if (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
+               port.iobase = uart->addr.address;
+               port.iotype = UPIO_PORT;
+       } else
+               return;
+
+       switch (uart->pci_prog_intfc) {
+               case 0x0: port.type = PORT_8250;    break;
+               case 0x1: port.type = PORT_16450;   break;
+               case 0x2: port.type = PORT_16550;   break;
+               case 0x3: port.type = PORT_16650;   break;
+               case 0x4: port.type = PORT_16750;   break;
+               case 0x5: port.type = PORT_16850;   break;
+               case 0x6: port.type = PORT_16C950;  break;
+               default:  port.type = PORT_UNKNOWN; break;
+       }
+
+       port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
+
+       if (uart_irq_supported(rev, uart)) {
+               port.irq = acpi_register_gsi(uart->gsi,
+                       uart_active_high_low(rev, uart),
+                       uart_edge_level(rev, uart));
+               port.flags |= UPF_AUTO_IRQ;  /* some FW reported wrong GSI */
+               if (uart_pci(rev, uart))
+                       port.flags |= UPF_SHARE_IRQ;
+       }
+
+       if (early_serial_setup(&port) < 0)
+               return;
+
+       snprintf(options, sizeof(options), "%lun%d", uart->baud,
+               uart->bits ? uart->bits : 8);
+       add_preferred_console("ttyS", port.line, options);
+
+       printk(KERN_INFO "PCDP: serial console at %s 0x%lx (ttyS%d, options %s)\n",
+               port.iotype == UPIO_MEM ? "MMIO" : "I/O",
+               uart->addr.address, port.line, options);
+#endif
+}
+
+static void __init
+setup_vga_console(struct pcdp_vga *vga)
+{
+#ifdef CONFIG_VT
+#ifdef CONFIG_VGA_CONSOLE
+       if (efi_mem_type(0xA0000) == EFI_CONVENTIONAL_MEMORY) {
+               printk(KERN_ERR "PCDP: VGA selected, but frame buffer is not MMIO!\n");
+               return;
+       }
+
+       conswitchp = &vga_con;
+       printk(KERN_INFO "PCDP: VGA console\n");
+#endif
+#endif
+}
+
+void __init
+efi_setup_pcdp_console(char *cmdline)
+{
+       struct pcdp *pcdp;
+       struct pcdp_uart *uart;
+       struct pcdp_device *dev, *end;
+       int i, serial = 0;
+
+       pcdp = efi.hcdp;
+       if (!pcdp)
+               return;
+
+       printk(KERN_INFO "PCDP: v%d at 0x%p\n", pcdp->rev, pcdp);
+
+       if (pcdp->rev < 3) {
+               if (strstr(cmdline, "console=ttyS0") || efi_uart_console_only())
+                       serial = 1;
+       }
+
+       for (i = 0, uart = pcdp->uart; i < pcdp->num_uarts; i++, uart++) {
+               if (uart->flags & PCDP_UART_PRIMARY_CONSOLE || serial) {
+                       if (uart->type == PCDP_CONSOLE_UART) {
+                               setup_serial_console(pcdp->rev, uart);
+                               return;
+                       }
+               }
+       }
+
+       end = (struct pcdp_device *) ((u8 *) pcdp + pcdp->length);
+       for (dev = (struct pcdp_device *) (pcdp->uart + pcdp->num_uarts);
+            dev < end;
+            dev = (struct pcdp_device *) ((u8 *) dev + dev->length)) {
+               if (dev->flags & PCDP_PRIMARY_CONSOLE) {
+                       if (dev->type == PCDP_CONSOLE_VGA) {
+                               setup_vga_console((struct pcdp_vga *) dev);
+                               return;
+                       }
+               }
+       }
+}
+
+#ifdef CONFIG_IA64_EARLY_PRINTK_UART
+unsigned long
+hcdp_early_uart (void)
+{
+       efi_system_table_t *systab;
+       efi_config_table_t *config_tables;
+       unsigned long addr = 0;
+       struct pcdp *pcdp = 0;
+       struct pcdp_uart *uart;
+       int i;
+
+       systab = (efi_system_table_t *) ia64_boot_param->efi_systab;
+       if (!systab)
+               return 0;
+       systab = __va(systab);
+
+       config_tables = (efi_config_table_t *) systab->tables;
+       if (!config_tables)
+               return 0;
+       config_tables = __va(config_tables);
+
+       for (i = 0; i < systab->nr_tables; i++) {
+               if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
+                       pcdp = (struct pcdp *) config_tables[i].table;
+                       break;
+               }
+       }
+       if (!pcdp)
+               return 0;
+       pcdp = __va(pcdp);
+
+       for (i = 0, uart = pcdp->uart; i < pcdp->num_uarts; i++, uart++) {
+               if (uart->type == PCDP_CONSOLE_UART) {
+                       addr = uart->addr.address;
+                       break;
+               }
+       }
+       return addr;
+}
+#endif /* CONFIG_IA64_EARLY_PRINTK_UART */
diff --git a/drivers/firmware/pcdp.h b/drivers/firmware/pcdp.h
new file mode 100644 (file)
index 0000000..4217c3b
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2002, 2004 Hewlett-Packard Co.
+ *     Khalid Aziz <khalid_aziz@hp.com>
+ *     Bjorn Helgaas <bjorn.helgaas@hp.com>
+ *
+ * Definitions for PCDP-defined console devices
+ *
+ * v1.0a: http://www.dig64.org/specifications/DIG64_HCDPv10a_01.pdf
+ * v2.0:  http://www.dig64.org/specifications/DIG64_HCDPv20_042804.pdf
+ */
+
+#define PCDP_CONSOLE                   0
+#define PCDP_DEBUG                     1
+#define PCDP_CONSOLE_OUTPUT            2
+#define PCDP_CONSOLE_INPUT             3
+
+#define PCDP_UART                      (0 << 3)
+#define PCDP_VGA                       (1 << 3)
+#define PCDP_USB                       (2 << 3)
+
+/* pcdp_uart.type and pcdp_device.type */
+#define PCDP_CONSOLE_UART              (PCDP_UART | PCDP_CONSOLE)
+#define PCDP_DEBUG_UART                        (PCDP_UART | PCDP_DEBUG)
+#define PCDP_CONSOLE_VGA               (PCDP_VGA  | PCDP_CONSOLE_OUTPUT)
+#define PCDP_CONSOLE_USB               (PCDP_USB  | PCDP_CONSOLE_INPUT)
+
+/* pcdp_uart.flags */
+#define PCDP_UART_EDGE_SENSITIVE       (1 << 0)
+#define PCDP_UART_ACTIVE_LOW           (1 << 1)
+#define PCDP_UART_PRIMARY_CONSOLE      (1 << 2)
+#define PCDP_UART_IRQ                  (1 << 6) /* in pci_func for rev < 3 */
+#define PCDP_UART_PCI                  (1 << 7) /* in pci_func for rev < 3 */
+
+struct pcdp_uart {
+       u8                              type;
+       u8                              bits;
+       u8                              parity;
+       u8                              stop_bits;
+       u8                              pci_seg;
+       u8                              pci_bus;
+       u8                              pci_dev;
+       u8                              pci_func;
+       u64                             baud;
+       struct acpi_generic_address     addr;
+       u16                             pci_dev_id;
+       u16                             pci_vendor_id;
+       u32                             gsi;
+       u32                             clock_rate;
+       u8                              pci_prog_intfc;
+       u8                              flags;
+};
+
+struct pcdp_vga {
+       u8                      count;          /* address space descriptors */
+};
+
+/* pcdp_device.flags */
+#define PCDP_PRIMARY_CONSOLE   1
+
+struct pcdp_device {
+       u8                      type;
+       u8                      flags;
+       u16                     length;
+       u16                     efi_index;
+};
+
+struct pcdp {
+       u8                      signature[4];
+       u32                     length;
+       u8                      rev;            /* PCDP v2.0 is rev 3 */
+       u8                      chksum;
+       u8                      oemid[6];
+       u8                      oem_tabid[8];
+       u32                     oem_rev;
+       u8                      creator_id[4];
+       u32                     creator_rev;
+       u32                     num_uarts;
+       struct pcdp_uart        uart[0];        /* actual size is num_uarts */
+       /* remainder of table is pcdp_device structures */
+};
diff --git a/drivers/media/video/ovcamchip/ov6x20.c b/drivers/media/video/ovcamchip/ov6x20.c
new file mode 100644 (file)
index 0000000..3433619
--- /dev/null
@@ -0,0 +1,415 @@
+/* OmniVision OV6620/OV6120 Camera Chip Support Code
+ *
+ * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org>
+ * http://alpha.dyndns.org/ov511/
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
+ */
+
+#define DEBUG
+
+#include <linux/slab.h>
+#include "ovcamchip_priv.h"
+
+/* Registers */
+#define REG_GAIN               0x00    /* gain [5:0] */
+#define REG_BLUE               0x01    /* blue gain */
+#define REG_RED                        0x02    /* red gain */
+#define REG_SAT                        0x03    /* saturation */
+#define REG_CNT                        0x05    /* Y contrast */
+#define REG_BRT                        0x06    /* Y brightness */
+#define REG_WB_BLUE            0x0C    /* WB blue ratio [5:0] */
+#define REG_WB_RED             0x0D    /* WB red ratio [5:0] */
+#define REG_EXP                        0x10    /* exposure */
+
+/* Window parameters */
+#define HWSBASE 0x38
+#define HWEBASE 0x3A
+#define VWSBASE 0x05
+#define VWEBASE 0x06
+
+struct ov6x20 {
+       int auto_brt;
+       int auto_exp;
+       int backlight;
+       int bandfilt;
+       int mirror;
+};
+
+/* Initial values for use with OV511/OV511+ cameras */
+static struct ovcamchip_regvals regvals_init_6x20_511[] = {
+       { 0x12, 0x80 }, /* reset */
+       { 0x11, 0x01 },
+       { 0x03, 0x60 },
+       { 0x05, 0x7f }, /* For when autoadjust is off */
+       { 0x07, 0xa8 },
+       { 0x0c, 0x24 },
+       { 0x0d, 0x24 },
+       { 0x0f, 0x15 }, /* COMS */
+       { 0x10, 0x75 }, /* AEC Exposure time */
+       { 0x12, 0x24 }, /* Enable AGC and AWB */
+       { 0x14, 0x04 },
+       { 0x16, 0x03 },
+       { 0x26, 0xb2 }, /* BLC enable */
+       /* 0x28: 0x05 Selects RGB format if RGB on */
+       { 0x28, 0x05 },
+       { 0x2a, 0x04 }, /* Disable framerate adjust */
+       { 0x2d, 0x99 },
+       { 0x33, 0xa0 }, /* Color Processing Parameter */
+       { 0x34, 0xd2 }, /* Max A/D range */
+       { 0x38, 0x8b },
+       { 0x39, 0x40 },
+
+       { 0x3c, 0x39 }, /* Enable AEC mode changing */
+       { 0x3c, 0x3c }, /* Change AEC mode */
+       { 0x3c, 0x24 }, /* Disable AEC mode changing */
+
+       { 0x3d, 0x80 },
+       /* These next two registers (0x4a, 0x4b) are undocumented. They
+        * control the color balance */
+       { 0x4a, 0x80 },
+       { 0x4b, 0x80 },
+       { 0x4d, 0xd2 }, /* This reduces noise a bit */
+       { 0x4e, 0xc1 },
+       { 0x4f, 0x04 },
+       { 0xff, 0xff }, /* END MARKER */
+};
+
+/* Initial values for use with OV518 cameras */
+static struct ovcamchip_regvals regvals_init_6x20_518[] = {
+       { 0x12, 0x80 }, /* Do a reset */
+       { 0x03, 0xc0 }, /* Saturation */
+       { 0x05, 0x8a }, /* Contrast */
+       { 0x0c, 0x24 }, /* AWB blue */
+       { 0x0d, 0x24 }, /* AWB red */
+       { 0x0e, 0x8d }, /* Additional 2x gain */
+       { 0x0f, 0x25 }, /* Black expanding level = 1.3V */
+       { 0x11, 0x01 }, /* Clock div. */
+       { 0x12, 0x24 }, /* Enable AGC and AWB */
+       { 0x13, 0x01 }, /* (default) */
+       { 0x14, 0x80 }, /* Set reserved bit 7 */
+       { 0x15, 0x01 }, /* (default) */
+       { 0x16, 0x03 }, /* (default) */
+       { 0x17, 0x38 }, /* (default) */
+       { 0x18, 0xea }, /* (default) */
+       { 0x19, 0x04 },
+       { 0x1a, 0x93 },
+       { 0x1b, 0x00 }, /* (default) */
+       { 0x1e, 0xc4 }, /* (default) */
+       { 0x1f, 0x04 }, /* (default) */
+       { 0x20, 0x20 }, /* Enable 1st stage aperture correction */
+       { 0x21, 0x10 }, /* Y offset */
+       { 0x22, 0x88 }, /* U offset */
+       { 0x23, 0xc0 }, /* Set XTAL power level */
+       { 0x24, 0x53 }, /* AEC bright ratio */
+       { 0x25, 0x7a }, /* AEC black ratio */
+       { 0x26, 0xb2 }, /* BLC enable */
+       { 0x27, 0xa2 }, /* Full output range */
+       { 0x28, 0x01 }, /* (default) */
+       { 0x29, 0x00 }, /* (default) */
+       { 0x2a, 0x84 }, /* (default) */
+       { 0x2b, 0xa8 }, /* Set custom frame rate */
+       { 0x2c, 0xa0 }, /* (reserved) */
+       { 0x2d, 0x95 }, /* Enable banding filter */
+       { 0x2e, 0x88 }, /* V offset */
+       { 0x33, 0x22 }, /* Luminance gamma on */
+       { 0x34, 0xc7 }, /* A/D bias */
+       { 0x36, 0x12 }, /* (reserved) */
+       { 0x37, 0x63 }, /* (reserved) */
+       { 0x38, 0x8b }, /* Quick AEC/AEB */
+       { 0x39, 0x00 }, /* (default) */
+       { 0x3a, 0x0f }, /* (default) */
+       { 0x3b, 0x3c }, /* (default) */
+       { 0x3c, 0x5c }, /* AEC controls */
+       { 0x3d, 0x80 }, /* Drop 1 (bad) frame when AEC change */
+       { 0x3e, 0x80 }, /* (default) */
+       { 0x3f, 0x02 }, /* (default) */
+       { 0x40, 0x10 }, /* (reserved) */
+       { 0x41, 0x10 }, /* (reserved) */
+       { 0x42, 0x00 }, /* (reserved) */
+       { 0x43, 0x7f }, /* (reserved) */
+       { 0x44, 0x80 }, /* (reserved) */
+       { 0x45, 0x1c }, /* (reserved) */
+       { 0x46, 0x1c }, /* (reserved) */
+       { 0x47, 0x80 }, /* (reserved) */
+       { 0x48, 0x5f }, /* (reserved) */
+       { 0x49, 0x00 }, /* (reserved) */
+       { 0x4a, 0x00 }, /* Color balance (undocumented) */
+       { 0x4b, 0x80 }, /* Color balance (undocumented) */
+       { 0x4c, 0x58 }, /* (reserved) */
+       { 0x4d, 0xd2 }, /* U *= .938, V *= .838 */
+       { 0x4e, 0xa0 }, /* (default) */
+       { 0x4f, 0x04 }, /* UV 3-point average */
+       { 0x50, 0xff }, /* (reserved) */
+       { 0x51, 0x58 }, /* (reserved) */
+       { 0x52, 0xc0 }, /* (reserved) */
+       { 0x53, 0x42 }, /* (reserved) */
+       { 0x27, 0xa6 }, /* Enable manual offset adj. (reg 21 & 22) */
+       { 0x12, 0x20 },
+       { 0x12, 0x24 },
+
+       { 0xff, 0xff }, /* END MARKER */
+};
+
+/* This initializes the OV6x20 camera chip and relevant variables. */
+static int ov6x20_init(struct i2c_client *c)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+       struct ov6x20 *s;
+       int rc;
+
+       DDEBUG(4, &c->dev, "entered");
+
+       switch (c->adapter->id) {
+       case I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV511:
+               rc = ov_write_regvals(c, regvals_init_6x20_511);
+               break;
+       case I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518:
+               rc = ov_write_regvals(c, regvals_init_6x20_518);
+               break;
+       default:
+               dev_err(&c->dev, "ov6x20: Unsupported adapter\n");
+               rc = -ENODEV;
+       }
+
+       if (rc < 0)
+               return rc;
+
+       ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+       if (!s)
+               return -ENOMEM;
+       memset(s, 0, sizeof *s);
+
+       s->auto_brt = 1;
+       s->auto_exp = 1;
+
+       return rc;
+}
+
+static int ov6x20_free(struct i2c_client *c)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+
+       kfree(ov->spriv);
+       return 0;
+}
+
+static int ov6x20_set_control(struct i2c_client *c,
+                             struct ovcamchip_control *ctl)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+       struct ov6x20 *s = ov->spriv;
+       int rc;
+       int v = ctl->value;
+
+       switch (ctl->id) {
+       case OVCAMCHIP_CID_CONT:
+               rc = ov_write(c, REG_CNT, v >> 8);
+               break;
+       case OVCAMCHIP_CID_BRIGHT:
+               rc = ov_write(c, REG_BRT, v >> 8);
+               break;
+       case OVCAMCHIP_CID_SAT:
+               rc = ov_write(c, REG_SAT, v >> 8);
+               break;
+       case OVCAMCHIP_CID_HUE:
+               rc = ov_write(c, REG_RED, 0xFF - (v >> 8));
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write(c, REG_BLUE, v >> 8);
+               break;
+       case OVCAMCHIP_CID_EXP:
+               rc = ov_write(c, REG_EXP, v);
+               break;
+       case OVCAMCHIP_CID_FREQ:
+       {
+               int sixty = (v == 60);
+
+               rc = ov_write(c, 0x2b, sixty?0xa8:0x28);
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write(c, 0x2a, sixty?0x84:0xa4);
+               break;
+       }
+       case OVCAMCHIP_CID_BANDFILT:
+               rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04);
+               s->bandfilt = v;
+               break;
+       case OVCAMCHIP_CID_AUTOBRIGHT:
+               rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10);
+               s->auto_brt = v;
+               break;
+       case OVCAMCHIP_CID_AUTOEXP:
+               rc = ov_write_mask(c, 0x13, v?0x01:0x00, 0x01);
+               s->auto_exp = v;
+               break;
+       case OVCAMCHIP_CID_BACKLIGHT:
+       {
+               rc = ov_write_mask(c, 0x4e, v?0xe0:0xc0, 0xe0);
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write_mask(c, 0x29, v?0x08:0x00, 0x08);
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write_mask(c, 0x0e, v?0x80:0x00, 0x80);
+               s->backlight = v;
+               break;
+       }
+       case OVCAMCHIP_CID_MIRROR:
+               rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40);
+               s->mirror = v;
+               break;
+       default:
+               DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+               return -EPERM;
+       }
+
+out:
+       DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc);
+       return rc;
+}
+
+static int ov6x20_get_control(struct i2c_client *c,
+                             struct ovcamchip_control *ctl)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+       struct ov6x20 *s = ov->spriv;
+       int rc = 0;
+       unsigned char val = 0;
+
+       switch (ctl->id) {
+       case OVCAMCHIP_CID_CONT:
+               rc = ov_read(c, REG_CNT, &val);
+               ctl->value = val << 8;
+               break;
+       case OVCAMCHIP_CID_BRIGHT:
+               rc = ov_read(c, REG_BRT, &val);
+               ctl->value = val << 8;
+               break;
+       case OVCAMCHIP_CID_SAT:
+               rc = ov_read(c, REG_SAT, &val);
+               ctl->value = val << 8;
+               break;
+       case OVCAMCHIP_CID_HUE:
+               rc = ov_read(c, REG_BLUE, &val);
+               ctl->value = val << 8;
+               break;
+       case OVCAMCHIP_CID_EXP:
+               rc = ov_read(c, REG_EXP, &val);
+               ctl->value = val;
+               break;
+       case OVCAMCHIP_CID_BANDFILT:
+               ctl->value = s->bandfilt;
+               break;
+       case OVCAMCHIP_CID_AUTOBRIGHT:
+               ctl->value = s->auto_brt;
+               break;
+       case OVCAMCHIP_CID_AUTOEXP:
+               ctl->value = s->auto_exp;
+               break;
+       case OVCAMCHIP_CID_BACKLIGHT:
+               ctl->value = s->backlight;
+               break;
+       case OVCAMCHIP_CID_MIRROR:
+               ctl->value = s->mirror;
+               break;
+       default:
+               DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+               return -EPERM;
+       }
+
+       DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc);
+       return rc;
+}
+
+static int ov6x20_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
+{
+       /******** QCIF-specific regs ********/
+
+       ov_write(c, 0x14, win->quarter?0x24:0x04);
+
+       /******** Palette-specific regs ********/
+
+       /* OV518 needs 8 bit multiplexed in color mode, and 16 bit in B&W */
+       if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) {
+               if (win->format == VIDEO_PALETTE_GREY)
+                       ov_write_mask(c, 0x13, 0x00, 0x20);
+               else
+                       ov_write_mask(c, 0x13, 0x20, 0x20);
+       } else {
+               if (win->format == VIDEO_PALETTE_GREY)
+                       ov_write_mask(c, 0x13, 0x20, 0x20);
+               else
+                       ov_write_mask(c, 0x13, 0x00, 0x20);
+       }
+
+       /******** Clock programming ********/
+
+       /* The OV6620 needs special handling. This prevents the
+        * severe banding that normally occurs */
+
+       /* Clock down */
+       ov_write(c, 0x2a, 0x04);
+
+       ov_write(c, 0x11, win->clockdiv);
+
+       ov_write(c, 0x2a, 0x84);
+       /* This next setting is critical. It seems to improve
+        * the gain or the contrast. The "reserved" bits seem
+        * to have some effect in this case. */
+       ov_write(c, 0x2d, 0x85); /* FIXME: This messes up banding filter */
+
+       return 0;
+}
+
+static int ov6x20_set_window(struct i2c_client *c, struct ovcamchip_window *win)
+{
+       int ret, hwscale, vwscale;
+
+       ret = ov6x20_mode_init(c, win);
+       if (ret < 0)
+               return ret;
+
+       if (win->quarter) {
+               hwscale = 0;
+               vwscale = 0;
+       } else {
+               hwscale = 1;
+               vwscale = 1;    /* The datasheet says 0; it's wrong */
+       }
+
+       ov_write(c, 0x17, HWSBASE + (win->x >> hwscale));
+       ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale));
+       ov_write(c, 0x19, VWSBASE + (win->y >> vwscale));
+       ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale));
+
+       return 0;
+}
+
+static int ov6x20_command(struct i2c_client *c, unsigned int cmd, void *arg)
+{
+       switch (cmd) {
+       case OVCAMCHIP_CMD_S_CTRL:
+               return ov6x20_set_control(c, arg);
+       case OVCAMCHIP_CMD_G_CTRL:
+               return ov6x20_get_control(c, arg);
+       case OVCAMCHIP_CMD_S_MODE:
+               return ov6x20_set_window(c, arg);
+       default:
+               DDEBUG(2, &c->dev, "command not supported: %d", cmd);
+               return -ENOIOCTLCMD;
+       }
+}
+
+struct ovcamchip_ops ov6x20_ops = {
+       .init    =      ov6x20_init,
+       .free    =      ov6x20_free,
+       .command =      ov6x20_command,
+};
diff --git a/drivers/media/video/ovcamchip/ov6x30.c b/drivers/media/video/ovcamchip/ov6x30.c
new file mode 100644 (file)
index 0000000..44a8423
--- /dev/null
@@ -0,0 +1,374 @@
+/* OmniVision OV6630/OV6130 Camera Chip Support Code
+ *
+ * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org>
+ * http://alpha.dyndns.org/ov511/
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
+ */
+
+#define DEBUG
+
+#include <linux/slab.h>
+#include "ovcamchip_priv.h"
+
+/* Registers */
+#define REG_GAIN               0x00    /* gain [5:0] */
+#define REG_BLUE               0x01    /* blue gain */
+#define REG_RED                        0x02    /* red gain */
+#define REG_SAT                        0x03    /* saturation [7:3] */
+#define REG_CNT                        0x05    /* Y contrast [3:0] */
+#define REG_BRT                        0x06    /* Y brightness */
+#define REG_SHARP              0x07    /* sharpness */
+#define REG_WB_BLUE            0x0C    /* WB blue ratio [5:0] */
+#define REG_WB_RED             0x0D    /* WB red ratio [5:0] */
+#define REG_EXP                        0x10    /* exposure */
+
+/* Window parameters */
+#define HWSBASE 0x38
+#define HWEBASE 0x3A
+#define VWSBASE 0x05
+#define VWEBASE 0x06
+
+struct ov6x30 {
+       int auto_brt;
+       int auto_exp;
+       int backlight;
+       int bandfilt;
+       int mirror;
+};
+
+static struct ovcamchip_regvals regvals_init_6x30[] = {
+       { 0x12, 0x80 }, /* reset */
+       { 0x00, 0x1f }, /* Gain */
+       { 0x01, 0x99 }, /* Blue gain */
+       { 0x02, 0x7c }, /* Red gain */
+       { 0x03, 0xc0 }, /* Saturation */
+       { 0x05, 0x0a }, /* Contrast */
+       { 0x06, 0x95 }, /* Brightness */
+       { 0x07, 0x2d }, /* Sharpness */
+       { 0x0c, 0x20 },
+       { 0x0d, 0x20 },
+       { 0x0e, 0x20 },
+       { 0x0f, 0x05 },
+       { 0x10, 0x9a }, /* "exposure check" */
+       { 0x11, 0x00 }, /* Pixel clock = fastest */
+       { 0x12, 0x24 }, /* Enable AGC and AWB */
+       { 0x13, 0x21 },
+       { 0x14, 0x80 },
+       { 0x15, 0x01 },
+       { 0x16, 0x03 },
+       { 0x17, 0x38 },
+       { 0x18, 0xea },
+       { 0x19, 0x04 },
+       { 0x1a, 0x93 },
+       { 0x1b, 0x00 },
+       { 0x1e, 0xc4 },
+       { 0x1f, 0x04 },
+       { 0x20, 0x20 },
+       { 0x21, 0x10 },
+       { 0x22, 0x88 },
+       { 0x23, 0xc0 }, /* Crystal circuit power level */
+       { 0x25, 0x9a }, /* Increase AEC black pixel ratio */
+       { 0x26, 0xb2 }, /* BLC enable */
+       { 0x27, 0xa2 },
+       { 0x28, 0x00 },
+       { 0x29, 0x00 },
+       { 0x2a, 0x84 }, /* (keep) */
+       { 0x2b, 0xa8 }, /* (keep) */
+       { 0x2c, 0xa0 },
+       { 0x2d, 0x95 }, /* Enable auto-brightness */
+       { 0x2e, 0x88 },
+       { 0x33, 0x26 },
+       { 0x34, 0x03 },
+       { 0x36, 0x8f },
+       { 0x37, 0x80 },
+       { 0x38, 0x83 },
+       { 0x39, 0x80 },
+       { 0x3a, 0x0f },
+       { 0x3b, 0x3c },
+       { 0x3c, 0x1a },
+       { 0x3d, 0x80 },
+       { 0x3e, 0x80 },
+       { 0x3f, 0x0e },
+       { 0x40, 0x00 }, /* White bal */
+       { 0x41, 0x00 }, /* White bal */
+       { 0x42, 0x80 },
+       { 0x43, 0x3f }, /* White bal */
+       { 0x44, 0x80 },
+       { 0x45, 0x20 },
+       { 0x46, 0x20 },
+       { 0x47, 0x80 },
+       { 0x48, 0x7f },
+       { 0x49, 0x00 },
+       { 0x4a, 0x00 },
+       { 0x4b, 0x80 },
+       { 0x4c, 0xd0 },
+       { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
+       { 0x4e, 0x40 },
+       { 0x4f, 0x07 }, /* UV average mode, color killer: strongest */
+       { 0x50, 0xff },
+       { 0x54, 0x23 }, /* Max AGC gain: 18dB */
+       { 0x55, 0xff },
+       { 0x56, 0x12 },
+       { 0x57, 0x81 }, /* (default) */
+       { 0x58, 0x75 },
+       { 0x59, 0x01 }, /* AGC dark current compensation: +1 */
+       { 0x5a, 0x2c },
+       { 0x5b, 0x0f }, /* AWB chrominance levels */
+       { 0x5c, 0x10 },
+       { 0x3d, 0x80 },
+       { 0x27, 0xa6 },
+       /* Toggle AWB off and on */
+       { 0x12, 0x20 },
+       { 0x12, 0x24 },
+
+       { 0xff, 0xff }, /* END MARKER */
+};
+
+/* This initializes the OV6x30 camera chip and relevant variables. */
+static int ov6x30_init(struct i2c_client *c)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+       struct ov6x30 *s;
+       int rc;
+
+       DDEBUG(4, &c->dev, "entered");
+
+       rc = ov_write_regvals(c, regvals_init_6x30);
+       if (rc < 0)
+               return rc;
+
+       ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+       if (!s)
+               return -ENOMEM;
+       memset(s, 0, sizeof *s);
+
+       s->auto_brt = 1;
+       s->auto_exp = 1;
+
+       return rc;
+}
+
+static int ov6x30_free(struct i2c_client *c)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+
+       kfree(ov->spriv);
+       return 0;
+}
+
+static int ov6x30_set_control(struct i2c_client *c,
+                             struct ovcamchip_control *ctl)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+       struct ov6x30 *s = ov->spriv;
+       int rc;
+       int v = ctl->value;
+
+       switch (ctl->id) {
+       case OVCAMCHIP_CID_CONT:
+               rc = ov_write_mask(c, REG_CNT, v >> 12, 0x0f);
+               break;
+       case OVCAMCHIP_CID_BRIGHT:
+               rc = ov_write(c, REG_BRT, v >> 8);
+               break;
+       case OVCAMCHIP_CID_SAT:
+               rc = ov_write(c, REG_SAT, v >> 8);
+               break;
+       case OVCAMCHIP_CID_HUE:
+               rc = ov_write(c, REG_RED, 0xFF - (v >> 8));
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write(c, REG_BLUE, v >> 8);
+               break;
+       case OVCAMCHIP_CID_EXP:
+               rc = ov_write(c, REG_EXP, v);
+               break;
+       case OVCAMCHIP_CID_FREQ:
+       {
+               int sixty = (v == 60);
+
+               rc = ov_write(c, 0x2b, sixty?0xa8:0x28);
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write(c, 0x2a, sixty?0x84:0xa4);
+               break;
+       }
+       case OVCAMCHIP_CID_BANDFILT:
+               rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04);
+               s->bandfilt = v;
+               break;
+       case OVCAMCHIP_CID_AUTOBRIGHT:
+               rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10);
+               s->auto_brt = v;
+               break;
+       case OVCAMCHIP_CID_AUTOEXP:
+               rc = ov_write_mask(c, 0x28, v?0x00:0x10, 0x10);
+               s->auto_exp = v;
+               break;
+       case OVCAMCHIP_CID_BACKLIGHT:
+       {
+               rc = ov_write_mask(c, 0x4e, v?0x80:0x60, 0xe0);
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write_mask(c, 0x29, v?0x08:0x00, 0x08);
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write_mask(c, 0x28, v?0x02:0x00, 0x02);
+               s->backlight = v;
+               break;
+       }
+       case OVCAMCHIP_CID_MIRROR:
+               rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40);
+               s->mirror = v;
+               break;
+       default:
+               DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+               return -EPERM;
+       }
+
+out:
+       DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc);
+       return rc;
+}
+
+static int ov6x30_get_control(struct i2c_client *c,
+                             struct ovcamchip_control *ctl)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+       struct ov6x30 *s = ov->spriv;
+       int rc = 0;
+       unsigned char val = 0;
+
+       switch (ctl->id) {
+       case OVCAMCHIP_CID_CONT:
+               rc = ov_read(c, REG_CNT, &val);
+               ctl->value = (val & 0x0f) << 12;
+               break;
+       case OVCAMCHIP_CID_BRIGHT:
+               rc = ov_read(c, REG_BRT, &val);
+               ctl->value = val << 8;
+               break;
+       case OVCAMCHIP_CID_SAT:
+               rc = ov_read(c, REG_SAT, &val);
+               ctl->value = val << 8;
+               break;
+       case OVCAMCHIP_CID_HUE:
+               rc = ov_read(c, REG_BLUE, &val);
+               ctl->value = val << 8;
+               break;
+       case OVCAMCHIP_CID_EXP:
+               rc = ov_read(c, REG_EXP, &val);
+               ctl->value = val;
+               break;
+       case OVCAMCHIP_CID_BANDFILT:
+               ctl->value = s->bandfilt;
+               break;
+       case OVCAMCHIP_CID_AUTOBRIGHT:
+               ctl->value = s->auto_brt;
+               break;
+       case OVCAMCHIP_CID_AUTOEXP:
+               ctl->value = s->auto_exp;
+               break;
+       case OVCAMCHIP_CID_BACKLIGHT:
+               ctl->value = s->backlight;
+               break;
+       case OVCAMCHIP_CID_MIRROR:
+               ctl->value = s->mirror;
+               break;
+       default:
+               DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+               return -EPERM;
+       }
+
+       DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc);
+       return rc;
+}
+
+static int ov6x30_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
+{
+       /******** QCIF-specific regs ********/
+
+       ov_write_mask(c, 0x14, win->quarter?0x20:0x00, 0x20);
+
+       /******** Palette-specific regs ********/
+
+       if (win->format == VIDEO_PALETTE_GREY) {
+               if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) {
+                       /* Do nothing - we're already in 8-bit mode */
+               } else {
+                       ov_write_mask(c, 0x13, 0x20, 0x20);
+               }
+       } else {
+               /* The OV518 needs special treatment. Although both the OV518
+                * and the OV6630 support a 16-bit video bus, only the 8 bit Y
+                * bus is actually used. The UV bus is tied to ground.
+                * Therefore, the OV6630 needs to be in 8-bit multiplexed
+                * output mode */
+
+               if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) {
+                       /* Do nothing - we want to stay in 8-bit mode */
+                       /* Warning: Messing with reg 0x13 breaks OV518 color */
+               } else {
+                       ov_write_mask(c, 0x13, 0x00, 0x20);
+               }
+       }
+
+       /******** Clock programming ********/
+
+       ov_write(c, 0x11, win->clockdiv);
+
+       return 0;
+}
+
+static int ov6x30_set_window(struct i2c_client *c, struct ovcamchip_window *win)
+{
+       int ret, hwscale, vwscale;
+
+       ret = ov6x30_mode_init(c, win);
+       if (ret < 0)
+               return ret;
+
+       if (win->quarter) {
+               hwscale = 0;
+               vwscale = 0;
+       } else {
+               hwscale = 1;
+               vwscale = 1;    /* The datasheet says 0; it's wrong */
+       }
+
+       ov_write(c, 0x17, HWSBASE + (win->x >> hwscale));
+       ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale));
+       ov_write(c, 0x19, VWSBASE + (win->y >> vwscale));
+       ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale));
+
+       return 0;
+}
+
+static int ov6x30_command(struct i2c_client *c, unsigned int cmd, void *arg)
+{
+       switch (cmd) {
+       case OVCAMCHIP_CMD_S_CTRL:
+               return ov6x30_set_control(c, arg);
+       case OVCAMCHIP_CMD_G_CTRL:
+               return ov6x30_get_control(c, arg);
+       case OVCAMCHIP_CMD_S_MODE:
+               return ov6x30_set_window(c, arg);
+       default:
+               DDEBUG(2, &c->dev, "command not supported: %d", cmd);
+               return -ENOIOCTLCMD;
+       }
+}
+
+struct ovcamchip_ops ov6x30_ops = {
+       .init    =      ov6x30_init,
+       .free    =      ov6x30_free,
+       .command =      ov6x30_command,
+};
diff --git a/drivers/media/video/ovcamchip/ov76be.c b/drivers/media/video/ovcamchip/ov76be.c
new file mode 100644 (file)
index 0000000..29bbdc0
--- /dev/null
@@ -0,0 +1,303 @@
+/* OmniVision OV76BE Camera Chip Support Code
+ *
+ * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org>
+ * http://alpha.dyndns.org/ov511/
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
+ */
+
+#define DEBUG
+
+#include <linux/slab.h>
+#include "ovcamchip_priv.h"
+
+/* OV7610 registers: Since the OV76BE is undocumented, we'll settle for these
+ * for now. */
+#define REG_GAIN               0x00    /* gain [5:0] */
+#define REG_BLUE               0x01    /* blue channel balance */
+#define REG_RED                        0x02    /* red channel balance */
+#define REG_SAT                        0x03    /* saturation */
+#define REG_CNT                        0x05    /* Y contrast */
+#define REG_BRT                        0x06    /* Y brightness */
+#define REG_BLUE_BIAS          0x0C    /* blue channel bias [5:0] */
+#define REG_RED_BIAS           0x0D    /* red channel bias [5:0] */
+#define REG_GAMMA_COEFF                0x0E    /* gamma settings */
+#define REG_WB_RANGE           0x0F    /* AEC/ALC/S-AWB settings */
+#define REG_EXP                        0x10    /* manual exposure setting */
+#define REG_CLOCK              0x11    /* polarity/clock prescaler */
+#define REG_FIELD_DIVIDE       0x16    /* field interval/mode settings */
+#define REG_HWIN_START         0x17    /* horizontal window start */
+#define REG_HWIN_END           0x18    /* horizontal window end */
+#define REG_VWIN_START         0x19    /* vertical window start */
+#define REG_VWIN_END           0x1A    /* vertical window end */
+#define REG_PIXEL_SHIFT        0x1B    /* pixel shift */
+#define REG_YOFFSET            0x21    /* Y channel offset */
+#define REG_UOFFSET            0x22    /* U channel offset */
+#define REG_ECW                        0x24    /* exposure white level for AEC */
+#define REG_ECB                        0x25    /* exposure black level for AEC */
+#define REG_FRAMERATE_H                0x2A    /* frame rate MSB + misc */
+#define REG_FRAMERATE_L                0x2B    /* frame rate LSB */
+#define REG_ALC                        0x2C    /* Auto Level Control settings */
+#define REG_VOFFSET            0x2E    /* V channel offset adjustment */
+#define REG_ARRAY_BIAS         0x2F    /* array bias -- don't change */
+#define REG_YGAMMA             0x33    /* misc gamma settings [7:6] */
+#define REG_BIAS_ADJUST                0x34    /* misc bias settings */
+
+/* Window parameters */
+#define HWSBASE 0x38
+#define HWEBASE 0x3a
+#define VWSBASE 0x05
+#define VWEBASE 0x05
+
+struct ov76be {
+       int auto_brt;
+       int auto_exp;
+       int bandfilt;
+       int mirror;
+};
+
+/* NOTE: These are the same as the 7x10 settings, but should eventually be
+ * optimized for the OV76BE */
+static struct ovcamchip_regvals regvals_init_76be[] = {
+       { 0x10, 0xff },
+       { 0x16, 0x03 },
+       { 0x28, 0x24 },
+       { 0x2b, 0xac },
+       { 0x12, 0x00 },
+       { 0x38, 0x81 },
+       { 0x28, 0x24 }, /* 0c */
+       { 0x0f, 0x85 }, /* lg's setting */
+       { 0x15, 0x01 },
+       { 0x20, 0x1c },
+       { 0x23, 0x2a },
+       { 0x24, 0x10 },
+       { 0x25, 0x8a },
+       { 0x26, 0xa2 },
+       { 0x27, 0xc2 },
+       { 0x2a, 0x04 },
+       { 0x2c, 0xfe },
+       { 0x2d, 0x93 },
+       { 0x30, 0x71 },
+       { 0x31, 0x60 },
+       { 0x32, 0x26 },
+       { 0x33, 0x20 },
+       { 0x34, 0x48 },
+       { 0x12, 0x24 },
+       { 0x11, 0x01 },
+       { 0x0c, 0x24 },
+       { 0x0d, 0x24 },
+       { 0xff, 0xff }, /* END MARKER */
+};
+
+/* This initializes the OV76be camera chip and relevant variables. */
+static int ov76be_init(struct i2c_client *c)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+       struct ov76be *s;
+       int rc;
+
+       DDEBUG(4, &c->dev, "entered");
+
+       rc = ov_write_regvals(c, regvals_init_76be);
+       if (rc < 0)
+               return rc;
+
+       ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+       if (!s)
+               return -ENOMEM;
+       memset(s, 0, sizeof *s);
+
+       s->auto_brt = 1;
+       s->auto_exp = 1;
+
+       return rc;
+}
+
+static int ov76be_free(struct i2c_client *c)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+
+       kfree(ov->spriv);
+       return 0;
+}
+
+static int ov76be_set_control(struct i2c_client *c,
+                             struct ovcamchip_control *ctl)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+       struct ov76be *s = ov->spriv;
+       int rc;
+       int v = ctl->value;
+
+       switch (ctl->id) {
+       case OVCAMCHIP_CID_BRIGHT:
+               rc = ov_write(c, REG_BRT, v >> 8);
+               break;
+       case OVCAMCHIP_CID_SAT:
+               rc = ov_write(c, REG_SAT, v >> 8);
+               break;
+       case OVCAMCHIP_CID_EXP:
+               rc = ov_write(c, REG_EXP, v);
+               break;
+       case OVCAMCHIP_CID_FREQ:
+       {
+               int sixty = (v == 60);
+
+               rc = ov_write_mask(c, 0x2a, sixty?0x00:0x80, 0x80);
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write(c, 0x2b, sixty?0x00:0xac);
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write_mask(c, 0x76, 0x01, 0x01);
+               break;
+       }
+       case OVCAMCHIP_CID_BANDFILT:
+               rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04);
+               s->bandfilt = v;
+               break;
+       case OVCAMCHIP_CID_AUTOBRIGHT:
+               rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10);
+               s->auto_brt = v;
+               break;
+       case OVCAMCHIP_CID_AUTOEXP:
+               rc = ov_write_mask(c, 0x13, v?0x01:0x00, 0x01);
+               s->auto_exp = v;
+               break;
+       case OVCAMCHIP_CID_MIRROR:
+               rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40);
+               s->mirror = v;
+               break;
+       default:
+               DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+               return -EPERM;
+       }
+
+out:
+       DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc);
+       return rc;
+}
+
+static int ov76be_get_control(struct i2c_client *c,
+                             struct ovcamchip_control *ctl)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+       struct ov76be *s = ov->spriv;
+       int rc = 0;
+       unsigned char val = 0;
+
+       switch (ctl->id) {
+       case OVCAMCHIP_CID_BRIGHT:
+               rc = ov_read(c, REG_BRT, &val);
+               ctl->value = val << 8;
+               break;
+       case OVCAMCHIP_CID_SAT:
+               rc = ov_read(c, REG_SAT, &val);
+               ctl->value = val << 8;
+               break;
+       case OVCAMCHIP_CID_EXP:
+               rc = ov_read(c, REG_EXP, &val);
+               ctl->value = val;
+               break;
+       case OVCAMCHIP_CID_BANDFILT:
+               ctl->value = s->bandfilt;
+               break;
+       case OVCAMCHIP_CID_AUTOBRIGHT:
+               ctl->value = s->auto_brt;
+               break;
+       case OVCAMCHIP_CID_AUTOEXP:
+               ctl->value = s->auto_exp;
+               break;
+       case OVCAMCHIP_CID_MIRROR:
+               ctl->value = s->mirror;
+               break;
+       default:
+               DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+               return -EPERM;
+       }
+
+       DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc);
+       return rc;
+}
+
+static int ov76be_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
+{
+       int qvga = win->quarter;
+
+       /******** QVGA-specific regs ********/
+
+       ov_write(c, 0x14, qvga?0xa4:0x84);
+
+       /******** Palette-specific regs ********/
+
+       if (win->format == VIDEO_PALETTE_GREY) {
+               ov_write_mask(c, 0x0e, 0x40, 0x40);
+               ov_write_mask(c, 0x13, 0x20, 0x20);
+       } else {
+               ov_write_mask(c, 0x0e, 0x00, 0x40);
+               ov_write_mask(c, 0x13, 0x00, 0x20);
+       }
+
+       /******** Clock programming ********/
+
+       ov_write(c, 0x11, win->clockdiv);
+
+       /******** Resolution-specific ********/
+
+       if (win->width == 640 && win->height == 480)
+               ov_write(c, 0x35, 0x9e);
+       else
+               ov_write(c, 0x35, 0x1e);
+
+       return 0;
+}
+
+static int ov76be_set_window(struct i2c_client *c, struct ovcamchip_window *win)
+{
+       int ret, hwscale, vwscale;
+
+       ret = ov76be_mode_init(c, win);
+       if (ret < 0)
+               return ret;
+
+       if (win->quarter) {
+               hwscale = 1;
+               vwscale = 0;
+       } else {
+               hwscale = 2;
+               vwscale = 1;
+       }
+
+       ov_write(c, 0x17, HWSBASE + (win->x >> hwscale));
+       ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale));
+       ov_write(c, 0x19, VWSBASE + (win->y >> vwscale));
+       ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale));
+
+       return 0;
+}
+
+static int ov76be_command(struct i2c_client *c, unsigned int cmd, void *arg)
+{
+       switch (cmd) {
+       case OVCAMCHIP_CMD_S_CTRL:
+               return ov76be_set_control(c, arg);
+       case OVCAMCHIP_CMD_G_CTRL:
+               return ov76be_get_control(c, arg);
+       case OVCAMCHIP_CMD_S_MODE:
+               return ov76be_set_window(c, arg);
+       default:
+               DDEBUG(2, &c->dev, "command not supported: %d", cmd);
+               return -ENOIOCTLCMD;
+       }
+}
+
+struct ovcamchip_ops ov76be_ops = {
+       .init    =      ov76be_init,
+       .free    =      ov76be_free,
+       .command =      ov76be_command,
+};
diff --git a/drivers/media/video/ovcamchip/ov7x10.c b/drivers/media/video/ovcamchip/ov7x10.c
new file mode 100644 (file)
index 0000000..6c383d4
--- /dev/null
@@ -0,0 +1,335 @@
+/* OmniVision OV7610/OV7110 Camera Chip Support Code
+ *
+ * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org>
+ * http://alpha.dyndns.org/ov511/
+ *
+ * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
+ */
+
+#define DEBUG
+
+#include <linux/slab.h>
+#include "ovcamchip_priv.h"
+
+/* Registers */
+#define REG_GAIN               0x00    /* gain [5:0] */
+#define REG_BLUE               0x01    /* blue channel balance */
+#define REG_RED                        0x02    /* red channel balance */
+#define REG_SAT                        0x03    /* saturation */
+#define REG_CNT                        0x05    /* Y contrast */
+#define REG_BRT                        0x06    /* Y brightness */
+#define REG_BLUE_BIAS          0x0C    /* blue channel bias [5:0] */
+#define REG_RED_BIAS           0x0D    /* red channel bias [5:0] */
+#define REG_GAMMA_COEFF                0x0E    /* gamma settings */
+#define REG_WB_RANGE           0x0F    /* AEC/ALC/S-AWB settings */
+#define REG_EXP                        0x10    /* manual exposure setting */
+#define REG_CLOCK              0x11    /* polarity/clock prescaler */
+#define REG_FIELD_DIVIDE       0x16    /* field interval/mode settings */
+#define REG_HWIN_START         0x17    /* horizontal window start */
+#define REG_HWIN_END           0x18    /* horizontal window end */
+#define REG_VWIN_START         0x19    /* vertical window start */
+#define REG_VWIN_END           0x1A    /* vertical window end */
+#define REG_PIXEL_SHIFT        0x1B    /* pixel shift */
+#define REG_YOFFSET            0x21    /* Y channel offset */
+#define REG_UOFFSET            0x22    /* U channel offset */
+#define REG_ECW                        0x24    /* exposure white level for AEC */
+#define REG_ECB                        0x25    /* exposure black level for AEC */
+#define REG_FRAMERATE_H                0x2A    /* frame rate MSB + misc */
+#define REG_FRAMERATE_L                0x2B    /* frame rate LSB */
+#define REG_ALC                        0x2C    /* Auto Level Control settings */
+#define REG_VOFFSET            0x2E    /* V channel offset adjustment */
+#define REG_ARRAY_BIAS         0x2F    /* array bias -- don't change */
+#define REG_YGAMMA             0x33    /* misc gamma settings [7:6] */
+#define REG_BIAS_ADJUST                0x34    /* misc bias settings */
+
+/* Window parameters */
+#define HWSBASE 0x38
+#define HWEBASE 0x3a
+#define VWSBASE 0x05
+#define VWEBASE 0x05
+
+struct ov7x10 {
+       int auto_brt;
+       int auto_exp;
+       int bandfilt;
+       int mirror;
+};
+
+/* Lawrence Glaister <lg@jfm.bc.ca> reports:
+ *
+ * Register 0x0f in the 7610 has the following effects:
+ *
+ * 0x85 (AEC method 1): Best overall, good contrast range
+ * 0x45 (AEC method 2): Very overexposed
+ * 0xa5 (spec sheet default): Ok, but the black level is
+ *     shifted resulting in loss of contrast
+ * 0x05 (old driver setting): very overexposed, too much
+ *     contrast
+ */
+static struct ovcamchip_regvals regvals_init_7x10[] = {
+       { 0x10, 0xff },
+       { 0x16, 0x03 },
+       { 0x28, 0x24 },
+       { 0x2b, 0xac },
+       { 0x12, 0x00 },
+       { 0x38, 0x81 },
+       { 0x28, 0x24 }, /* 0c */
+       { 0x0f, 0x85 }, /* lg's setting */
+       { 0x15, 0x01 },
+       { 0x20, 0x1c },
+       { 0x23, 0x2a },
+       { 0x24, 0x10 },
+       { 0x25, 0x8a },
+       { 0x26, 0xa2 },
+       { 0x27, 0xc2 },
+       { 0x2a, 0x04 },
+       { 0x2c, 0xfe },
+       { 0x2d, 0x93 },
+       { 0x30, 0x71 },
+       { 0x31, 0x60 },
+       { 0x32, 0x26 },
+       { 0x33, 0x20 },
+       { 0x34, 0x48 },
+       { 0x12, 0x24 },
+       { 0x11, 0x01 },
+       { 0x0c, 0x24 },
+       { 0x0d, 0x24 },
+       { 0xff, 0xff }, /* END MARKER */
+};
+
+/* This initializes the OV7x10 camera chip and relevant variables. */
+static int ov7x10_init(struct i2c_client *c)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+       struct ov7x10 *s;
+       int rc;
+
+       DDEBUG(4, &c->dev, "entered");
+
+       rc = ov_write_regvals(c, regvals_init_7x10);
+       if (rc < 0)
+               return rc;
+
+       ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+       if (!s)
+               return -ENOMEM;
+       memset(s, 0, sizeof *s);
+
+       s->auto_brt = 1;
+       s->auto_exp = 1;
+
+       return rc;
+}
+
+static int ov7x10_free(struct i2c_client *c)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+
+       kfree(ov->spriv);
+       return 0;
+}
+
+static int ov7x10_set_control(struct i2c_client *c,
+                             struct ovcamchip_control *ctl)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+       struct ov7x10 *s = ov->spriv;
+       int rc;
+       int v = ctl->value;
+
+       switch (ctl->id) {
+       case OVCAMCHIP_CID_CONT:
+               rc = ov_write(c, REG_CNT, v >> 8);
+               break;
+       case OVCAMCHIP_CID_BRIGHT:
+               rc = ov_write(c, REG_BRT, v >> 8);
+               break;
+       case OVCAMCHIP_CID_SAT:
+               rc = ov_write(c, REG_SAT, v >> 8);
+               break;
+       case OVCAMCHIP_CID_HUE:
+               rc = ov_write(c, REG_RED, 0xFF - (v >> 8));
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write(c, REG_BLUE, v >> 8);
+               break;
+       case OVCAMCHIP_CID_EXP:
+               rc = ov_write(c, REG_EXP, v);
+               break;
+       case OVCAMCHIP_CID_FREQ:
+       {
+               int sixty = (v == 60);
+
+               rc = ov_write_mask(c, 0x2a, sixty?0x00:0x80, 0x80);
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write(c, 0x2b, sixty?0x00:0xac);
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write_mask(c, 0x13, 0x10, 0x10);
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write_mask(c, 0x13, 0x00, 0x10);
+               break;
+       }
+       case OVCAMCHIP_CID_BANDFILT:
+               rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04);
+               s->bandfilt = v;
+               break;
+       case OVCAMCHIP_CID_AUTOBRIGHT:
+               rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10);
+               s->auto_brt = v;
+               break;
+       case OVCAMCHIP_CID_AUTOEXP:
+               rc = ov_write_mask(c, 0x29, v?0x00:0x80, 0x80);
+               s->auto_exp = v;
+               break;
+       case OVCAMCHIP_CID_MIRROR:
+               rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40);
+               s->mirror = v;
+               break;
+       default:
+               DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+               return -EPERM;
+       }
+
+out:
+       DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc);
+       return rc;
+}
+
+static int ov7x10_get_control(struct i2c_client *c,
+                             struct ovcamchip_control *ctl)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+       struct ov7x10 *s = ov->spriv;
+       int rc = 0;
+       unsigned char val = 0;
+
+       switch (ctl->id) {
+       case OVCAMCHIP_CID_CONT:
+               rc = ov_read(c, REG_CNT, &val);
+               ctl->value = val << 8;
+               break;
+       case OVCAMCHIP_CID_BRIGHT:
+               rc = ov_read(c, REG_BRT, &val);
+               ctl->value = val << 8;
+               break;
+       case OVCAMCHIP_CID_SAT:
+               rc = ov_read(c, REG_SAT, &val);
+               ctl->value = val << 8;
+               break;
+       case OVCAMCHIP_CID_HUE:
+               rc = ov_read(c, REG_BLUE, &val);
+               ctl->value = val << 8;
+               break;
+       case OVCAMCHIP_CID_EXP:
+               rc = ov_read(c, REG_EXP, &val);
+               ctl->value = val;
+               break;
+       case OVCAMCHIP_CID_BANDFILT:
+               ctl->value = s->bandfilt;
+               break;
+       case OVCAMCHIP_CID_AUTOBRIGHT:
+               ctl->value = s->auto_brt;
+               break;
+       case OVCAMCHIP_CID_AUTOEXP:
+               ctl->value = s->auto_exp;
+               break;
+       case OVCAMCHIP_CID_MIRROR:
+               ctl->value = s->mirror;
+               break;
+       default:
+               DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+               return -EPERM;
+       }
+
+       DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc);
+       return rc;
+}
+
+static int ov7x10_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
+{
+       int qvga = win->quarter;
+
+       /******** QVGA-specific regs ********/
+
+       ov_write(c, 0x14, qvga?0x24:0x04);
+
+       /******** Palette-specific regs ********/
+
+       if (win->format == VIDEO_PALETTE_GREY) {
+               ov_write_mask(c, 0x0e, 0x40, 0x40);
+               ov_write_mask(c, 0x13, 0x20, 0x20);
+       } else {
+               ov_write_mask(c, 0x0e, 0x00, 0x40);
+               ov_write_mask(c, 0x13, 0x00, 0x20);
+       }
+
+       /******** Clock programming ********/
+
+       ov_write(c, 0x11, win->clockdiv);
+
+       /******** Resolution-specific ********/
+
+       if (win->width == 640 && win->height == 480)
+               ov_write(c, 0x35, 0x9e);
+       else
+               ov_write(c, 0x35, 0x1e);
+
+       return 0;
+}
+
+static int ov7x10_set_window(struct i2c_client *c, struct ovcamchip_window *win)
+{
+       int ret, hwscale, vwscale;
+
+       ret = ov7x10_mode_init(c, win);
+       if (ret < 0)
+               return ret;
+
+       if (win->quarter) {
+               hwscale = 1;
+               vwscale = 0;
+       } else {
+               hwscale = 2;
+               vwscale = 1;
+       }
+
+       ov_write(c, 0x17, HWSBASE + (win->x >> hwscale));
+       ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale));
+       ov_write(c, 0x19, VWSBASE + (win->y >> vwscale));
+       ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale));
+
+       return 0;
+}
+
+static int ov7x10_command(struct i2c_client *c, unsigned int cmd, void *arg)
+{
+       switch (cmd) {
+       case OVCAMCHIP_CMD_S_CTRL:
+               return ov7x10_set_control(c, arg);
+       case OVCAMCHIP_CMD_G_CTRL:
+               return ov7x10_get_control(c, arg);
+       case OVCAMCHIP_CMD_S_MODE:
+               return ov7x10_set_window(c, arg);
+       default:
+               DDEBUG(2, &c->dev, "command not supported: %d", cmd);
+               return -ENOIOCTLCMD;
+       }
+}
+
+struct ovcamchip_ops ov7x10_ops = {
+       .init    =      ov7x10_init,
+       .free    =      ov7x10_free,
+       .command =      ov7x10_command,
+};
diff --git a/drivers/media/video/ovcamchip/ov7x20.c b/drivers/media/video/ovcamchip/ov7x20.c
new file mode 100644 (file)
index 0000000..3c8c48f
--- /dev/null
@@ -0,0 +1,455 @@
+/* OmniVision OV7620/OV7120 Camera Chip Support Code
+ *
+ * Copyright (c) 1999-2004 Mark McClelland <mark@alpha.dyndns.org>
+ * http://alpha.dyndns.org/ov511/
+ *
+ * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. NO WARRANTY OF ANY KIND is expressed or implied.
+ */
+
+#define DEBUG
+
+#include <linux/slab.h>
+#include "ovcamchip_priv.h"
+
+/* Registers */
+#define REG_GAIN               0x00    /* gain [5:0] */
+#define REG_BLUE               0x01    /* blue gain */
+#define REG_RED                        0x02    /* red gain */
+#define REG_SAT                        0x03    /* saturation */
+#define REG_BRT                        0x06    /* Y brightness */
+#define REG_SHARP              0x07    /* analog sharpness */
+#define REG_BLUE_BIAS          0x0C    /* WB blue ratio [5:0] */
+#define REG_RED_BIAS           0x0D    /* WB red ratio [5:0] */
+#define REG_EXP                        0x10    /* exposure */
+
+/* Default control settings. Values are in terms of V4L2 controls. */
+#define OV7120_DFL_BRIGHT     0x60
+#define OV7620_DFL_BRIGHT     0x60
+#define OV7120_DFL_SAT        0xb0
+#define OV7620_DFL_SAT        0xc0
+#define DFL_AUTO_EXP             1
+#define DFL_AUTO_GAIN            1
+#define OV7120_DFL_GAIN       0x00
+#define OV7620_DFL_GAIN       0x00
+/* NOTE: Since autoexposure is the default, these aren't programmed into the
+ * OV7x20 chip. They are just here because V4L2 expects a default */
+#define OV7120_DFL_EXP        0x7f
+#define OV7620_DFL_EXP        0x7f
+
+/* Window parameters */
+#define HWSBASE 0x2F   /* From 7620.SET (spec is wrong) */
+#define HWEBASE 0x2F
+#define VWSBASE 0x05
+#define VWEBASE 0x05
+
+struct ov7x20 {
+       int auto_brt;
+       int auto_exp;
+       int auto_gain;
+       int backlight;
+       int bandfilt;
+       int mirror;
+};
+
+/* Contrast look-up table */
+static unsigned char ctab[] = {
+       0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
+       0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
+};
+
+/* Settings for (Black & White) OV7120 camera chip */
+static struct ovcamchip_regvals regvals_init_7120[] = {
+       { 0x12, 0x80 }, /* reset */
+       { 0x13, 0x00 }, /* Autoadjust off */
+       { 0x12, 0x20 }, /* Disable AWB */
+       { 0x13, DFL_AUTO_GAIN?0x01:0x00 }, /* Autoadjust on (if desired) */
+       { 0x00, OV7120_DFL_GAIN },
+       { 0x01, 0x80 },
+       { 0x02, 0x80 },
+       { 0x03, OV7120_DFL_SAT },
+       { 0x06, OV7120_DFL_BRIGHT },
+       { 0x07, 0x00 },
+       { 0x0c, 0x20 },
+       { 0x0d, 0x20 },
+       { 0x11, 0x01 },
+       { 0x14, 0x84 },
+       { 0x15, 0x01 },
+       { 0x16, 0x03 },
+       { 0x17, 0x2f },
+       { 0x18, 0xcf },
+       { 0x19, 0x06 },
+       { 0x1a, 0xf5 },
+       { 0x1b, 0x00 },
+       { 0x20, 0x08 },
+       { 0x21, 0x80 },
+       { 0x22, 0x80 },
+       { 0x23, 0x00 },
+       { 0x26, 0xa0 },
+       { 0x27, 0xfa },
+       { 0x28, 0x20 }, /* DON'T set bit 6. It is for the OV7620 only */
+       { 0x29, DFL_AUTO_EXP?0x00:0x80 },
+       { 0x2a, 0x10 },
+       { 0x2b, 0x00 },
+       { 0x2c, 0x88 },
+       { 0x2d, 0x95 },
+       { 0x2e, 0x80 },
+       { 0x2f, 0x44 },
+       { 0x60, 0x20 },
+       { 0x61, 0x02 },
+       { 0x62, 0x5f },
+       { 0x63, 0xd5 },
+       { 0x64, 0x57 },
+       { 0x65, 0x83 }, /* OV says "don't change this value" */
+       { 0x66, 0x55 },
+       { 0x67, 0x92 },
+       { 0x68, 0xcf },
+       { 0x69, 0x76 },
+       { 0x6a, 0x22 },
+       { 0x6b, 0xe2 },
+       { 0x6c, 0x40 },
+       { 0x6d, 0x48 },
+       { 0x6e, 0x80 },
+       { 0x6f, 0x0d },
+       { 0x70, 0x89 },
+       { 0x71, 0x00 },
+       { 0x72, 0x14 },
+       { 0x73, 0x54 },
+       { 0x74, 0xa0 },
+       { 0x75, 0x8e },
+       { 0x76, 0x00 },
+       { 0x77, 0xff },
+       { 0x78, 0x80 },
+       { 0x79, 0x80 },
+       { 0x7a, 0x80 },
+       { 0x7b, 0xe6 },
+       { 0x7c, 0x00 },
+       { 0x24, 0x3a },
+       { 0x25, 0x60 },
+       { 0xff, 0xff }, /* END MARKER */
+};
+
+/* Settings for (color) OV7620 camera chip */
+static struct ovcamchip_regvals regvals_init_7620[] = {
+       { 0x12, 0x80 }, /* reset */
+       { 0x00, OV7620_DFL_GAIN },
+       { 0x01, 0x80 },
+       { 0x02, 0x80 },
+       { 0x03, OV7620_DFL_SAT },
+       { 0x06, OV7620_DFL_BRIGHT },
+       { 0x07, 0x00 },
+       { 0x0c, 0x24 },
+       { 0x0c, 0x24 },
+       { 0x0d, 0x24 },
+       { 0x11, 0x01 },
+       { 0x12, 0x24 },
+       { 0x13, DFL_AUTO_GAIN?0x01:0x00 },
+       { 0x14, 0x84 },
+       { 0x15, 0x01 },
+       { 0x16, 0x03 },
+       { 0x17, 0x2f },
+       { 0x18, 0xcf },
+       { 0x19, 0x06 },
+       { 0x1a, 0xf5 },
+       { 0x1b, 0x00 },
+       { 0x20, 0x18 },
+       { 0x21, 0x80 },
+       { 0x22, 0x80 },
+       { 0x23, 0x00 },
+       { 0x26, 0xa2 },
+       { 0x27, 0xea },
+       { 0x28, 0x20 },
+       { 0x29, DFL_AUTO_EXP?0x00:0x80 },
+       { 0x2a, 0x10 },
+       { 0x2b, 0x00 },
+       { 0x2c, 0x88 },
+       { 0x2d, 0x91 },
+       { 0x2e, 0x80 },
+       { 0x2f, 0x44 },
+       { 0x60, 0x27 },
+       { 0x61, 0x02 },
+       { 0x62, 0x5f },
+       { 0x63, 0xd5 },
+       { 0x64, 0x57 },
+       { 0x65, 0x83 },
+       { 0x66, 0x55 },
+       { 0x67, 0x92 },
+       { 0x68, 0xcf },
+       { 0x69, 0x76 },
+       { 0x6a, 0x22 },
+       { 0x6b, 0x00 },
+       { 0x6c, 0x02 },
+       { 0x6d, 0x44 },
+       { 0x6e, 0x80 },
+       { 0x6f, 0x1d },
+       { 0x70, 0x8b },
+       { 0x71, 0x00 },
+       { 0x72, 0x14 },
+       { 0x73, 0x54 },
+       { 0x74, 0x00 },
+       { 0x75, 0x8e },
+       { 0x76, 0x00 },
+       { 0x77, 0xff },
+       { 0x78, 0x80 },
+       { 0x79, 0x80 },
+       { 0x7a, 0x80 },
+       { 0x7b, 0xe2 },
+       { 0x7c, 0x00 },
+       { 0xff, 0xff }, /* END MARKER */
+};
+
+/* Returns index into the specified look-up table, with 'n' elements, for which
+ * the value is greater than or equal to "val". If a match isn't found, (n-1)
+ * is returned. The entries in the table must be in ascending order. */
+static inline int ov7x20_lut_find(unsigned char lut[], int n, unsigned char val)
+{
+       int i = 0;
+
+       while (lut[i] < val && i < n)
+               i++;
+
+       return i;
+}
+
+/* This initializes the OV7x20 camera chip and relevant variables. */
+static int ov7x20_init(struct i2c_client *c)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+       struct ov7x20 *s;
+       int rc;
+
+       DDEBUG(4, &c->dev, "entered");
+
+       if (ov->mono)
+               rc = ov_write_regvals(c, regvals_init_7120);
+       else
+               rc = ov_write_regvals(c, regvals_init_7620);
+
+       if (rc < 0)
+               return rc;
+
+       ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+       if (!s)
+               return -ENOMEM;
+       memset(s, 0, sizeof *s);
+
+       s->auto_brt = 1;
+       s->auto_exp = DFL_AUTO_EXP;
+       s->auto_gain = DFL_AUTO_GAIN;
+
+       return 0;
+}
+
+static int ov7x20_free(struct i2c_client *c)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+
+       kfree(ov->spriv);
+       return 0;
+}
+
+static int ov7x20_set_v4l1_control(struct i2c_client *c,
+                                  struct ovcamchip_control *ctl)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+       struct ov7x20 *s = ov->spriv;
+       int rc;
+       int v = ctl->value;
+
+       switch (ctl->id) {
+       case OVCAMCHIP_CID_CONT:
+       {
+               /* Use Y gamma control instead. Bit 0 enables it. */
+               rc = ov_write(c, 0x64, ctab[v >> 12]);
+               break;
+       }
+       case OVCAMCHIP_CID_BRIGHT:
+               /* 7620 doesn't like manual changes when in auto mode */
+               if (!s->auto_brt)
+                       rc = ov_write(c, REG_BRT, v >> 8);
+               else
+                       rc = 0;
+               break;
+       case OVCAMCHIP_CID_SAT:
+               rc = ov_write(c, REG_SAT, v >> 8);
+               break;
+       case OVCAMCHIP_CID_EXP:
+               if (!s->auto_exp)
+                       rc = ov_write(c, REG_EXP, v);
+               else
+                       rc = -EBUSY;
+               break;
+       case OVCAMCHIP_CID_FREQ:
+       {
+               int sixty = (v == 60);
+
+               rc = ov_write_mask(c, 0x2a, sixty?0x00:0x80, 0x80);
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write(c, 0x2b, sixty?0x00:0xac);
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write_mask(c, 0x76, 0x01, 0x01);
+               break;
+       }
+       case OVCAMCHIP_CID_BANDFILT:
+               rc = ov_write_mask(c, 0x2d, v?0x04:0x00, 0x04);
+               s->bandfilt = v;
+               break;
+       case OVCAMCHIP_CID_AUTOBRIGHT:
+               rc = ov_write_mask(c, 0x2d, v?0x10:0x00, 0x10);
+               s->auto_brt = v;
+               break;
+       case OVCAMCHIP_CID_AUTOEXP:
+               rc = ov_write_mask(c, 0x13, v?0x01:0x00, 0x01);
+               s->auto_exp = v;
+               break;
+       case OVCAMCHIP_CID_BACKLIGHT:
+       {
+               rc = ov_write_mask(c, 0x68, v?0xe0:0xc0, 0xe0);
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write_mask(c, 0x29, v?0x08:0x00, 0x08);
+               if (rc < 0)
+                       goto out;
+
+               rc = ov_write_mask(c, 0x28, v?0x02:0x00, 0x02);
+               s->backlight = v;
+               break;
+       }
+       case OVCAMCHIP_CID_MIRROR:
+               rc = ov_write_mask(c, 0x12, v?0x40:0x00, 0x40);
+               s->mirror = v;
+               break;
+       default:
+               DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+               return -EPERM;
+       }
+
+out:
+       DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, v, rc);
+       return rc;
+}
+
+static int ov7x20_get_v4l1_control(struct i2c_client *c,
+                                  struct ovcamchip_control *ctl)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+       struct ov7x20 *s = ov->spriv;
+       int rc = 0;
+       unsigned char val = 0;
+
+       switch (ctl->id) {
+       case OVCAMCHIP_CID_CONT:
+               rc = ov_read(c, 0x64, &val);
+               ctl->value = ov7x20_lut_find(ctab, 16, val) << 12;
+               break;
+       case OVCAMCHIP_CID_BRIGHT:
+               rc = ov_read(c, REG_BRT, &val);
+               ctl->value = val << 8;
+               break;
+       case OVCAMCHIP_CID_SAT:
+               rc = ov_read(c, REG_SAT, &val);
+               ctl->value = val << 8;
+               break;
+       case OVCAMCHIP_CID_EXP:
+               rc = ov_read(c, REG_EXP, &val);
+               ctl->value = val;
+               break;
+       case OVCAMCHIP_CID_BANDFILT:
+               ctl->value = s->bandfilt;
+               break;
+       case OVCAMCHIP_CID_AUTOBRIGHT:
+               ctl->value = s->auto_brt;
+               break;
+       case OVCAMCHIP_CID_AUTOEXP:
+               ctl->value = s->auto_exp;
+               break;
+       case OVCAMCHIP_CID_BACKLIGHT:
+               ctl->value = s->backlight;
+               break;
+       case OVCAMCHIP_CID_MIRROR:
+               ctl->value = s->mirror;
+               break;
+       default:
+               DDEBUG(2, &c->dev, "control not supported: %d", ctl->id);
+               return -EPERM;
+       }
+
+       DDEBUG(3, &c->dev, "id=%d, arg=%d, rc=%d", ctl->id, ctl->value, rc);
+       return rc;
+}
+
+static int ov7x20_mode_init(struct i2c_client *c, struct ovcamchip_window *win)
+{
+       struct ovcamchip *ov = i2c_get_clientdata(c);
+       int qvga = win->quarter;
+
+       /******** QVGA-specific regs ********/
+       ov_write_mask(c, 0x14, qvga?0x20:0x00, 0x20);
+       ov_write_mask(c, 0x28, qvga?0x00:0x20, 0x20);
+       ov_write(c, 0x24, qvga?0x20:0x3a);
+       ov_write(c, 0x25, qvga?0x30:0x60);
+       ov_write_mask(c, 0x2d, qvga?0x40:0x00, 0x40);
+       if (!ov->mono)
+               ov_write_mask(c, 0x67, qvga?0xf0:0x90, 0xf0);
+       ov_write_mask(c, 0x74, qvga?0x20:0x00, 0x20);
+
+       /******** Clock programming ********/
+
+       ov_write(c, 0x11, win->clockdiv);
+
+       return 0;
+}
+
+static int ov7x20_set_window(struct i2c_client *c, struct ovcamchip_window *win)
+{
+       int ret, hwscale, vwscale;
+
+       ret = ov7x20_mode_init(c, win);
+       if (ret < 0)
+               return ret;
+
+       if (win->quarter) {
+               hwscale = 1;
+               vwscale = 0;
+       } else {
+               hwscale = 2;
+               vwscale = 1;
+       }
+
+       ov_write(c, 0x17, HWSBASE + (win->x >> hwscale));
+       ov_write(c, 0x18, HWEBASE + ((win->x + win->width) >> hwscale));
+       ov_write(c, 0x19, VWSBASE + (win->y >> vwscale));
+       ov_write(c, 0x1a, VWEBASE + ((win->y + win->height) >> vwscale));
+
+       return 0;
+}
+
+static int ov7x20_command(struct i2c_client *c, unsigned int cmd, void *arg)
+{
+       switch (cmd) {
+       case OVCAMCHIP_CMD_S_CTRL:
+               return ov7x20_set_v4l1_control(c, arg);
+       case OVCAMCHIP_CMD_G_CTRL:
+               return ov7x20_get_v4l1_control(c, arg);
+       case OVCAMCHIP_CMD_S_MODE:
+               return ov7x20_set_window(c, arg);
+       default:
+               DDEBUG(2, &c->dev, "command not supported: %d", cmd);
+               return -ENOIOCTLCMD;
+       }
+}
+
+struct ovcamchip_ops ov7x20_ops = {
+       .init    =      ov7x20_init,
+       .free    =      ov7x20_free,
+       .command =      ov7x20_command,
+};
diff --git a/drivers/net/fec_8xx/Kconfig b/drivers/net/fec_8xx/Kconfig
new file mode 100644 (file)
index 0000000..db36ac3
--- /dev/null
@@ -0,0 +1,14 @@
+config FEC_8XX
+       tristate "Motorola 8xx FEC driver"
+       depends on NET_ETHERNET && 8xx && (NETTA || NETPHONE)
+       select MII
+
+config FEC_8XX_GENERIC_PHY
+       bool "Support any generic PHY"
+       depends on FEC_8XX
+       default y
+
+config FEC_8XX_DM9161_PHY
+       bool "Support DM9161 PHY"
+       depends on FEC_8XX
+       default n
diff --git a/drivers/net/fec_8xx/Makefile b/drivers/net/fec_8xx/Makefile
new file mode 100644 (file)
index 0000000..70c54f8
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# Makefile for the Motorola 8xx FEC ethernet controller
+#
+
+obj-$(CONFIG_FEC_8XX) += fec_8xx.o
+
+fec_8xx-objs := fec_main.o fec_mii.o
+
+# the platform instantatiation objects
+ifeq ($(CONFIG_NETTA),y)
+fec_8xx-objs   += fec_8xx-netta.o
+endif
diff --git a/drivers/net/fec_8xx/fec_8xx.h b/drivers/net/fec_8xx/fec_8xx.h
new file mode 100644 (file)
index 0000000..5af60b0
--- /dev/null
@@ -0,0 +1,218 @@
+#ifndef FEC_8XX_H
+#define FEC_8XX_H
+
+#include <linux/mii.h>
+#include <linux/netdevice.h>
+
+#include <linux/types.h>
+
+/* HW info */
+
+/* CRC polynomium used by the FEC for the multicast group filtering */
+#define FEC_CRC_POLY   0x04C11DB7
+
+#define MII_ADVERTISE_HALF     (ADVERTISE_100HALF | \
+                                ADVERTISE_10HALF | ADVERTISE_CSMA)
+#define MII_ADVERTISE_ALL      (ADVERTISE_100FULL | \
+                                ADVERTISE_10FULL | MII_ADVERTISE_HALF)
+
+/* Interrupt events/masks.
+*/
+#define FEC_ENET_HBERR 0x80000000U     /* Heartbeat error          */
+#define FEC_ENET_BABR  0x40000000U     /* Babbling receiver        */
+#define FEC_ENET_BABT  0x20000000U     /* Babbling transmitter     */
+#define FEC_ENET_GRA   0x10000000U     /* Graceful stop complete   */
+#define FEC_ENET_TXF   0x08000000U     /* Full frame transmitted   */
+#define FEC_ENET_TXB   0x04000000U     /* A buffer was transmitted */
+#define FEC_ENET_RXF   0x02000000U     /* Full frame received      */
+#define FEC_ENET_RXB   0x01000000U     /* A buffer was received    */
+#define FEC_ENET_MII   0x00800000U     /* MII interrupt            */
+#define FEC_ENET_EBERR 0x00400000U     /* SDMA bus error           */
+
+#define FEC_ECNTRL_PINMUX      0x00000004
+#define FEC_ECNTRL_ETHER_EN    0x00000002
+#define FEC_ECNTRL_RESET       0x00000001
+
+#define FEC_RCNTRL_BC_REJ      0x00000010
+#define FEC_RCNTRL_PROM                0x00000008
+#define FEC_RCNTRL_MII_MODE    0x00000004
+#define FEC_RCNTRL_DRT         0x00000002
+#define FEC_RCNTRL_LOOP                0x00000001
+
+#define FEC_TCNTRL_FDEN                0x00000004
+#define FEC_TCNTRL_HBC         0x00000002
+#define FEC_TCNTRL_GTS         0x00000001
+
+/* values for MII phy_status */
+
+#define PHY_CONF_ANE   0x0001  /* 1 auto-negotiation enabled     */
+#define PHY_CONF_LOOP  0x0002  /* 1 loopback mode enabled        */
+#define PHY_CONF_SPMASK        0x00f0  /* mask for speed                 */
+#define PHY_CONF_10HDX 0x0010  /* 10 Mbit half duplex supported  */
+#define PHY_CONF_10FDX 0x0020  /* 10 Mbit full duplex supported  */
+#define PHY_CONF_100HDX        0x0040  /* 100 Mbit half duplex supported */
+#define PHY_CONF_100FDX        0x0080  /* 100 Mbit full duplex supported */
+
+#define PHY_STAT_LINK  0x0100  /* 1 up - 0 down                  */
+#define PHY_STAT_FAULT 0x0200  /* 1 remote fault                 */
+#define PHY_STAT_ANC   0x0400  /* 1 auto-negotiation complete    */
+#define PHY_STAT_SPMASK        0xf000  /* mask for speed                 */
+#define PHY_STAT_10HDX 0x1000  /* 10 Mbit half duplex selected   */
+#define PHY_STAT_10FDX 0x2000  /* 10 Mbit full duplex selected   */
+#define PHY_STAT_100HDX        0x4000  /* 100 Mbit half duplex selected  */
+#define PHY_STAT_100FDX        0x8000  /* 100 Mbit full duplex selected  */
+
+typedef struct phy_info {
+       unsigned int id;
+       const char *name;
+       void (*startup) (struct net_device * dev);
+       void (*shutdown) (struct net_device * dev);
+       void (*ack_int) (struct net_device * dev);
+} phy_info_t;
+
+/* The FEC stores dest/src/type, data, and checksum for receive packets.
+ */
+#define MAX_MTU 1508           /* Allow fullsized pppoe packets over VLAN */
+#define MIN_MTU 46             /* this is data size */
+#define CRC_LEN 4
+
+#define PKT_MAXBUF_SIZE                (MAX_MTU+ETH_HLEN+CRC_LEN)
+#define PKT_MINBUF_SIZE                (MIN_MTU+ETH_HLEN+CRC_LEN)
+
+/* Must be a multiple of 4 */
+#define PKT_MAXBLR_SIZE                ((PKT_MAXBUF_SIZE+3) & ~3)
+/* This is needed so that invalidate_xxx wont invalidate too much */
+#define ENET_RX_FRSIZE         L1_CACHE_ALIGN(PKT_MAXBUF_SIZE)
+
+/* platform interface */
+
+struct fec_platform_info {
+       int fec_no;             /* FEC index                  */
+       int use_mdio;           /* use external MII           */
+       int phy_addr;           /* the phy address            */
+       int fec_irq, phy_irq;   /* the irq for the controller */
+       int rx_ring, tx_ring;   /* number of buffers on rx    */
+       int sys_clk;            /* system clock               */
+       __u8 macaddr[6];        /* mac address                */
+       int rx_copybreak;       /* limit we copy small frames */
+       int use_napi;           /* use NAPI                   */
+       int napi_weight;        /* NAPI weight                */
+};
+
+/* forward declaration */
+struct fec;
+
+struct fec_enet_private {
+       spinlock_t lock;        /* during all ops except TX pckt processing */
+       spinlock_t tx_lock;     /* during fec_start_xmit and fec_tx         */
+       int fecno;
+       struct fec *fecp;
+       const struct fec_platform_info *fpi;
+       int rx_ring, tx_ring;
+       dma_addr_t ring_mem_addr;
+       void *ring_base;
+       struct sk_buff **rx_skbuff;
+       struct sk_buff **tx_skbuff;
+       cbd_t *rx_bd_base;      /* Address of Rx and Tx buffers.    */
+       cbd_t *tx_bd_base;
+       cbd_t *dirty_tx;        /* ring entries to be free()ed.     */
+       cbd_t *cur_rx;
+       cbd_t *cur_tx;
+       int tx_free;
+       struct net_device_stats stats;
+       struct timer_list phy_timer_list;
+       const struct phy_info *phy;
+       unsigned int fec_phy_speed;
+       __u32 msg_enable;
+       struct mii_if_info mii_if;
+};
+
+/***************************************************************************/
+
+void fec_restart(struct net_device *dev, int duplex, int speed);
+void fec_stop(struct net_device *dev);
+
+/***************************************************************************/
+
+int fec_mii_read(struct net_device *dev, int phy_id, int location);
+void fec_mii_write(struct net_device *dev, int phy_id, int location, int value);
+
+int fec_mii_phy_id_detect(struct net_device *dev);
+void fec_mii_startup(struct net_device *dev);
+void fec_mii_shutdown(struct net_device *dev);
+void fec_mii_ack_int(struct net_device *dev);
+
+void fec_mii_link_status_change_check(struct net_device *dev, int init_media);
+
+/***************************************************************************/
+
+#define FEC1_NO        0x00
+#define FEC2_NO        0x01
+#define FEC3_NO        0x02
+
+int fec_8xx_init_one(const struct fec_platform_info *fpi,
+                    struct net_device **devp);
+int fec_8xx_cleanup_one(struct net_device *dev);
+
+/***************************************************************************/
+
+#define DRV_MODULE_NAME                "fec_8xx"
+#define PFX DRV_MODULE_NAME    ": "
+#define DRV_MODULE_VERSION     "0.1"
+#define DRV_MODULE_RELDATE     "May 6, 2004"
+
+/***************************************************************************/
+
+int fec_8xx_platform_init(void);
+void fec_8xx_platform_cleanup(void);
+
+/***************************************************************************/
+
+/* FEC access macros */
+#if defined(CONFIG_8xx)
+/* for a 8xx __raw_xxx's are sufficient */
+#define __fec_out32(addr, x)   __raw_writel(x, addr)
+#define __fec_out16(addr, x)   __raw_writew(x, addr)
+#define __fec_in32(addr)       __raw_readl(addr)
+#define __fec_in16(addr)       __raw_readw(addr)
+#else
+/* for others play it safe */
+#define __fec_out32(addr, x)   out_be32(addr, x)
+#define __fec_out16(addr, x)   out_be16(addr, x)
+#define __fec_in32(addr)       in_be32(addr)
+#define __fec_in16(addr)       in_be16(addr)
+#endif
+
+/* write */
+#define FW(_fecp, _reg, _v) __fec_out32(&(_fecp)->fec_ ## _reg, (_v))
+
+/* read */
+#define FR(_fecp, _reg)        __fec_in32(&(_fecp)->fec_ ## _reg)
+
+/* set bits */
+#define FS(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) | (_v))
+
+/* clear bits */
+#define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v))
+
+/* buffer descriptor access macros */
+
+/* write */
+#define CBDW_SC(_cbd, _sc)             __fec_out16(&(_cbd)->cbd_sc, (_sc))
+#define CBDW_DATLEN(_cbd, _datlen)     __fec_out16(&(_cbd)->cbd_datlen, (_datlen))
+#define CBDW_BUFADDR(_cbd, _bufaddr)   __fec_out32(&(_cbd)->cbd_bufaddr, (_bufaddr))
+
+/* read */
+#define CBDR_SC(_cbd)                  __fec_in16(&(_cbd)->cbd_sc)
+#define CBDR_DATLEN(_cbd)              __fec_in16(&(_cbd)->cbd_datlen)
+#define CBDR_BUFADDR(_cbd)             __fec_in32(&(_cbd)->cbd_bufaddr)
+
+/* set bits */
+#define CBDS_SC(_cbd, _sc)             CBDW_SC(_cbd, CBDR_SC(_cbd) | (_sc))
+
+/* clear bits */
+#define CBDC_SC(_cbd, _sc)             CBDW_SC(_cbd, CBDR_SC(_cbd) & ~(_sc))
+
+/***************************************************************************/
+
+#endif
diff --git a/drivers/net/netdump.c b/drivers/net/netdump.c
new file mode 100644 (file)
index 0000000..3ebea07
--- /dev/null
@@ -0,0 +1,534 @@
+/*
+ *  linux/drivers/net/netdump.c
+ *
+ *  Copyright (C) 2001  Ingo Molnar <mingo@redhat.com>
+ *  Copyright (C) 2002  Red Hat, Inc.
+ *  Copyright (C) 2004  Red Hat, Inc.
+ *
+ *  This file contains the implementation of an IRQ-safe, crash-safe
+ *  kernel console implementation that outputs kernel messages to the
+ *  network.
+ *
+ * Modification history:
+ *
+ * 2001-09-17    started by Ingo Molnar.
+ * 2002-03-14    simultaneous syslog packet option by Michael K. Johnson
+ * 2004-04-07    port to 2.6 netpoll facility by Dave Anderson and Jeff Moyer.
+ */
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/random.h>
+#include <linux/reboot.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <asm/unaligned.h>
+#include <asm/pgtable.h>
+#include <linux/console.h>
+#include <linux/smp_lock.h>
+#include <linux/elf.h>
+#include <linux/preempt.h>
+
+#include "netdump.h"
+#include <linux/netpoll.h>
+
+/*
+ *  prototypes.
+ */
+void netdump_rx(struct netpoll *np, short source, char *data, int dlen);
+static void send_netdump_msg(struct netpoll *np, const char *msg, unsigned int msg_len, reply_t *reply);
+static void send_netdump_mem(struct netpoll *np, req_t *req);
+static void netdump_startup_handshake(struct netpoll *np);
+static void netpoll_netdump(struct pt_regs *regs);
+static void netpoll_start_netdump(struct pt_regs *regs);
+
+
+#include <asm/netdump.h>
+
+
+#undef Dprintk
+#define DEBUG 0
+#if DEBUG
+# define Dprintk(x...) printk(KERN_INFO x)
+#else
+# define Dprintk(x...)
+#endif
+
+MODULE_AUTHOR("Maintainer: Dave Anderson <anderson@redhat.com>");
+MODULE_DESCRIPTION("Network kernel crash dump module");
+MODULE_LICENSE("GPL");
+
+static char config[256];
+module_param_string(netdump, config, 256, 0);
+MODULE_PARM_DESC(netdump, 
+     " netdump=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]\n");
+
+static u32 magic1, magic2;
+module_param(magic1, uint, 000);
+module_param(magic2, uint, 000);
+
+static struct netpoll np = {
+       .name = "netdump",
+       .dev_name = "eth0",
+       .local_port = 6666,
+       .remote_port = 6666,
+       .remote_mac = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+       .rx_hook = netdump_rx,
+       .dump_func = netpoll_start_netdump,
+};
+
+
+/*
+ * NOTE: security depends on the trusted path between the netconsole
+ *       server and netconsole client, since none of the packets are
+ *       encrypted. The random magic number protects the protocol
+ *       against spoofing.
+ */
+static u64 netdump_magic;
+
+static spinlock_t req_lock = SPIN_LOCK_UNLOCKED;
+static int nr_req = 0;
+static LIST_HEAD(request_list);
+
+static unsigned long long t0, jiffy_cycles;
+void *netdump_stack;
+
+
+static void update_jiffies(void)
+{
+       static unsigned long long prev_tick;
+       platform_timestamp(t0);
+
+       /* maintain jiffies in a polling fashion, based on rdtsc. */
+       if (t0 - prev_tick >= jiffy_cycles) {
+               prev_tick += jiffy_cycles;
+               jiffies++;
+       }
+}
+
+static void add_new_req(req_t *req)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&req_lock, flags);
+       list_add_tail(&req->list, &request_list);
+       nr_req++;
+       Dprintk("pending requests: %d.\n", nr_req);
+       spin_unlock_irqrestore(&req_lock, flags);
+}
+
+static req_t *get_new_req(void)
+{
+       req_t *req = NULL;
+       unsigned long flags;
+
+       update_jiffies();
+
+       spin_lock_irqsave(&req_lock, flags);
+       if (nr_req) {
+               req = list_entry(request_list.next, req_t, list);
+               list_del(&req->list);
+               nr_req--;
+       }
+       spin_unlock_irqrestore(&req_lock, flags);
+
+       return req;
+}
+
+static req_t *alloc_req(void)
+{
+       req_t *req;
+
+       req = (req_t *) kmalloc(sizeof(*req), GFP_ATOMIC);
+       return req;
+}
+
+static inline void print_status (req_t *req)
+{
+       static int count = 0;
+       static int prev_jiffies = 0;
+
+       if (jiffies/HZ != prev_jiffies/HZ) {
+               prev_jiffies = jiffies;
+               count++;
+               switch (count & 3) {
+                       case 0: printk("%d(%ld)/\r", nr_req, jiffies); break;
+                       case 1: printk("%d(%ld)|\r", nr_req, jiffies); break;
+                       case 2: printk("%d(%ld)\\\r", nr_req, jiffies); break;
+                       case 3: printk("%d(%ld)-\r", nr_req, jiffies); break;
+               }
+       }
+}
+
+void netdump_rx(struct netpoll *np, short source, char *data, int dlen)
+{
+       req_t *req, *__req = (req_t *)data;
+
+       if (!netdump_mode)
+               return;
+#if DEBUG
+       {
+               static int packet_count;
+               Dprintk("        %d\r", ++packet_count);
+       }
+#endif
+
+       if (dlen < NETDUMP_REQ_SIZE) {
+               Dprintk("... netdump_rx: len not ok.\n");
+               return;
+       }
+
+       req = alloc_req();
+       if (!req) {
+               printk("no more RAM to allocate request - dropping it.\n");
+               return;
+       }
+
+       req->magic = ntohl(__req->magic);
+       req->command = ntohl(__req->command);
+       req->from = ntohl(__req->from);
+       req->to = ntohl(__req->to);
+       req->nr = ntohl(__req->nr);
+
+       Dprintk("... netdump magic:   %08Lx.\n", req->magic);
+       Dprintk("... netdump command: %08x.\n", req->command);
+       Dprintk("... netdump from:    %08x.\n", req->from);
+       Dprintk("... netdump to:      %08x.\n", req->to);
+
+       add_new_req(req);
+       return;
+}
+
+#define MAX_MSG_LEN HEADER_LEN + 1024
+
+static void send_netdump_msg(struct netpoll *np, const char *msg, unsigned int msg_len, reply_t *reply)
+{
+       /* max len should be 1024 + HEADER_LEN */
+       static unsigned char netpoll_msg[MAX_MSG_LEN + 1];
+
+       if (msg_len + HEADER_LEN > MAX_MSG_LEN + 1) {
+               printk("CODER ERROR!!! msg_len %ud too big for send msg\n",
+                      msg_len);
+               for (;;) local_irq_disable();
+               /* NOTREACHED */
+       }
+
+       netpoll_msg[0] = NETDUMP_VERSION;
+       put_unaligned(htonl(reply->nr), (u32 *) (&netpoll_msg[1]));
+       put_unaligned(htonl(reply->code), (u32 *) (&netpoll_msg[5]));
+       put_unaligned(htonl(reply->info), (u32 *) (&netpoll_msg[9]));
+       memcpy(&netpoll_msg[HEADER_LEN], msg, msg_len);
+
+       netpoll_send_udp(np, netpoll_msg, HEADER_LEN + msg_len);
+}
+
+static void send_netdump_mem(struct netpoll *np, req_t *req)
+{
+       int i;
+       char *kaddr;
+       char str[1024];
+       struct page *page;
+       unsigned long nr = req->from;
+       int nr_chunks = PAGE_SIZE/1024;
+       reply_t reply;
+       
+       Dprintk(" ... send_netdump_mem\n");
+       reply.nr = req->nr;
+       reply.info = 0;
+       if (req->from >= platform_max_pfn()) {
+               sprintf(str, "page %08lx is bigger than max page # %08lx!\n", 
+                       nr, platform_max_pfn());
+               reply.code = REPLY_ERROR;
+               send_netdump_msg(np, str, strlen(str), &reply);
+               return;
+       }
+       if (page_is_ram(nr))
+               page = pfn_to_page(nr);
+       else
+               page = ZERO_PAGE(0);
+
+       kaddr = (char *)kmap_atomic(page, KM_NETDUMP);
+
+       for (i = 0; i < nr_chunks; i++) {
+               unsigned int offset = i*1024;
+               reply.code = REPLY_MEM;
+               reply.info = offset;
+               Dprintk(" ... send_netdump_mem: sending message\n");
+               send_netdump_msg(np, kaddr + offset, 1024, &reply);
+               Dprintk(" ... send_netdump_mem: sent message\n");
+       }
+
+       kunmap_atomic(kaddr, KM_NETDUMP);
+       Dprintk(" ... send_netdump_mem: returning\n");
+}
+
+/*
+ * This function waits for the client to acknowledge the receipt
+ * of the netdump startup reply, with the possibility of packets
+ * getting lost. We resend the startup packet if no ACK is received,
+ * after a 1 second delay.
+ *
+ * (The client can test the success of the handshake via the HELLO
+ * command, and send ACKs until we enter netdump mode.)
+ */
+static void netdump_startup_handshake(struct netpoll *np)
+{
+       char tmp[200];
+       reply_t reply;
+       req_t *req = NULL;
+       int i;
+
+repeat:
+       sprintf(tmp, "NETDUMP start, waiting for start-ACK.\n");
+       reply.code = REPLY_START_NETDUMP;
+       reply.nr = 0;
+       reply.info = 0;
+
+       send_netdump_msg(np, tmp, strlen(tmp), &reply);
+
+       for (i = 0; i < 10000; i++) {
+               // wait 1 sec.
+               udelay(100);
+               Dprintk("handshake: polling controller ...\n");
+               netpoll_poll(np);
+               req = get_new_req();
+               if (req)
+                       break;
+       }
+       if (!req)
+               goto repeat;
+       if (req->command != COMM_START_NETDUMP_ACK) {
+               kfree(req);
+               goto repeat;
+       }
+       kfree(req);
+
+       printk("NETDUMP START!\n");
+}
+
+static char cpus_frozen[NR_CPUS] = { 0 }; 
+
+static void freeze_cpu (void * dummy)
+{
+       cpus_frozen[smp_processor_id()] = 1;
+       for (;;) local_irq_disable();
+}
+
+static void netpoll_start_netdump(struct pt_regs *regs)
+{
+       int i;
+       unsigned long flags;
+
+       /*
+        *  The netdump code is not re-entrant for several reasons.  Most
+        *  immediately, we will switch to the base of our stack and 
+        *  overwrite all of our call history.
+        */
+       if (netdump_mode) {
+               printk(KERN_ERR
+               "netpoll_start_netdump: called recursively.  rebooting.\n");
+               mdelay(3000);
+               machine_restart(NULL);
+       }
+       netdump_mode = 1;
+
+       local_irq_save(flags);
+       preempt_disable();
+
+       smp_call_function(freeze_cpu, NULL, 1, -1);
+       mdelay(3000);
+       for (i = 0; i < NR_CPUS; i++) {
+               if (cpus_frozen[i])
+                       printk("CPU#%d is frozen.\n", i);
+               else if (i == smp_processor_id())
+                       printk("CPU#%d is executing netdump.\n", i);
+       }
+
+       /*
+        *  Some platforms may want to execute netdump on its own stack.
+        */
+       platform_start_netdump(netdump_stack, regs);
+
+       preempt_enable_no_resched();
+       local_irq_restore(flags);
+       return;
+}
+
+static void netpoll_netdump(struct pt_regs *regs)
+{
+       reply_t reply;
+       char tmp[200];
+       struct pt_regs myregs;
+       req_t *req;
+
+       /*
+        * Just in case we are crashing within the networking code
+        * ... attempt to fix up.
+        */
+       netpoll_reset_locks(&np);
+       platform_fix_regs();
+       platform_timestamp(t0);
+       netpoll_set_trap(1); /* bypass networking stack */
+
+       printk("< netdump activated - performing handshake with the server. >\n");
+       netdump_startup_handshake(&np);
+
+       printk("< handshake completed - listening for dump requests. >\n");
+
+       while (netdump_mode) {
+               local_irq_disable();
+               Dprintk("main netdump loop: polling controller ...\n");
+               netpoll_poll(&np);
+
+               req = get_new_req();
+               if (!req)
+                       continue;
+
+               Dprintk("got new req, command %d.\n", req->command);
+               print_status(req);
+               switch (req->command) {
+               case COMM_NONE:
+                       Dprintk("got NO command.\n");
+                       break;
+
+               case COMM_SEND_MEM:
+                       Dprintk("got MEM command.\n");
+                       send_netdump_mem(&np, req);
+                       break;
+
+               case COMM_EXIT:
+                       Dprintk("got EXIT command.\n");
+                       netdump_mode = 0;
+                       netpoll_set_trap(0);
+                       break;
+
+               case COMM_REBOOT:
+                       Dprintk("got REBOOT command.\n");
+                       printk("netdump: rebooting in 3 seconds.\n");
+                       mdelay(3000);
+                       machine_restart(NULL);
+                       break;
+
+               case COMM_HELLO:
+                       sprintf(tmp, "Hello, this is netdump version 0.%02d\n",
+                               NETDUMP_VERSION);
+                       reply.code = REPLY_HELLO;
+                       reply.nr = req->nr;
+                       reply.info = NETDUMP_VERSION;
+                       send_netdump_msg(&np, tmp, strlen(tmp), &reply);
+                       break;
+
+               case COMM_GET_PAGE_SIZE:
+                       sprintf(tmp, "PAGE_SIZE: %ld\n", PAGE_SIZE);
+                       reply.code = REPLY_PAGE_SIZE;
+                       reply.nr = req->nr;
+                       reply.info = PAGE_SIZE;
+                       send_netdump_msg(&np, tmp, strlen(tmp), &reply);
+                       break;
+
+               case COMM_GET_REGS:
+               {
+                       char *tmp2 = tmp;
+                       elf_gregset_t elf_regs;
+
+                       reply.code = REPLY_REGS;
+                       reply.nr = req->nr;
+                       reply.info = platform_max_pfn();
+                       tmp2 = tmp + sprintf(tmp, "Sending register info.\n");
+                       ELF_CORE_COPY_REGS(elf_regs, (&myregs));
+                       memcpy(tmp2, &elf_regs, sizeof(elf_regs));
+                       Dprintk("netdump: sending regs\n");
+                       send_netdump_msg(&np, tmp, 
+                               strlen(tmp) + sizeof(elf_regs), &reply);
+                       Dprintk("netdump: sent regs\n");
+                       break;
+               }
+
+               case COMM_GET_NR_PAGES:
+                       reply.code = REPLY_NR_PAGES;
+                       reply.nr = req->nr;
+                       reply.info = platform_max_pfn();
+                       sprintf(tmp, 
+                               "Number of pages: %ld\n", platform_max_pfn());
+                       send_netdump_msg(&np, tmp, strlen(tmp), &reply);
+                       break;
+
+               case COMM_SHOW_STATE:
+                       /* send response first */
+                       reply.code = REPLY_SHOW_STATE;
+                       reply.nr = req->nr;
+                       reply.info = 0;
+
+                       send_netdump_msg(&np, tmp, strlen(tmp), &reply);
+
+                       netdump_mode = 0;
+                       if (regs)
+                               show_regs(regs);
+                       show_state();
+                       show_mem();
+                       netdump_mode = 1;
+                       break;
+
+               default:
+                       reply.code = REPLY_ERROR;
+                       reply.nr = req->nr;
+                       reply.info = req->command;
+                       Dprintk("got UNKNOWN command!\n");
+                       sprintf(tmp, "Got unknown command code %d!\n", 
+                               req->command);
+                       send_netdump_msg(&np, tmp, strlen(tmp), &reply);
+                       break;
+               }
+               kfree(req);
+               req = NULL;
+       }
+       sprintf(tmp, "NETDUMP end.\n");
+       reply.code = REPLY_END_NETDUMP;
+       reply.nr = 0;
+       reply.info = 0;
+       send_netdump_msg(&np, tmp, strlen(tmp), &reply);
+       printk("NETDUMP END!\n");
+}
+
+static int option_setup(char *opt)
+{
+       return !netpoll_parse_options(&np, opt);
+}
+
+__setup("netdump=", option_setup);
+
+static int init_netdump(void)
+{
+       int configured = 0;
+
+       if (strlen(config))
+               configured = option_setup(config);
+
+       if (!configured) {
+               printk(KERN_ERR "netdump: not configured, aborting\n");
+               return -EINVAL;
+       }
+
+       if (netpoll_setup(&np))
+               return -EINVAL;
+
+       if (magic1 || magic2)
+               netdump_magic = magic1 + (((u64)magic2)<<32);
+
+       /*
+        *  Allocate a separate stack for netdump.
+        */
+       platform_init_stack(&netdump_stack);
+
+       printk(KERN_INFO "netdump: network crash dump enabled\n");
+       return 0;
+}
+
+static void cleanup_netdump(void)
+{
+       netpoll_cleanup(&np);
+       platform_cleanup_stack(netdump_stack);
+}
+
+module_init(init_netdump);
+module_exit(cleanup_netdump);
diff --git a/drivers/net/netdump.h b/drivers/net/netdump.h
new file mode 100644 (file)
index 0000000..cc3100e
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *  linux/drivers/net/netdump.h
+ *
+ *  Copyright (C) 2001  Ingo Molnar <mingo@redhat.com>
+ *
+ *  This file contains the implementation of an IRQ-safe, crash-safe
+ *  kernel console implementation that outputs kernel messages to the
+ *  network.
+ *
+ * Modification history:
+ *
+ * 2001-09-17    started by Ingo Molnar.
+ */
+
+/****************************************************************
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2, or (at your option)
+ *      any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+#define NETDUMP_VERSION 0x04
+
+enum netdump_commands {
+       COMM_NONE = 0,
+       COMM_SEND_MEM = 1,
+       COMM_EXIT = 2,
+       COMM_REBOOT = 3,
+       COMM_HELLO = 4,
+       COMM_GET_NR_PAGES = 5,
+       COMM_GET_PAGE_SIZE = 6,
+       COMM_START_NETDUMP_ACK = 7,
+       COMM_GET_REGS = 8,
+       COMM_SHOW_STATE = 9,
+};
+
+#define NETDUMP_REQ_SIZE (8+4*4)
+
+typedef struct netdump_req_s {
+       u64 magic;
+       u32 nr;
+       u32 command;
+       u32 from;
+       u32 to;
+       struct list_head list; 
+} req_t;
+
+enum netdump_replies {
+       REPLY_NONE = 0,
+       REPLY_ERROR = 1,
+       REPLY_LOG = 2,
+       REPLY_MEM = 3,
+       REPLY_RESERVED = 4,
+       REPLY_HELLO = 5,
+       REPLY_NR_PAGES = 6,
+       REPLY_PAGE_SIZE = 7,
+       REPLY_START_NETDUMP = 8,
+       REPLY_END_NETDUMP = 9,
+       REPLY_REGS = 10,
+       REPLY_MAGIC = 11,
+       REPLY_SHOW_STATE = 12,
+};
+
+typedef struct netdump_reply_s {
+       u32 nr;
+       u32 code;
+       u32 info;
+} reply_t;
+
+#define HEADER_LEN (1 + sizeof(reply_t))
+
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
new file mode 100644 (file)
index 0000000..694e13f
--- /dev/null
@@ -0,0 +1,732 @@
+/*
+ * Driver for the Cirrus PD6729 PCI-PCMCIA bridge.
+ *
+ * Based on the i82092.c driver.
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License, incorporated herein by reference.
+ */
+
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/cs.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include "pd6729.h"
+#include "i82365.h"
+#include "cirrus.h"
+
+MODULE_LICENSE("GPL");
+
+#define MAX_SOCKETS 2
+
+/* simple helper functions */
+/* External clock time, in nanoseconds.  120 ns = 8.33 MHz */
+#define to_cycles(ns)  ((ns)/120)
+
+static spinlock_t port_lock = SPIN_LOCK_UNLOCKED;
+
+/* basic value read/write functions */
+
+static unsigned char indirect_read(struct pd6729_socket *socket, unsigned short reg)
+{
+       unsigned long port;
+       unsigned char val;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port_lock, flags);
+       reg += socket->number * 0x40;
+       port = socket->io_base;
+       outb(reg, port);
+       val = inb(port + 1);
+       spin_unlock_irqrestore(&port_lock, flags);
+
+       return val;
+}
+
+static unsigned short indirect_read16(struct pd6729_socket *socket, unsigned short reg)
+{
+       unsigned long port;
+       unsigned short tmp;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port_lock, flags);
+       reg  = reg + socket->number * 0x40;
+       port = socket->io_base;
+       outb(reg, port);
+       tmp = inb(port + 1);
+       reg++;
+       outb(reg, port);
+       tmp = tmp | (inb(port + 1) << 8);
+       spin_unlock_irqrestore(&port_lock, flags);
+
+       return tmp;
+}
+
+static void indirect_write(struct pd6729_socket *socket, unsigned short reg, unsigned char value)
+{
+       unsigned long port;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port_lock, flags);
+       reg = reg + socket->number * 0x40;
+       port = socket->io_base;
+       outb(reg, port);
+       outb(value, port + 1);
+       spin_unlock_irqrestore(&port_lock, flags);
+}
+
+static void indirect_setbit(struct pd6729_socket *socket, unsigned short reg, unsigned char mask)
+{
+       unsigned long port;
+       unsigned char val;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port_lock, flags);
+       reg = reg + socket->number * 0x40;
+       port = socket->io_base;
+       outb(reg, port);
+       val = inb(port + 1);
+       val |= mask;
+       outb(reg, port);
+       outb(val, port + 1);
+       spin_unlock_irqrestore(&port_lock, flags);
+}
+
+static void indirect_resetbit(struct pd6729_socket *socket, unsigned short reg, unsigned char mask)
+{
+       unsigned long port;
+       unsigned char val;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port_lock, flags);
+       reg = reg + socket->number * 0x40;
+       port = socket->io_base;
+       outb(reg, port);
+       val = inb(port + 1);
+       val &= ~mask;
+       outb(reg, port);
+       outb(val, port + 1);
+       spin_unlock_irqrestore(&port_lock, flags);
+}
+
+static void indirect_write16(struct pd6729_socket *socket, unsigned short reg, unsigned short value)
+{
+       unsigned long port;
+       unsigned char val;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port_lock, flags);
+       reg = reg + socket->number * 0x40;
+       port = socket->io_base;
+
+       outb(reg, port);
+       val = value & 255;
+       outb(val, port + 1);
+
+       reg++;
+
+       outb(reg, port);
+       val = value >> 8;
+       outb(val, port + 1);
+       spin_unlock_irqrestore(&port_lock, flags);
+}
+
+/* Interrupt handler functionality */
+
+static irqreturn_t pd6729_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+       struct pd6729_socket *socket = (struct pd6729_socket *)dev;
+       int i;
+       int loopcount = 0;
+       int handled = 0;
+       unsigned int events, active = 0;
+
+       while (1) {
+               loopcount++;
+               if (loopcount > 20) {
+                       printk(KERN_ERR "pd6729: infinite eventloop in interrupt\n");
+                       break;
+               }
+
+               active = 0;
+
+               for (i = 0; i < MAX_SOCKETS; i++) {
+                       unsigned int csc;
+
+                       /* card status change register */
+                       csc = indirect_read(&socket[i], I365_CSC);
+                       if (csc == 0)  /* no events on this socket */
+                               continue;
+
+                       handled = 1;
+                       events = 0;
+
+                       if (csc & I365_CSC_DETECT) {
+                               events |= SS_DETECT;
+                               dprintk("Card detected in socket %i!\n", i);
+                       }
+
+                       if (indirect_read(&socket[i], I365_INTCTL) & I365_PC_IOCARD) {
+                               /* For IO/CARDS, bit 0 means "read the card" */
+                               events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
+                       } else {
+                               /* Check for battery/ready events */
+                               events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0;
+                               events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
+                               events |= (csc & I365_CSC_READY) ? SS_READY : 0;
+                       }
+
+                       if (events) {
+                               pcmcia_parse_events(&socket[i].socket, events);
+                       }
+                       active |= events;
+               }
+
+               if (active == 0) /* no more events to handle */
+                       break;
+       }
+       return IRQ_RETVAL(handled);
+}
+
+/* socket functions */
+
+static void set_bridge_state(struct pd6729_socket *socket)
+{
+       indirect_write(socket, I365_GBLCTL, 0x00);
+       indirect_write(socket, I365_GENCTL, 0x00);
+
+       indirect_setbit(socket, I365_INTCTL, 0x08);
+}
+
+static int pd6729_get_status(struct pcmcia_socket *sock, u_int *value)
+{
+       struct pd6729_socket *socket = container_of(sock, struct pd6729_socket, socket);
+       unsigned int status;
+       unsigned int data;
+       struct pd6729_socket *t;
+
+       /* Interface Status Register */
+       status = indirect_read(socket, I365_STATUS);
+       *value = 0;
+
+       if ((status & I365_CS_DETECT) == I365_CS_DETECT) {
+               *value |= SS_DETECT;
+       }
+
+       /* IO cards have a different meaning of bits 0,1 */
+       /* Also notice the inverse-logic on the bits */
+       if (indirect_read(socket, I365_INTCTL) & I365_PC_IOCARD) {
+               /* IO card */
+               if (!(status & I365_CS_STSCHG))
+                       *value |= SS_STSCHG;
+       } else {
+               /* non I/O card */
+               if (!(status & I365_CS_BVD1))
+                       *value |= SS_BATDEAD;
+               if (!(status & I365_CS_BVD2))
+                       *value |= SS_BATWARN;
+       }
+
+       if (status & I365_CS_WRPROT)
+               *value |= SS_WRPROT;    /* card is write protected */
+
+       if (status & I365_CS_READY)
+               *value |= SS_READY;     /* card is not busy */
+
+       if (status & I365_CS_POWERON)
+               *value |= SS_POWERON;   /* power is applied to the card */
+
+       t = (socket->number) ? socket : socket + 1;
+       indirect_write(t, PD67_EXT_INDEX, PD67_EXTERN_DATA);
+       data = indirect_read16(t, PD67_EXT_DATA);
+       *value |= (data & PD67_EXD_VS1(socket->number)) ? 0 : SS_3VCARD;
+
+       return 0;
+}
+
+
+static int pd6729_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
+{
+       struct pd6729_socket *socket = container_of(sock, struct pd6729_socket, socket);
+       unsigned char reg, vcc, vpp;
+
+       state->flags    = 0;
+       state->Vcc      = 0;
+       state->Vpp      = 0;
+       state->io_irq   = 0;
+       state->csc_mask = 0;
+
+       /* First the power status of the socket */
+       /* PCTRL - Power Control Register */
+       reg = indirect_read(socket, I365_POWER);
+
+       if (reg & I365_PWR_AUTO)
+               state->flags |= SS_PWR_AUTO;  /* Automatic Power Switch */
+
+       if (reg & I365_PWR_OUT)
+               state->flags |= SS_OUTPUT_ENA; /* Output signals are enabled */
+
+       vcc = reg & I365_VCC_MASK;    vpp = reg & I365_VPP1_MASK;
+
+       if (reg & I365_VCC_5V) {
+               state->Vcc = (indirect_read(socket, PD67_MISC_CTL_1) &
+                       PD67_MC1_VCC_3V) ? 33 : 50;
+
+               if (vpp == I365_VPP1_5V) {
+                       if (state->Vcc == 50)
+                               state->Vpp = 50;
+                       else
+                               state->Vpp = 33;
+               }
+               if (vpp == I365_VPP1_12V)
+                       state->Vpp = 120;
+       }
+
+       /* Now the IO card, RESET flags and IO interrupt */
+       /* IGENC, Interrupt and General Control */
+       reg = indirect_read(socket, I365_INTCTL);
+
+       if ((reg & I365_PC_RESET) == 0)
+               state->flags |= SS_RESET;
+       if (reg & I365_PC_IOCARD)
+               state->flags |= SS_IOCARD; /* This is an IO card */
+
+       /* Set the IRQ number */
+       state->io_irq = socket->socket.pci_irq;
+
+       /* Card status change */
+       /* CSCICR, Card Status Change Interrupt Configuration */
+       reg = indirect_read(socket, I365_CSCINT);
+
+       if (reg & I365_CSC_DETECT)
+               state->csc_mask |= SS_DETECT; /* Card detect is enabled */
+
+       if (state->flags & SS_IOCARD) {/* IO Cards behave different */
+               if (reg & I365_CSC_STSCHG)
+                       state->csc_mask |= SS_STSCHG;
+       } else {
+               if (reg & I365_CSC_BVD1)
+                       state->csc_mask |= SS_BATDEAD;
+               if (reg & I365_CSC_BVD2)
+                       state->csc_mask |= SS_BATWARN;
+               if (reg & I365_CSC_READY)
+                       state->csc_mask |= SS_READY;
+       }
+
+       return 0;
+}
+
+static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
+{
+       struct pd6729_socket *socket = container_of(sock, struct pd6729_socket, socket);
+       unsigned char reg;
+
+       /* First, set the global controller options */
+
+       set_bridge_state(socket);
+
+       /* Values for the IGENC register */
+
+       reg = 0;
+       /* The reset bit has "inverse" logic */
+       if (!(state->flags & SS_RESET))
+               reg = reg | I365_PC_RESET;
+       if (state->flags & SS_IOCARD)
+               reg = reg | I365_PC_IOCARD;
+
+       /* IGENC, Interrupt and General Control Register */
+       indirect_write(socket, I365_INTCTL, reg);
+
+       /* Power registers */
+
+       reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */
+
+       if (state->flags & SS_PWR_AUTO) {
+               dprintk("Auto power\n");
+               reg |= I365_PWR_AUTO;   /* automatic power mngmnt */
+       }
+       if (state->flags & SS_OUTPUT_ENA) {
+               dprintk("Power Enabled\n");
+               reg |= I365_PWR_OUT;    /* enable power */
+       }
+
+       switch (state->Vcc) {
+       case 0:
+               break;
+       case 33:
+               dprintk("setting voltage to Vcc to 3.3V on socket %i\n",
+                       socket->number);
+               reg |= I365_VCC_5V;
+               indirect_setbit(socket, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
+               break;
+       case 50:
+               dprintk("setting voltage to Vcc to 5V on socket %i\n",
+                       socket->number);
+               reg |= I365_VCC_5V;
+               indirect_resetbit(socket, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
+               break;
+       default:
+               dprintk("pd6729: pd6729_set_socket called with invalid VCC power value: %i\n",
+                       state->Vcc);
+               return -EINVAL;
+       }
+
+       switch (state->Vpp) {
+       case 0:
+               dprintk("not setting Vpp on socket %i\n", socket->number);
+               break;
+       case 33:
+       case 50:
+               dprintk("setting Vpp to Vcc for socket %i\n", socket->number);
+               reg |= I365_VPP1_5V;
+               break;
+       case 120:
+               dprintk("setting Vpp to 12.0\n");
+               reg |= I365_VPP1_12V;
+               break;
+       default:
+               dprintk("pd6729: pd6729_set_socket called with invalid VPP power value: %i\n",
+                       state->Vpp);
+               return -EINVAL;
+       }
+
+       /* only write if changed */
+       if (reg != indirect_read(socket, I365_POWER))
+               indirect_write(socket, I365_POWER, reg);
+
+       /* Now, specifiy that all interrupts are to be done as PCI interrupts */
+       indirect_write(socket, PD67_EXT_INDEX, PD67_EXT_CTL_1);
+       indirect_write(socket, PD67_EXT_DATA, PD67_EC1_INV_MGMT_IRQ | PD67_EC1_INV_CARD_IRQ);
+
+       /* Enable specific interrupt events */
+
+       reg = 0x00;
+       if (state->csc_mask & SS_DETECT) {
+               reg |= I365_CSC_DETECT;
+       }
+       if (state->flags & SS_IOCARD) {
+               if (state->csc_mask & SS_STSCHG)
+                       reg |= I365_CSC_STSCHG;
+       } else {
+               if (state->csc_mask & SS_BATDEAD)
+                       reg |= I365_CSC_BVD1;
+               if (state->csc_mask & SS_BATWARN)
+                       reg |= I365_CSC_BVD2;
+               if (state->csc_mask & SS_READY)
+                       reg |= I365_CSC_READY;
+       }
+       reg |= 0x30;    /* management IRQ: PCI INTA# = "irq 3" */
+       indirect_write(socket, I365_CSCINT, reg);
+
+       reg = indirect_read(socket, I365_INTCTL);
+       reg |= 0x03;    /* card IRQ: PCI INTA# = "irq 3" */
+       indirect_write(socket, I365_INTCTL, reg);
+
+       /* now clear the (probably bogus) pending stuff by doing a dummy read */
+       (void)indirect_read(socket, I365_CSC);
+
+       return 0;
+}
+
+static int pd6729_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
+{
+       struct pd6729_socket *socket = container_of(sock, struct pd6729_socket, socket);
+       unsigned char map, ioctl;
+
+       map = io->map;
+
+       /* Check error conditions */
+       if (map > 1) {
+               dprintk("pd6729_set_io_map with invalid map");
+               return -EINVAL;
+       }
+
+       /* Turn off the window before changing anything */
+       if (indirect_read(socket, I365_ADDRWIN) & I365_ENA_IO(map))
+               indirect_resetbit(socket, I365_ADDRWIN, I365_ENA_IO(map));
+
+/*     dprintk("set_io_map: Setting range to %x - %x\n", io->start, io->stop);*/
+
+       /* write the new values */
+       indirect_write16(socket, I365_IO(map)+I365_W_START, io->start);
+       indirect_write16(socket, I365_IO(map)+I365_W_STOP, io->stop);
+
+       ioctl = indirect_read(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map);
+
+       if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map);
+       if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map);
+       if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map);
+
+       indirect_write(socket, I365_IOCTL, ioctl);
+
+       /* Turn the window back on if needed */
+       if (io->flags & MAP_ACTIVE)
+               indirect_setbit(socket, I365_ADDRWIN, I365_ENA_IO(map));
+
+       return 0;
+}
+
+static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
+{
+       struct pd6729_socket *socket = container_of(sock, struct pd6729_socket, socket);
+       unsigned short base, i;
+       unsigned char map;
+
+       map = mem->map;
+       if (map > 4) {
+               printk("pd6729_set_mem_map: invalid map");
+               return -EINVAL;
+       }
+
+       if ((mem->sys_start > mem->sys_stop) || (mem->speed > 1000)) {
+               printk("pd6729_set_mem_map: invalid address / speed");
+               /* printk("invalid mem map for socket %i : %lx to %lx with a start of %x\n",
+                        sock, mem->sys_start, mem->sys_stop, mem->card_start); */
+               return -EINVAL;
+       }
+
+       /* Turn off the window before changing anything */
+       if (indirect_read(socket, I365_ADDRWIN) & I365_ENA_MEM(map))
+               indirect_resetbit(socket, I365_ADDRWIN, I365_ENA_MEM(map));
+
+       /* write the start address */
+       base = I365_MEM(map);
+       i = (mem->sys_start >> 12) & 0x0fff;
+       if (mem->flags & MAP_16BIT)
+               i |= I365_MEM_16BIT;
+       if (mem->flags & MAP_0WS)
+               i |= I365_MEM_0WS;
+       indirect_write16(socket, base + I365_W_START, i);
+
+       /* write the stop address */
+
+       i= (mem->sys_stop >> 12) & 0x0fff;
+       switch (to_cycles(mem->speed)) {
+       case 0:
+               break;
+       case 1:
+               i |= I365_MEM_WS0;
+               break;
+       case 2:
+               i |= I365_MEM_WS1;
+               break;
+       default:
+               i |= I365_MEM_WS1 | I365_MEM_WS0;
+               break;
+       }
+
+       indirect_write16(socket, base + I365_W_STOP, i);
+
+       /* Take care of high byte */
+       indirect_write(socket, PD67_EXT_INDEX, PD67_MEM_PAGE(map));
+       indirect_write(socket, PD67_EXT_DATA, mem->sys_start >> 24);
+
+       /* card start */
+
+       i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
+       if (mem->flags & MAP_WRPROT)
+               i |= I365_MEM_WRPROT;
+       if (mem->flags & MAP_ATTRIB) {
+/*             dprintk("requesting attribute memory for socket %i\n",
+                       socket->number);*/
+               i |= I365_MEM_REG;
+       } else {
+/*             dprintk("requesting normal memory for socket %i\n",
+                       socket->number);*/
+       }
+       indirect_write16(socket, base + I365_W_OFF, i);
+
+       /* Enable the window if necessary */
+       if (mem->flags & MAP_ACTIVE)
+               indirect_setbit(socket, I365_ADDRWIN, I365_ENA_MEM(map));
+
+       return 0;
+}
+
+static int pd6729_suspend(struct pcmcia_socket *sock)
+{
+       return pd6729_set_socket(sock, &dead_socket);
+}
+
+static int pd6729_init(struct pcmcia_socket *sock)
+{
+       int i;
+       struct resource res = { .end = 0x0fff };
+       pccard_io_map io = { 0, 0, 0, 0, 1 };
+       pccard_mem_map mem = { .res = &res, .sys_stop = 0x0fff };
+
+       pd6729_set_socket(sock, &dead_socket);
+       for (i = 0; i < 2; i++) {
+               io.map = i;
+               pd6729_set_io_map(sock, &io);
+       }
+       for (i = 0; i < 5; i++) {
+               mem.map = i;
+               pd6729_set_mem_map(sock, &mem);
+       }
+
+       return 0;
+}
+
+
+/* the pccard structure and its functions */
+static struct pccard_operations pd6729_operations = {
+       .init                   = pd6729_init,
+       .suspend                = pd6729_suspend,
+       .get_status             = pd6729_get_status,
+       .get_socket             = pd6729_get_socket,
+       .set_socket             = pd6729_set_socket,
+       .set_io_map             = pd6729_set_io_map,
+       .set_mem_map            = pd6729_set_mem_map,
+};
+
+static int __devinit pd6729_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+       int i, j, ret;
+       char configbyte;
+       struct pd6729_socket *socket;
+
+       socket = kmalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS, GFP_KERNEL);
+       if (!socket)
+               return -ENOMEM;
+
+       memset(socket, 0, sizeof(struct pd6729_socket) * MAX_SOCKETS);
+
+       if ((ret = pci_enable_device(dev)))
+               goto err_out_free_mem;
+
+       printk(KERN_INFO "pd6729: Cirrus PD6729 PCI to PCMCIA Bridge at 0x%lx on irq %d\n",
+               pci_resource_start(dev, 0), dev->irq);
+       printk(KERN_INFO "pd6729: configured as a %d socket device.\n", MAX_SOCKETS);
+       /* Since we have no memory BARs some firmware we may not
+          have had PCI_COMMAND_MEM enabled, yet the device needs
+          it. */
+       pci_read_config_byte(dev, PCI_COMMAND, &configbyte);
+       if (!(configbyte & PCI_COMMAND_MEMORY)) {
+               printk(KERN_DEBUG "pd6729: Enabling PCI_COMMAND_MEMORY.\n");
+               configbyte |= PCI_COMMAND_MEMORY;
+               pci_write_config_byte(dev, PCI_COMMAND, configbyte);
+       }
+
+       ret = pci_request_regions(dev, "pd6729");
+       if (ret) {
+               printk(KERN_INFO "pd6729: pci request region failed.\n");
+               goto err_out_disable;
+       }
+
+       for (i = 0; i < MAX_SOCKETS; i++) {
+               socket[i].io_base = pci_resource_start(dev, 0);
+               socket[i].socket.features |= SS_CAP_PCCARD;
+               socket[i].socket.map_size = 0x1000;
+               socket[i].socket.irq_mask = 0;
+               socket[i].socket.pci_irq  = dev->irq;
+               socket[i].socket.owner = THIS_MODULE;
+
+               socket[i].number = i;
+
+               socket[i].socket.ops = &pd6729_operations;
+               socket[i].socket.dev.dev = &dev->dev;
+               socket[i].socket.driver_data = &socket[i];
+       }
+
+       pci_set_drvdata(dev, socket);
+
+       /* Register the interrupt handler */
+       if ((ret = request_irq(dev->irq, pd6729_interrupt, SA_SHIRQ, "pd6729", socket))) {
+               printk(KERN_ERR "pd6729: Failed to register irq %d, aborting\n", dev->irq);
+               goto err_out_free_res;
+       }
+
+       for (i = 0; i < MAX_SOCKETS; i++) {
+               ret = pcmcia_register_socket(&socket[i].socket);
+               if (ret) {
+                       printk(KERN_INFO "pd6729: pcmcia_register_socket failed.\n");
+                       for (j = 0; j < i ; j++)
+                               pcmcia_unregister_socket(&socket[j].socket);
+                       goto err_out_free_res2;
+               }
+       }
+
+       return 0;
+
+ err_out_free_res2:
+       free_irq(dev->irq, socket);
+ err_out_free_res:
+       pci_release_regions(dev);
+ err_out_disable:
+       pci_disable_device(dev);
+
+ err_out_free_mem:
+       kfree(socket);
+       return ret;
+}
+
+static void __devexit pd6729_pci_remove(struct pci_dev *dev)
+{
+       int i;
+       struct pd6729_socket *socket = pci_get_drvdata(dev);
+
+       for (i = 0; i < MAX_SOCKETS; i++)
+               pcmcia_unregister_socket(&socket[i].socket);
+
+       free_irq(dev->irq, socket);
+       pci_release_regions(dev);
+       pci_disable_device(dev);
+
+       kfree(socket);
+}
+
+static int pd6729_socket_suspend(struct pci_dev *dev, u32 state)
+{
+       return pcmcia_socket_dev_suspend(&dev->dev, state);
+}
+
+static int pd6729_socket_resume(struct pci_dev *dev)
+{
+       return pcmcia_socket_dev_resume(&dev->dev);
+}
+
+static struct pci_device_id pd6729_pci_ids[] = {
+       {
+               .vendor         = PCI_VENDOR_ID_CIRRUS,
+               .device         = PCI_DEVICE_ID_CIRRUS_6729,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(pci, pd6729_pci_ids);
+
+static struct pci_driver pd6729_pci_drv = {
+       .name           = "pd6729",
+       .id_table       = pd6729_pci_ids,
+       .probe          = pd6729_pci_probe,
+       .remove         = __devexit_p(pd6729_pci_remove),
+       .suspend        = pd6729_socket_suspend,
+       .resume         = pd6729_socket_resume,
+};
+
+static int pd6729_module_init(void)
+{
+       return pci_module_init(&pd6729_pci_drv);
+}
+
+static void pd6729_module_exit(void)
+{
+       pci_unregister_driver(&pd6729_pci_drv);
+}
+
+module_init(pd6729_module_init);
+module_exit(pd6729_module_exit);
diff --git a/drivers/pcmcia/pd6729.h b/drivers/pcmcia/pd6729.h
new file mode 100644 (file)
index 0000000..9e90520
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _INCLUDE_GUARD_PD6729_H_
+#define _INCLUDE_GUARD_PD6729_H_
+
+/* Debuging defines */
+#ifdef NOTRACE
+#define dprintk(fmt, args...) printk(fmt , ## args)
+#else
+#define dprintk(fmt, args...) do {} while (0)
+#endif
+
+/* Flags for I365_GENCTL */
+#define I365_DF_VS1            0x40    /* DF-step Voltage Sense */
+#define I365_DF_VS2            0x80
+
+/* Fields in PD67_EXTERN_DATA */
+#define PD67_EXD_VS1(s)                (0x01 << ((s) << 1))
+#define PD67_EXD_VS2(s)                (0x02 << ((s) << 1))
+
+
+
+
+struct pd6729_socket {
+       int     number;
+       unsigned long io_base;  /* base io address of the socket */
+       struct pcmcia_socket socket;
+};
+
+#endif
diff --git a/drivers/s390/net/ctcdbug.c b/drivers/s390/net/ctcdbug.c
new file mode 100644 (file)
index 0000000..ba004e0
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ *
+ * linux/drivers/s390/net/ctcdbug.c ($Revision: 1.1 $)
+ *
+ * Linux on zSeries OSA Express and HiperSockets support
+ *
+ * Copyright 2000,2003 IBM Corporation
+ *
+ *    Author(s): Original Code written by
+ *                       Peter Tiedemann (ptiedem@de.ibm.com)
+ *
+ *    $Revision: 1.1 $  $Date: 2004/07/02 16:31:22 $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "ctcdbug.h"
+
+/**
+ * Debug Facility Stuff
+ */
+debug_info_t *dbf_setup = NULL;
+debug_info_t *dbf_data = NULL;
+debug_info_t *dbf_trace = NULL;
+
+DEFINE_PER_CPU(char[256], dbf_txt_buf);
+
+void
+unregister_dbf_views(void)
+{
+       if (dbf_setup)
+               debug_unregister(dbf_setup);
+       if (dbf_data)
+               debug_unregister(dbf_data);
+       if (dbf_trace)
+               debug_unregister(dbf_trace);
+}
+int
+register_dbf_views(void)
+{
+       dbf_setup = debug_register(CTC_DBF_SETUP_NAME,
+                                       CTC_DBF_SETUP_INDEX,
+                                       CTC_DBF_SETUP_NR_AREAS,
+                                       CTC_DBF_SETUP_LEN);
+       dbf_data = debug_register(CTC_DBF_DATA_NAME,
+                                      CTC_DBF_DATA_INDEX,
+                                      CTC_DBF_DATA_NR_AREAS,
+                                      CTC_DBF_DATA_LEN);
+       dbf_trace = debug_register(CTC_DBF_TRACE_NAME,
+                                       CTC_DBF_TRACE_INDEX,
+                                       CTC_DBF_TRACE_NR_AREAS,
+                                       CTC_DBF_TRACE_LEN);
+
+       if ((dbf_setup == NULL) || (dbf_data == NULL) ||
+           (dbf_trace == NULL)) {
+               unregister_dbf_views();
+               return -ENOMEM;
+       }
+       debug_register_view(dbf_setup, &debug_hex_ascii_view);
+       debug_set_level(dbf_setup, CTC_DBF_SETUP_LEVEL);
+
+       debug_register_view(dbf_data, &debug_hex_ascii_view);
+       debug_set_level(dbf_data, CTC_DBF_DATA_LEVEL);
+
+       debug_register_view(dbf_trace, &debug_hex_ascii_view);
+       debug_set_level(dbf_trace, CTC_DBF_TRACE_LEVEL);
+
+       return 0;
+}
+
+
diff --git a/drivers/s390/net/ctcdbug.h b/drivers/s390/net/ctcdbug.h
new file mode 100644 (file)
index 0000000..447fd1a
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ *
+ * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.1 $)
+ *
+ * Linux on zSeries OSA Express and HiperSockets support
+ *
+ * Copyright 2000,2003 IBM Corporation
+ *
+ *    Author(s): Original Code written by
+ *                       Peter Tiedemann (ptiedem@de.ibm.com)
+ *
+ *    $Revision: 1.1 $  $Date: 2004/07/02 16:31:22 $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <asm/debug.h>
+/**
+ * Debug Facility stuff
+ */
+#define CTC_DBF_SETUP_NAME "ctc_setup"
+#define CTC_DBF_SETUP_LEN 16
+#define CTC_DBF_SETUP_INDEX 3
+#define CTC_DBF_SETUP_NR_AREAS 1
+#define CTC_DBF_SETUP_LEVEL 3
+
+#define CTC_DBF_DATA_NAME "ctc_data"
+#define CTC_DBF_DATA_LEN 128
+#define CTC_DBF_DATA_INDEX 3
+#define CTC_DBF_DATA_NR_AREAS 1
+#define CTC_DBF_DATA_LEVEL 2
+
+#define CTC_DBF_TRACE_NAME "ctc_trace"
+#define CTC_DBF_TRACE_LEN 16
+#define CTC_DBF_TRACE_INDEX 2
+#define CTC_DBF_TRACE_NR_AREAS 2
+#define CTC_DBF_TRACE_LEVEL 3
+
+#define DBF_TEXT(name,level,text) \
+       do { \
+               debug_text_event(dbf_##name,level,text); \
+       } while (0)
+
+#define DBF_HEX(name,level,addr,len) \
+       do { \
+               debug_event(dbf_##name,level,(void*)(addr),len); \
+       } while (0)
+
+extern DEFINE_PER_CPU(char[256], dbf_txt_buf);
+extern debug_info_t *dbf_setup;
+extern debug_info_t *dbf_data;
+extern debug_info_t *dbf_trace;
+
+
+#define DBF_TEXT_(name,level,text...)                          \
+       do {                                                            \
+               char* dbf_txt_buf = get_cpu_var(dbf_txt_buf);   \
+               sprintf(dbf_txt_buf, text);                             \
+               debug_text_event(dbf_##name,level,dbf_txt_buf); \
+               put_cpu_var(dbf_txt_buf);                               \
+       } while (0)
+
+#define DBF_SPRINTF(name,level,text...) \
+       do { \
+               debug_sprintf_event(dbf_trace, level, ##text ); \
+               debug_sprintf_event(dbf_trace, level, text ); \
+       } while (0)
+
+
+int register_dbf_views(void);
+
+void unregister_dbf_views(void);
+
+/**
+ * some more debug stuff
+ */
+
+#define HEXDUMP16(importance,header,ptr) \
+PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
+                  "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
+                  *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \
+                  *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \
+                  *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \
+                  *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \
+                  *(((char*)ptr)+12),*(((char*)ptr)+13), \
+                  *(((char*)ptr)+14),*(((char*)ptr)+15)); \
+PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
+                  "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
+                  *(((char*)ptr)+16),*(((char*)ptr)+17), \
+                  *(((char*)ptr)+18),*(((char*)ptr)+19), \
+                  *(((char*)ptr)+20),*(((char*)ptr)+21), \
+                  *(((char*)ptr)+22),*(((char*)ptr)+23), \
+                  *(((char*)ptr)+24),*(((char*)ptr)+25), \
+                  *(((char*)ptr)+26),*(((char*)ptr)+27), \
+                  *(((char*)ptr)+28),*(((char*)ptr)+29), \
+                  *(((char*)ptr)+30),*(((char*)ptr)+31));
+
+static inline void
+hex_dump(unsigned char *buf, size_t len)
+{
+       size_t i;
+
+       for (i = 0; i < len; i++) {
+               if (i && !(i % 16))
+                       printk("\n");
+               printk("%02x ", *(buf + i));
+       }
+       printk("\n");
+}
+
diff --git a/drivers/scsi/fdomain.h b/drivers/scsi/fdomain.h
new file mode 100644 (file)
index 0000000..47021d9
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * fdomain.c -- Future Domain TMC-16x0 SCSI driver
+ * Author: Rickard E. Faith, faith@cs.unc.edu
+ * Copyright 1992-1996, 1998 Rickard E. Faith (faith@acm.org)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+extern struct scsi_host_template fdomain_driver_template;
+extern int fdomain_setup(char *str);
+extern struct Scsi_Host *__fdomain_16x0_detect(struct  scsi_host_template *tpnt );
+extern int fdomain_16x0_bus_reset(struct scsi_cmnd *SCpnt);
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
new file mode 100644 (file)
index 0000000..bf1932e
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+ *  sata_nv.c - NVIDIA nForce SATA
+ *
+ *  Copyright 2004 NVIDIA Corp.  All rights reserved.
+ *  Copyright 2004 Andrew Chew
+ *
+ *  The contents of this file are subject to the Open
+ *  Software License version 1.1 that can be found at
+ *  http://www.opensource.org/licenses/osl-1.1.txt and is included herein
+ *  by reference.
+ *
+ *  Alternatively, the contents of this file may be used under the terms
+ *  of the GNU General Public License version 2 (the "GPL") as distributed
+ *  in the kernel source COPYING file, in which case the provisions of
+ *  the GPL are applicable instead of the above.  If you wish to allow
+ *  the use of your version of this file only under the terms of the
+ *  GPL and not to allow others to use your version of this file under
+ *  the OSL, indicate your decision by deleting the provisions above and
+ *  replace them with the notice and other provisions required by the GPL.
+ *  If you do not delete the provisions above, a recipient may use your
+ *  version of this file under either the OSL or the GPL.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#define DRV_NAME                       "sata_nv"
+#define DRV_VERSION                    "0.01"
+
+#define NV_PORTS                       2
+#define NV_PIO_MASK                    0x1f
+#define NV_UDMA_MASK                   0x7f
+#define NV_PORT0_BMDMA_REG_OFFSET      0x00
+#define NV_PORT1_BMDMA_REG_OFFSET      0x08
+#define NV_PORT0_SCR_REG_OFFSET                0x00
+#define NV_PORT1_SCR_REG_OFFSET                0x40
+
+#define NV_INT_STATUS                  0x10
+#define NV_INT_STATUS_PDEV_INT         0x01
+#define NV_INT_STATUS_PDEV_PM          0x02
+#define NV_INT_STATUS_PDEV_ADDED       0x04
+#define NV_INT_STATUS_PDEV_REMOVED     0x08
+#define NV_INT_STATUS_SDEV_INT         0x10
+#define NV_INT_STATUS_SDEV_PM          0x20
+#define NV_INT_STATUS_SDEV_ADDED       0x40
+#define NV_INT_STATUS_SDEV_REMOVED     0x80
+#define NV_INT_STATUS_PDEV_HOTPLUG     (NV_INT_STATUS_PDEV_ADDED | \
+                                       NV_INT_STATUS_PDEV_REMOVED)
+#define NV_INT_STATUS_SDEV_HOTPLUG     (NV_INT_STATUS_SDEV_ADDED | \
+                                       NV_INT_STATUS_SDEV_REMOVED)
+#define NV_INT_STATUS_HOTPLUG          (NV_INT_STATUS_PDEV_HOTPLUG | \
+                                       NV_INT_STATUS_SDEV_HOTPLUG)
+
+#define NV_INT_ENABLE                  0x11
+#define NV_INT_ENABLE_PDEV_MASK                0x01
+#define NV_INT_ENABLE_PDEV_PM          0x02
+#define NV_INT_ENABLE_PDEV_ADDED       0x04
+#define NV_INT_ENABLE_PDEV_REMOVED     0x08
+#define NV_INT_ENABLE_SDEV_MASK                0x10
+#define NV_INT_ENABLE_SDEV_PM          0x20
+#define NV_INT_ENABLE_SDEV_ADDED       0x40
+#define NV_INT_ENABLE_SDEV_REMOVED     0x80
+#define NV_INT_ENABLE_PDEV_HOTPLUG     (NV_INT_ENABLE_PDEV_ADDED | \
+                                       NV_INT_ENABLE_PDEV_REMOVED)
+#define NV_INT_ENABLE_SDEV_HOTPLUG     (NV_INT_ENABLE_SDEV_ADDED | \
+                                       NV_INT_ENABLE_SDEV_REMOVED)
+#define NV_INT_ENABLE_HOTPLUG          (NV_INT_ENABLE_PDEV_HOTPLUG | \
+                                       NV_INT_ENABLE_SDEV_HOTPLUG)
+
+#define NV_INT_CONFIG                  0x12
+#define NV_INT_CONFIG_METHD            0x01 // 0 = INT, 1 = SMI
+
+static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg);
+static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+static void nv_host_stop (struct ata_host_set *host_set);
+
+static struct pci_device_id nv_pci_tbl[] = {
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       { 0, } /* terminate list */
+};
+
+static struct pci_driver nv_pci_driver = {
+       .name                   = DRV_NAME,
+       .id_table               = nv_pci_tbl,
+       .probe                  = nv_init_one,
+       .remove                 = ata_pci_remove_one,
+};
+
+static Scsi_Host_Template nv_sht = {
+       .module                 = THIS_MODULE,
+       .name                   = DRV_NAME,
+       .queuecommand           = ata_scsi_queuecmd,
+       .eh_strategy_handler    = ata_scsi_error,
+       .can_queue              = ATA_DEF_QUEUE,
+       .this_id                = ATA_SHT_THIS_ID,
+       .sg_tablesize           = ATA_MAX_PRD,
+       .max_sectors            = ATA_MAX_SECTORS,
+       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
+       .emulated               = ATA_SHT_EMULATED,
+       .use_clustering         = ATA_SHT_USE_CLUSTERING,
+       .proc_name              = DRV_NAME,
+       .dma_boundary           = ATA_DMA_BOUNDARY,
+       .slave_configure        = ata_scsi_slave_config,
+       .bios_param             = ata_std_bios_param,
+};
+
+static struct ata_port_operations nv_ops = {
+       .port_disable           = ata_port_disable,
+       .tf_load                = ata_tf_load_pio,
+       .tf_read                = ata_tf_read_pio,
+       .exec_command           = ata_exec_command_pio,
+       .check_status           = ata_check_status_pio,
+       .phy_reset              = sata_phy_reset,
+       .bmdma_setup            = ata_bmdma_setup_pio,
+       .bmdma_start            = ata_bmdma_start_pio,
+       .qc_prep                = ata_qc_prep,
+       .qc_issue               = ata_qc_issue_prot,
+       .eng_timeout            = ata_eng_timeout,
+       .irq_handler            = nv_interrupt,
+       .irq_clear              = ata_bmdma_irq_clear,
+       .scr_read               = nv_scr_read,
+       .scr_write              = nv_scr_write,
+       .port_start             = ata_port_start,
+       .port_stop              = ata_port_stop,
+       .host_stop              = nv_host_stop,
+};
+
+MODULE_AUTHOR("NVIDIA");
+MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
+
+irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+{
+       struct ata_host_set *host_set = dev_instance;
+       unsigned int i;
+       unsigned int handled = 0;
+       unsigned long flags;
+       u8 intr_status;
+       u8 intr_enable;
+
+       spin_lock_irqsave(&host_set->lock, flags);
+
+       for (i = 0; i < host_set->n_ports; i++) {
+               struct ata_port *ap;
+
+               ap = host_set->ports[i];
+               if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+                       struct ata_queued_cmd *qc;
+
+                       qc = ata_qc_from_tag(ap, ap->active_tag);
+                       if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+                               handled += ata_host_intr(ap, qc);
+               }
+
+               intr_status = inb(ap->ioaddr.scr_addr + NV_INT_STATUS);
+               intr_enable = inb(ap->ioaddr.scr_addr + NV_INT_ENABLE);
+
+               // Clear interrupt status.
+               outb(0xff, ap->ioaddr.scr_addr + NV_INT_STATUS);
+
+               if (intr_status & NV_INT_STATUS_HOTPLUG) {
+                       if (intr_status & NV_INT_STATUS_PDEV_ADDED) {
+                               printk(KERN_WARNING "ata%u: "
+                                       "Primary device added\n", ap->id);
+                       }
+
+                       if (intr_status & NV_INT_STATUS_PDEV_REMOVED) {
+                               printk(KERN_WARNING "ata%u: "
+                                       "Primary device removed\n", ap->id);
+                       }
+
+                       if (intr_status & NV_INT_STATUS_SDEV_ADDED) {
+                               printk(KERN_WARNING "ata%u: "
+                                       "Secondary device added\n", ap->id);
+                       }
+
+                       if (intr_status & NV_INT_STATUS_SDEV_REMOVED) {
+                               printk(KERN_WARNING "ata%u: "
+                                       "Secondary device removed\n", ap->id);
+                       }
+               }
+       }
+
+       spin_unlock_irqrestore(&host_set->lock, flags);
+
+       return IRQ_RETVAL(handled);
+}
+
+static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+       if (sc_reg > SCR_CONTROL)
+               return 0xffffffffU;
+
+       return inl(ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+{
+       if (sc_reg > SCR_CONTROL)
+               return;
+
+       outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+static void nv_host_stop (struct ata_host_set *host_set)
+{
+       int i;
+
+       for (i=0; i<host_set->n_ports; i++) {
+               u8 intr_mask;
+
+               // Disable hotplug event interrupts.
+               intr_mask = inb(host_set->ports[i]->ioaddr.scr_addr +
+                               NV_INT_ENABLE);
+               intr_mask &= ~(NV_INT_ENABLE_HOTPLUG);
+               outb(intr_mask, host_set->ports[i]->ioaddr.scr_addr +
+                               NV_INT_ENABLE);
+       }
+}
+
+static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       static int printed_version = 0;
+       struct ata_probe_ent *probe_ent = NULL;
+       int i;
+       int rc;
+
+       if (!printed_version++)
+               printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       rc = pci_request_regions(pdev, DRV_NAME);
+       if (rc)
+               goto err_out;
+
+       rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+       if (rc)
+               goto err_out_regions;
+       rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+       if (rc)
+               goto err_out_regions;
+
+       probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+       if (!probe_ent) {
+               rc = -ENOMEM;
+               goto err_out_regions;
+       }
+
+       memset(probe_ent, 0, sizeof(*probe_ent));
+       INIT_LIST_HEAD(&probe_ent->node);
+
+       probe_ent->pdev = pdev;
+       probe_ent->sht = &nv_sht;
+       probe_ent->host_flags = ATA_FLAG_SATA |
+                               ATA_FLAG_SATA_RESET |
+                               ATA_FLAG_SRST |
+                               ATA_FLAG_NO_LEGACY;
+       probe_ent->port_ops = &nv_ops;
+       probe_ent->n_ports = NV_PORTS;
+       probe_ent->irq = pdev->irq;
+       probe_ent->irq_flags = SA_SHIRQ;
+       probe_ent->pio_mask = NV_PIO_MASK;
+       probe_ent->udma_mask = NV_UDMA_MASK;
+
+       probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
+       ata_std_ports(&probe_ent->port[0]);
+       probe_ent->port[0].altstatus_addr =
+       probe_ent->port[0].ctl_addr =
+               pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
+       probe_ent->port[0].bmdma_addr =
+               pci_resource_start(pdev, 4) | NV_PORT0_BMDMA_REG_OFFSET;
+       probe_ent->port[0].scr_addr =
+               pci_resource_start(pdev, 5) | NV_PORT0_SCR_REG_OFFSET;
+
+       probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
+       ata_std_ports(&probe_ent->port[1]);
+       probe_ent->port[1].altstatus_addr =
+       probe_ent->port[1].ctl_addr =
+               pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
+       probe_ent->port[1].bmdma_addr =
+               pci_resource_start(pdev, 4) | NV_PORT1_BMDMA_REG_OFFSET;
+       probe_ent->port[1].scr_addr =
+               pci_resource_start(pdev, 5) | NV_PORT1_SCR_REG_OFFSET;
+
+       pci_set_master(pdev);
+
+       rc = ata_device_add(probe_ent);
+       if (rc != NV_PORTS)
+               goto err_out_regions;
+
+       // Enable hotplug event interrupts.
+       for (i=0; i<probe_ent->n_ports; i++) {
+               u8 intr_mask;
+
+               outb(NV_INT_STATUS_HOTPLUG, probe_ent->port[i].scr_addr +
+                                               NV_INT_STATUS);
+
+               intr_mask = inb(probe_ent->port[i].scr_addr + NV_INT_ENABLE);
+               intr_mask |= NV_INT_ENABLE_HOTPLUG;
+               outb(intr_mask, probe_ent->port[i].scr_addr + NV_INT_ENABLE);
+       }
+
+       kfree(probe_ent);
+
+       return 0;
+
+err_out_regions:
+       pci_release_regions(pdev);
+
+err_out:
+       pci_disable_device(pdev);
+       return rc;
+}
+
+static int __init nv_init(void)
+{
+       return pci_module_init(&nv_pci_driver);
+}
+
+static void __exit nv_exit(void)
+{
+       pci_unregister_driver(&nv_pci_driver);
+}
+
+module_init(nv_init);
+module_exit(nv_exit);
diff --git a/drivers/serial/cpm_uart/Makefile b/drivers/serial/cpm_uart/Makefile
new file mode 100644 (file)
index 0000000..e072724
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for the Motorola 8xx FEC ethernet controller
+#
+
+obj-$(CONFIG_SERIAL_CPM) += cpm_uart.o
+
+# Select the correct platform objects.
+cpm_uart-objs-$(CONFIG_CPM2)   += cpm_uart_cpm2.o
+cpm_uart-objs-$(CONFIG_8xx)    += cpm_uart_cpm1.o
+
+cpm_uart-objs  := cpm_uart_core.o $(cpm_uart-objs-y)
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
new file mode 100644 (file)
index 0000000..0612e94
--- /dev/null
@@ -0,0 +1,1179 @@
+/*
+ *  linux/drivers/serial/cpm_uart.c
+ *
+ *  Driver for CPM (SCC/SMC) serial ports; core driver
+ *
+ *  Based on arch/ppc/cpm2_io/uart.c by Dan Malek
+ *  Based on ppc8xx.c by Thomas Gleixner
+ *  Based on drivers/serial/amba.c by Russell King
+ *
+ *  Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
+ *              Pantelis Antoniou (panto@intracom.gr) (CPM1)
+ * 
+ *  Copyright (C) 2004 Freescale Semiconductor, Inc.
+ *            (C) 2004 Intracom, S.A.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/device.h>
+#include <linux/bootmem.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/delay.h>
+
+#if defined(CONFIG_SERIAL_CPM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/serial_core.h>
+#include <linux/kernel.h>
+
+#include "cpm_uart.h"
+
+/***********************************************************************/
+
+/* Track which ports are configured as uarts */
+int cpm_uart_port_map[UART_NR];
+/* How many ports did we config as uarts */
+int cpm_uart_nr;
+
+/**************************************************************/
+
+static int  cpm_uart_tx_pump(struct uart_port *port);
+static void cpm_uart_init_smc(struct uart_cpm_port *pinfo, int bits, u16 cval);
+static void cpm_uart_init_scc(struct uart_cpm_port *pinfo, int sbits, u16 sval);
+
+/**************************************************************/
+
+/*
+ * Check, if transmit buffers are processed            
+*/
+static unsigned int cpm_uart_tx_empty(struct uart_port *port)
+{
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+       volatile cbd_t *bdp = pinfo->tx_bd_base;
+       int ret = 0;
+
+       while (1) {
+               if (bdp->cbd_sc & BD_SC_READY)
+                       break;
+
+               if (bdp->cbd_sc & BD_SC_WRAP) {
+                       ret = TIOCSER_TEMT;
+                       break;
+               }
+               bdp++;
+       }
+
+       pr_debug("CPM uart[%d]:tx_empty: %d\n", port->line, ret);
+
+       return ret;
+}
+
+static void cpm_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+       /* Whee. Do nothing. */
+}
+
+static unsigned int cpm_uart_get_mctrl(struct uart_port *port)
+{
+       /* Whee. Do nothing. */
+       return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+/*
+ * Stop transmitter
+ */
+static void cpm_uart_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+       volatile smc_t *smcp = pinfo->smcp;
+       volatile scc_t *sccp = pinfo->sccp;
+
+       pr_debug("CPM uart[%d]:stop tx\n", port->line);
+
+       if (IS_SMC(pinfo))
+               smcp->smc_smcm &= ~SMCM_TX;
+       else
+               sccp->scc_sccm &= ~UART_SCCM_TX;
+}
+
+/*
+ * Start transmitter
+ */
+static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+       volatile smc_t *smcp = pinfo->smcp;
+       volatile scc_t *sccp = pinfo->sccp;
+
+       pr_debug("CPM uart[%d]:start tx\n", port->line);
+
+       /* if in the middle of discarding return */
+       if (IS_DISCARDING(pinfo))
+               return;
+
+       if (IS_SMC(pinfo)) {
+               if (smcp->smc_smcm & SMCM_TX)
+                       return;
+       } else {
+               if (sccp->scc_sccm & UART_SCCM_TX)
+                       return;
+       }
+
+       if (cpm_uart_tx_pump(port) != 0) {
+               if (IS_SMC(pinfo))
+                       smcp->smc_smcm |= SMCM_TX;
+               else
+                       sccp->scc_sccm |= UART_SCCM_TX;
+       }
+}
+
+/*
+ * Stop receiver 
+ */
+static void cpm_uart_stop_rx(struct uart_port *port)
+{
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+       volatile smc_t *smcp = pinfo->smcp;
+       volatile scc_t *sccp = pinfo->sccp;
+
+       pr_debug("CPM uart[%d]:stop rx\n", port->line);
+
+       if (IS_SMC(pinfo))
+               smcp->smc_smcm &= ~SMCM_RX;
+       else
+               sccp->scc_sccm &= ~UART_SCCM_RX;
+}
+
+/*
+ * Enable Modem status interrupts
+ */
+static void cpm_uart_enable_ms(struct uart_port *port)
+{
+       pr_debug("CPM uart[%d]:enable ms\n", port->line);
+}
+
+/*
+ * Generate a break. 
+ */
+static void cpm_uart_break_ctl(struct uart_port *port, int break_state)
+{
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+       int line = pinfo - cpm_uart_ports;
+
+       pr_debug("CPM uart[%d]:break ctrl, break_state: %d\n", port->line,
+               break_state);
+
+       if (break_state)
+               cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
+       else
+               cpm_line_cr_cmd(line, CPM_CR_RESTART_TX);
+}
+
+/*
+ * Transmit characters, refill buffer descriptor, if possible
+ */
+static void cpm_uart_int_tx(struct uart_port *port, struct pt_regs *regs)
+{
+       pr_debug("CPM uart[%d]:TX INT\n", port->line);
+
+       cpm_uart_tx_pump(port);
+}
+
+/*
+ * Receive characters
+ */
+static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
+{
+       int i;
+       unsigned char ch, *cp;
+       struct tty_struct *tty = port->info->tty;
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+       volatile cbd_t *bdp;
+       u16 status;
+       unsigned int flg;
+
+       pr_debug("CPM uart[%d]:RX INT\n", port->line);
+
+       /* Just loop through the closed BDs and copy the characters into
+        * the buffer.
+        */
+       bdp = pinfo->rx_cur;
+       for (;;) {
+               /* get status */
+               status = bdp->cbd_sc;
+               /* If this one is empty, return happy */
+               if (status & BD_SC_EMPTY)
+                       break;
+
+               /* get number of characters, and check spce in flip-buffer */
+               i = bdp->cbd_datlen;
+
+               /* If we have not enough room in tty flip buffer, then we try 
+                * later, which will be the next rx-interrupt or a timeout
+                */
+               if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) {
+                       tty->flip.work.func((void *)tty);
+                       if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) {
+                               printk(KERN_WARNING "TTY_DONT_FLIP set\n");
+                               return;
+                       }
+               }
+
+               /* get pointer */
+               cp = (unsigned char *)bus_to_virt(bdp->cbd_bufaddr);
+
+               /* loop through the buffer */
+               while (i-- > 0) {
+                       ch = *cp++;
+                       port->icount.rx++;
+                       flg = TTY_NORMAL;
+
+                       if (status &
+                           (BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV))
+                               goto handle_error;
+                       if (uart_handle_sysrq_char(port, ch, regs))
+                               continue;
+
+                     error_return:
+                       *tty->flip.char_buf_ptr++ = ch;
+                       *tty->flip.flag_buf_ptr++ = flg;
+                       tty->flip.count++;
+
+               }               /* End while (i--) */
+
+               /* This BD is ready to be used again. Clear status. get next */
+               bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
+               bdp->cbd_sc |= BD_SC_EMPTY;
+
+               if (bdp->cbd_sc & BD_SC_WRAP)
+                       bdp = pinfo->rx_bd_base;
+               else
+                       bdp++;
+       } /* End for (;;) */
+
+       /* Write back buffer pointer */
+       pinfo->rx_cur = (volatile cbd_t *) bdp;
+
+       /* activate BH processing */
+       tty_flip_buffer_push(tty);
+
+       return;
+
+       /* Error processing */
+
+      handle_error:
+       /* Statistics */
+       if (status & BD_SC_BR)
+               port->icount.brk++;
+       if (status & BD_SC_PR)
+               port->icount.parity++;
+       if (status & BD_SC_FR)
+               port->icount.frame++;
+       if (status & BD_SC_OV)
+               port->icount.overrun++;
+
+       /* Mask out ignored conditions */
+       status &= port->read_status_mask;
+
+       /* Handle the remaining ones */
+       if (status & BD_SC_BR)
+               flg = TTY_BREAK;
+       else if (status & BD_SC_PR)
+               flg = TTY_PARITY;
+       else if (status & BD_SC_FR)
+               flg = TTY_FRAME;
+
+       /* overrun does not affect the current character ! */
+       if (status & BD_SC_OV) {
+               ch = 0;
+               flg = TTY_OVERRUN;
+               /* We skip this buffer */
+               /* CHECK: Is really nothing senseful there */
+               /* ASSUMPTION: it contains nothing valid */
+               i = 0;
+       }
+#ifdef SUPPORT_SYSRQ
+       port->sysrq = 0;
+#endif
+       goto error_return;
+}
+
+/*
+ * Asynchron mode interrupt handler
+ */
+static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs)
+{
+       u8 events;
+       struct uart_port *port = (struct uart_port *)data;
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+       volatile smc_t *smcp = pinfo->smcp;
+       volatile scc_t *sccp = pinfo->sccp;
+
+       pr_debug("CPM uart[%d]:IRQ\n", port->line);
+
+       if (IS_SMC(pinfo)) {
+               events = smcp->smc_smce;
+               if (events & SMCM_BRKE)
+                       uart_handle_break(port);
+               if (events & SMCM_RX)
+                       cpm_uart_int_rx(port, regs);
+               if (events & SMCM_TX)
+                       cpm_uart_int_tx(port, regs);
+               smcp->smc_smce = events;
+       } else {
+               events = sccp->scc_scce;
+               if (events & UART_SCCM_BRKE)
+                       uart_handle_break(port);
+               if (events & UART_SCCM_RX)
+                       cpm_uart_int_rx(port, regs);
+               if (events & UART_SCCM_TX)
+                       cpm_uart_int_tx(port, regs);
+               sccp->scc_scce = events;
+       }
+       return (events) ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int cpm_uart_startup(struct uart_port *port)
+{
+       int retval;
+
+       pr_debug("CPM uart[%d]:startup\n", port->line);
+
+       /* Install interrupt handler. */
+       retval = request_irq(port->irq, cpm_uart_int, 0, "cpm_uart", port);
+       if (retval)
+               return retval;
+
+       return 0;
+}
+
+/*
+ * Shutdown the uart
+ */
+static void cpm_uart_shutdown(struct uart_port *port)
+{
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+       int line = pinfo - cpm_uart_ports;
+
+       pr_debug("CPM uart[%d]:shutdown\n", port->line);
+
+       /* free interrupt handler */
+       free_irq(port->irq, port);
+
+       /* If the port is not the console, disable Rx and Tx. */
+       if (!(pinfo->flags & FLAG_CONSOLE)) {
+               /* Stop uarts */
+               if (IS_SMC(pinfo)) {
+                       volatile smc_t *smcp = pinfo->smcp;
+                       smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+                       smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
+               } else {
+                       volatile scc_t *sccp = pinfo->sccp;
+                       sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+                       sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+               }
+
+               /* Shut them really down and reinit buffer descriptors */
+               cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
+       }
+}
+
+static void cpm_uart_set_termios(struct uart_port *port,
+                                struct termios *termios, struct termios *old)
+{
+       int baud;
+       unsigned long flags;
+       u16 cval, scval;
+       int bits, sbits;
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+       int line = pinfo - cpm_uart_ports;
+       volatile cbd_t *bdp;
+
+       pr_debug("CPM uart[%d]:set_termios\n", port->line);
+
+       spin_lock_irqsave(&port->lock, flags);
+       /* disable uart interrupts */
+       if (IS_SMC(pinfo))
+               pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
+       else
+               pinfo->sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+       pinfo->flags |= FLAG_DISCARDING;
+       spin_unlock_irqrestore(&port->lock, flags);
+
+       /* if previous configuration exists wait for tx to finish */
+       if (pinfo->baud != 0 && pinfo->bits != 0) {
+
+               /* point to the last txed bd */
+               bdp = pinfo->tx_cur;
+               if (bdp == pinfo->tx_bd_base)
+                       bdp = pinfo->tx_bd_base + (pinfo->tx_nrfifos - 1);
+               else
+                       bdp--;
+
+               /* wait for it to be transmitted */
+               while ((bdp->cbd_sc & BD_SC_READY) != 0)
+                       schedule();
+
+               /* and delay for the hw fifo to drain */
+               udelay((3 * 1000000 * pinfo->bits) / pinfo->baud);
+       }
+
+       spin_lock_irqsave(&port->lock, flags);
+
+       /* Send the CPM an initialize command. */
+       cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
+
+       /* Stop uart */
+       if (IS_SMC(pinfo))
+               pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+       else
+               pinfo->sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+       /* Send the CPM an initialize command. */
+       cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
+
+       spin_unlock_irqrestore(&port->lock, flags);
+
+       baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
+
+       /* Character length programmed into the mode register is the
+        * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
+        * 1 or 2 stop bits, minus 1.
+        * The value 'bits' counts this for us.
+        */
+       cval = 0;
+       scval = 0;
+
+       /* byte size */
+       switch (termios->c_cflag & CSIZE) {
+       case CS5:
+               bits = 5;
+               break;
+       case CS6:
+               bits = 6;
+               break;
+       case CS7:
+               bits = 7;
+               break;
+       case CS8:
+               bits = 8;
+               break;
+               /* Never happens, but GCC is too dumb to figure it out */
+       default:
+               bits = 8;
+               break;
+       }
+       sbits = bits - 5;
+
+       if (termios->c_cflag & CSTOPB) {
+               cval |= SMCMR_SL;       /* Two stops */
+               scval |= SCU_PSMR_SL;
+               bits++;
+       }
+
+       if (termios->c_cflag & PARENB) {
+               cval |= SMCMR_PEN;
+               scval |= SCU_PSMR_PEN;
+               bits++;
+               if (!(termios->c_cflag & PARODD)) {
+                       cval |= SMCMR_PM_EVEN;
+                       scval |= (SCU_PSMR_REVP | SCU_PSMR_TEVP);
+               }
+       }
+
+       /*
+        * Set up parity check flag
+        */
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+       port->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);
+       if (termios->c_iflag & INPCK)
+               port->read_status_mask |= BD_SC_FR | BD_SC_PR;
+       if ((termios->c_iflag & BRKINT) || (termios->c_iflag & PARMRK))
+               port->read_status_mask |= BD_SC_BR;
+
+       /*
+        * Characters to ignore
+        */
+       port->ignore_status_mask = 0;
+       if (termios->c_iflag & IGNPAR)
+               port->ignore_status_mask |= BD_SC_PR | BD_SC_FR;
+       if (termios->c_iflag & IGNBRK) {
+               port->ignore_status_mask |= BD_SC_BR;
+               /*
+                * If we're ignore parity and break indicators, ignore
+                * overruns too.  (For real raw support).
+                */
+               if (termios->c_iflag & IGNPAR)
+                       port->ignore_status_mask |= BD_SC_OV;
+       }
+       /*
+        * !!! ignore all characters if CREAD is not set
+        */
+       if ((termios->c_cflag & CREAD) == 0)
+               port->read_status_mask &= ~BD_SC_EMPTY;
+       
+       spin_lock_irqsave(&port->lock, flags);
+
+       cpm_set_brg(pinfo->brg - 1, baud);
+
+       /* Start bit has not been added (so don't, because we would just
+        * subtract it later), and we need to add one for the number of
+        * stops bits (there is always at least one).
+        */
+       bits++;
+
+       /* re-init */
+       if (IS_SMC(pinfo))
+               cpm_uart_init_smc(pinfo, bits, cval);
+       else
+               cpm_uart_init_scc(pinfo, sbits, scval);
+
+       pinfo->baud = baud;
+       pinfo->bits = bits;
+
+       pinfo->flags &= ~FLAG_DISCARDING;
+       spin_unlock_irqrestore(&port->lock, flags);
+
+}
+
+static const char *cpm_uart_type(struct uart_port *port)
+{
+       pr_debug("CPM uart[%d]:uart_type\n", port->line);
+
+       return port->type == PORT_CPM ? "CPM UART" : NULL;
+}
+
+/*
+ * verify the new serial_struct (for TIOCSSERIAL).
+ */
+static int cpm_uart_verify_port(struct uart_port *port,
+                               struct serial_struct *ser)
+{
+       int ret = 0;
+
+       pr_debug("CPM uart[%d]:verify_port\n", port->line);
+
+       if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
+               ret = -EINVAL;
+       if (ser->irq < 0 || ser->irq >= NR_IRQS)
+               ret = -EINVAL;
+       if (ser->baud_base < 9600)
+               ret = -EINVAL;
+       return ret;
+}
+
+/*
+ * Transmit characters, refill buffer descriptor, if possible
+ */
+static int cpm_uart_tx_pump(struct uart_port *port)
+{
+       volatile cbd_t *bdp;
+       unsigned char *p;
+       int count;
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+       struct circ_buf *xmit = &port->info->xmit;
+
+       /* Handle xon/xoff */
+       if (port->x_char) {
+               /* Pick next descriptor and fill from buffer */
+               bdp = pinfo->tx_cur;
+
+               p = bus_to_virt(bdp->cbd_bufaddr);
+               *p++ = xmit->buf[xmit->tail];
+               bdp->cbd_datlen = 1;
+               bdp->cbd_sc |= BD_SC_READY;
+               /* Get next BD. */
+               if (bdp->cbd_sc & BD_SC_WRAP)
+                       bdp = pinfo->tx_bd_base;
+               else
+                       bdp++;
+               pinfo->tx_cur = bdp;
+
+               port->icount.tx++;
+               port->x_char = 0;
+               return 1;
+       }
+
+       if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+               cpm_uart_stop_tx(port, 0);
+               return 0;
+       }
+
+       /* Pick next descriptor and fill from buffer */
+       bdp = pinfo->tx_cur;
+
+       while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
+               count = 0;
+               p = bus_to_virt(bdp->cbd_bufaddr);
+               while (count < pinfo->tx_fifosize) {
+                       *p++ = xmit->buf[xmit->tail];
+                       xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+                       port->icount.tx++;
+                       count++;
+                       if (xmit->head == xmit->tail)
+                               break;
+               }
+               bdp->cbd_datlen = count;
+               bdp->cbd_sc |= BD_SC_READY;
+               /* Get next BD. */
+               if (bdp->cbd_sc & BD_SC_WRAP)
+                       bdp = pinfo->tx_bd_base;
+               else
+                       bdp++;
+       }
+       pinfo->tx_cur = bdp;
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(port);
+
+       if (uart_circ_empty(xmit)) {
+               cpm_uart_stop_tx(port, 0);
+               return 0;
+       }
+
+       return 1;
+}
+
+static void cpm_uart_init_scc(struct uart_cpm_port *pinfo, int bits, u16 scval)
+{
+       int line = pinfo - cpm_uart_ports;
+       volatile scc_t *scp;
+       volatile scc_uart_t *sup;
+       u8 *mem_addr;
+       volatile cbd_t *bdp;
+       int i;
+
+       pr_debug("CPM uart[%d]:init_scc\n", pinfo->port.line);
+
+       scp = pinfo->sccp;
+       sup = pinfo->sccup;
+
+       /* Set the physical address of the host memory
+        * buffers in the buffer descriptors, and the
+        * virtual address for us to work with.
+        */
+       pinfo->rx_cur = pinfo->rx_bd_base;
+       mem_addr = pinfo->mem_addr;
+       for (bdp = pinfo->rx_bd_base, i = 0; i < pinfo->rx_nrfifos; i++, bdp++) {
+               bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+               bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT | (i < (pinfo->rx_nrfifos - 1) ? 0 : BD_SC_WRAP);
+               mem_addr += pinfo->rx_fifosize;
+       }
+
+       /* Set the physical address of the host memory
+        * buffers in the buffer descriptors, and the
+        * virtual address for us to work with.
+        */
+       mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize);
+       pinfo->tx_cur = pinfo->tx_bd_base;
+       for (bdp = pinfo->tx_bd_base, i = 0; i < pinfo->tx_nrfifos; i++, bdp++) {
+               bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+               bdp->cbd_sc = BD_SC_INTRPT | (i < (pinfo->tx_nrfifos - 1) ? 0 : BD_SC_WRAP);
+               mem_addr += pinfo->tx_fifosize;
+               bdp++;
+       }
+
+       /* Store address */
+       pinfo->sccup->scc_genscc.scc_rbase = (unsigned char *)pinfo->rx_bd_base - DPRAM_BASE;
+       pinfo->sccup->scc_genscc.scc_tbase = (unsigned char *)pinfo->tx_bd_base - DPRAM_BASE;
+
+       /* Set up the uart parameters in the
+        * parameter ram.
+        */
+
+       cpm_set_scc_fcr(sup);
+
+       sup->scc_genscc.scc_mrblr = pinfo->rx_fifosize;
+       sup->scc_maxidl = pinfo->rx_fifosize;
+       sup->scc_brkcr = 1;
+       sup->scc_parec = 0;
+       sup->scc_frmec = 0;
+       sup->scc_nosec = 0;
+       sup->scc_brkec = 0;
+       sup->scc_uaddr1 = 0;
+       sup->scc_uaddr2 = 0;
+       sup->scc_toseq = 0;
+       sup->scc_char1 = 0x8000;
+       sup->scc_char2 = 0x8000;
+       sup->scc_char3 = 0x8000;
+       sup->scc_char4 = 0x8000;
+       sup->scc_char5 = 0x8000;
+       sup->scc_char6 = 0x8000;
+       sup->scc_char7 = 0x8000;
+       sup->scc_char8 = 0x8000;
+       sup->scc_rccm = 0xc0ff;
+
+       /* Send the CPM an initialize command.
+        */
+       cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
+
+       /* Set UART mode, 8 bit, no parity, one stop.
+        * Enable receive and transmit.
+        */
+       scp->scc_gsmrh = 0;
+       scp->scc_gsmrl =
+           (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+
+       /* Enable rx interrupts  and clear all pending events.  */
+       scp->scc_sccm = UART_SCCM_RX;
+       scp->scc_scce = 0xffff;
+       scp->scc_dsr = 0x7e7e;
+       scp->scc_psmr = (bits << 12) | scval;
+
+       scp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+}
+
+static void cpm_uart_init_smc(struct uart_cpm_port *pinfo, int bits, u16 cval)
+{
+       int line = pinfo - cpm_uart_ports;
+       volatile smc_t *sp;
+       volatile smc_uart_t *up;
+       volatile u8 *mem_addr;
+       volatile cbd_t *bdp;
+       int i;
+
+       pr_debug("CPM uart[%d]:init_smc\n", pinfo->port.line);
+
+       sp = pinfo->smcp;
+       up = pinfo->smcup;
+
+       /* Set the physical address of the host memory
+        * buffers in the buffer descriptors, and the
+        * virtual address for us to work with.
+        */
+       mem_addr = pinfo->mem_addr;
+       pinfo->rx_cur = pinfo->rx_bd_base;
+       for (bdp = pinfo->rx_bd_base, i = 0; i < pinfo->rx_nrfifos; i++, bdp++) {
+               bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+               bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT | (i < (pinfo->rx_nrfifos - 1) ? 0 : BD_SC_WRAP);
+               mem_addr += pinfo->rx_fifosize;
+       }
+
+       /* Set the physical address of the host memory
+        * buffers in the buffer descriptors, and the
+        * virtual address for us to work with.
+        */
+       mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize);
+       pinfo->tx_cur = pinfo->tx_bd_base;
+       for (bdp = pinfo->tx_bd_base, i = 0; i < pinfo->tx_nrfifos; i++, bdp++) {
+               bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+               bdp->cbd_sc = BD_SC_INTRPT | (i < (pinfo->tx_nrfifos - 1) ? 0 : BD_SC_WRAP);
+               mem_addr += pinfo->tx_fifosize;
+       }
+
+       /* Store address */
+       pinfo->smcup->smc_rbase = (u_char *)pinfo->rx_bd_base - DPRAM_BASE;
+       pinfo->smcup->smc_tbase = (u_char *)pinfo->tx_bd_base - DPRAM_BASE;
+
+       /* Set up the uart parameters in the
+        * parameter ram.
+        */
+       cpm_set_smc_fcr(up);
+
+       /* Using idle charater time requires some additional tuning.  */
+       up->smc_mrblr = pinfo->rx_fifosize;
+       up->smc_maxidl = pinfo->rx_fifosize;
+       up->smc_brkcr = 1;
+
+       cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
+
+       /* Set UART mode, according to the parameters */
+       sp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART;
+
+       /* Enable only rx interrupts clear all pending events. */
+       sp->smc_smcm = SMCM_RX;
+       sp->smc_smce = 0xff;
+
+       sp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
+}
+
+/*
+ * Initialize port. This is called from early_console stuff
+ * so we have to be careful here !
+ */
+static int cpm_uart_request_port(struct uart_port *port)
+{
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+       int ret;
+
+       pr_debug("CPM uart[%d]:request port\n", port->line);
+
+       if (pinfo->flags & FLAG_CONSOLE)
+               return 0;
+
+       /*
+        * Setup any port IO, connect any baud rate generators,
+        * etc.  This is expected to be handled by board
+        * dependant code 
+        */
+       if (pinfo->set_lineif)
+               pinfo->set_lineif(pinfo);
+
+       ret = cpm_uart_allocbuf(pinfo, 0);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static void cpm_uart_release_port(struct uart_port *port)
+{
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+
+       if (!(pinfo->flags & FLAG_CONSOLE))
+               cpm_uart_freebuf(pinfo);
+}
+
+/*
+ * Configure/autoconfigure the port.
+ */
+static void cpm_uart_config_port(struct uart_port *port, int flags)
+{
+       pr_debug("CPM uart[%d]:config_port\n", port->line);
+
+       if (flags & UART_CONFIG_TYPE) {
+               port->type = PORT_CPM;
+               cpm_uart_request_port(port);
+       }
+}
+static struct uart_ops cpm_uart_pops = {
+       .tx_empty       = cpm_uart_tx_empty,
+       .set_mctrl      = cpm_uart_set_mctrl,
+       .get_mctrl      = cpm_uart_get_mctrl,
+       .stop_tx        = cpm_uart_stop_tx,
+       .start_tx       = cpm_uart_start_tx,
+       .stop_rx        = cpm_uart_stop_rx,
+       .enable_ms      = cpm_uart_enable_ms,
+       .break_ctl      = cpm_uart_break_ctl,
+       .startup        = cpm_uart_startup,
+       .shutdown       = cpm_uart_shutdown,
+       .set_termios    = cpm_uart_set_termios,
+       .type           = cpm_uart_type,
+       .release_port   = cpm_uart_release_port,
+       .request_port   = cpm_uart_request_port,
+       .config_port    = cpm_uart_config_port,
+       .verify_port    = cpm_uart_verify_port,
+};
+
+struct uart_cpm_port cpm_uart_ports[UART_NR] = {
+       [UART_SMC1] = {
+               .port = {
+                       .irq            = SMC1_IRQ,
+                       .ops            = &cpm_uart_pops,
+                       .iotype         = SERIAL_IO_MEM,
+               },
+               .flags = FLAG_SMC,
+               .tx_nrfifos = TX_NUM_FIFO,
+               .tx_fifosize = TX_BUF_SIZE,
+               .rx_nrfifos = RX_NUM_FIFO, 
+               .rx_fifosize = RX_BUF_SIZE,
+               .set_lineif = smc1_lineif,
+       },
+       [UART_SMC2] = {
+               .port = {
+                       .irq            = SMC2_IRQ,
+                       .ops            = &cpm_uart_pops,
+                       .iotype         = SERIAL_IO_MEM,
+               },
+               .flags = FLAG_SMC,
+               .tx_nrfifos = TX_NUM_FIFO,
+               .tx_fifosize = TX_BUF_SIZE,
+               .rx_nrfifos = RX_NUM_FIFO, 
+               .rx_fifosize = RX_BUF_SIZE,
+               .set_lineif = smc2_lineif,
+       },
+       [UART_SCC1] = {
+               .port = {
+                       .irq            = SCC1_IRQ,
+                       .ops            = &cpm_uart_pops,
+                       .iotype         = SERIAL_IO_MEM,
+               },
+               .tx_nrfifos = TX_NUM_FIFO,
+               .tx_fifosize = TX_BUF_SIZE,
+               .rx_nrfifos = RX_NUM_FIFO, 
+               .rx_fifosize = RX_BUF_SIZE,
+               .set_lineif = scc1_lineif,
+       },
+       [UART_SCC2] = {
+               .port = {
+                       .irq            = SCC2_IRQ,
+                       .ops            = &cpm_uart_pops,
+                       .iotype         = SERIAL_IO_MEM,
+               },
+               .tx_nrfifos = TX_NUM_FIFO,
+               .tx_fifosize = TX_BUF_SIZE,
+               .rx_nrfifos = RX_NUM_FIFO, 
+               .rx_fifosize = RX_BUF_SIZE,
+               .set_lineif = scc2_lineif,
+       },
+       [UART_SCC3] = {
+               .port = {
+                       .irq            = SCC3_IRQ,
+                       .ops            = &cpm_uart_pops,
+                       .iotype         = SERIAL_IO_MEM,
+               },
+               .tx_nrfifos = TX_NUM_FIFO,
+               .tx_fifosize = TX_BUF_SIZE,
+               .rx_nrfifos = RX_NUM_FIFO, 
+               .rx_fifosize = RX_BUF_SIZE,
+               .set_lineif = scc3_lineif,
+       },
+       [UART_SCC4] = {
+               .port = {
+                       .irq            = SCC4_IRQ,
+                       .ops            = &cpm_uart_pops,
+                       .iotype         = SERIAL_IO_MEM,
+               },
+               .tx_nrfifos = TX_NUM_FIFO,
+               .tx_fifosize = TX_BUF_SIZE,
+               .rx_nrfifos = RX_NUM_FIFO, 
+               .rx_fifosize = RX_BUF_SIZE,
+               .set_lineif = scc4_lineif,
+       },
+};
+
+#ifdef CONFIG_SERIAL_CPM_CONSOLE
+/*
+ *     Print a string to the serial port trying not to disturb
+ *     any possible real use of the port...
+ *
+ *     Note that this is called with interrupts already disabled
+ */
+static void cpm_uart_console_write(struct console *co, const char *s,
+                                  u_int count)
+{
+       struct uart_cpm_port *pinfo =
+           &cpm_uart_ports[cpm_uart_port_map[co->index]];
+       unsigned int i;
+       volatile cbd_t *bdp, *bdbase;
+       volatile unsigned char *cp;
+
+       if (IS_DISCARDING(pinfo))
+               return;
+
+       /* Get the address of the host memory buffer.
+        */
+       bdp = pinfo->tx_cur;
+       bdbase = pinfo->tx_bd_base;
+
+       /*
+        * Now, do each character.  This is not as bad as it looks
+        * since this is a holding FIFO and not a transmitting FIFO.
+        * We could add the complexity of filling the entire transmit
+        * buffer, but we would just wait longer between accesses......
+        */
+       for (i = 0; i < count; i++, s++) {
+               /* Wait for transmitter fifo to empty.
+                * Ready indicates output is ready, and xmt is doing
+                * that, not that it is ready for us to send.
+                */
+               while ((bdp->cbd_sc & BD_SC_READY) != 0)
+                       ;
+
+               /* Send the character out.
+                * If the buffer address is in the CPM DPRAM, don't
+                * convert it.
+                */
+               if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR)
+                       cp = (unsigned char *) (bdp->cbd_bufaddr);
+               else
+                       cp = bus_to_virt(bdp->cbd_bufaddr);
+               
+               *cp = *s;
+
+               bdp->cbd_datlen = 1;
+               bdp->cbd_sc |= BD_SC_READY;
+
+               if (bdp->cbd_sc & BD_SC_WRAP)
+                       bdp = bdbase;
+               else
+                       bdp++;
+
+               /* if a LF, also do CR... */
+               if (*s == 10) {
+                       while ((bdp->cbd_sc & BD_SC_READY) != 0)
+                               ;
+
+                       if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR)
+                               cp = (unsigned char *) (bdp->cbd_bufaddr);
+                       else
+                               cp = bus_to_virt(bdp->cbd_bufaddr);
+
+                       *cp = 13;
+                       bdp->cbd_datlen = 1;
+                       bdp->cbd_sc |= BD_SC_READY;
+
+                       if (bdp->cbd_sc & BD_SC_WRAP)
+                               bdp = bdbase;
+                       else
+                               bdp++;
+               }
+       }
+
+       /*
+        * Finally, Wait for transmitter & holding register to empty
+        *  and restore the IER
+        */
+       while ((bdp->cbd_sc & BD_SC_READY) != 0)
+               ;
+
+       pinfo->tx_cur = (volatile cbd_t *) bdp;
+}
+
+/*
+ * Setup console. Be careful is called early !
+ */
+static int __init cpm_uart_console_setup(struct console *co, char *options)
+{
+       struct uart_port *port;
+       struct uart_cpm_port *pinfo;
+       int baud = 38400;
+       int bits = 8;
+       int parity = 'n';
+       int flow = 'n';
+       int ret;
+
+       port =
+           (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
+       pinfo = (struct uart_cpm_port *)port;
+       
+       pinfo->flags |= FLAG_CONSOLE;
+
+       if (options) {
+               uart_parse_options(options, &baud, &parity, &bits, &flow);
+       } else {
+               bd_t *bd = (bd_t *) __res;
+
+               if (bd->bi_baudrate)
+                       baud = bd->bi_baudrate;
+               else
+                       baud = 9600;
+       }
+
+       /*
+        * Setup any port IO, connect any baud rate generators,
+        * etc.  This is expected to be handled by board
+        * dependant code 
+        */
+       if (pinfo->set_lineif)
+               pinfo->set_lineif(pinfo);
+
+       ret = cpm_uart_allocbuf(pinfo, 1);
+       if (ret)
+               return ret;
+
+       uart_set_options(port, co, baud, parity, bits, flow);
+
+       return 0;
+}
+
+extern struct uart_driver cpm_reg;
+static struct console cpm_scc_uart_console = {
+       .name           "ttyCPM",
+       .write          cpm_uart_console_write,
+       .device         uart_console_device,
+       .setup          cpm_uart_console_setup,
+       .flags          CON_PRINTBUFFER,
+       .index          -1,
+       .data           = &cpm_reg,
+};
+
+int __init cpm_uart_console_init(void)
+{
+       int ret = cpm_uart_init_portdesc();
+
+       if (!ret)
+               register_console(&cpm_scc_uart_console);
+       return ret;
+}
+
+console_initcall(cpm_uart_console_init);
+
+#define CPM_UART_CONSOLE       &cpm_scc_uart_console
+#else
+#define CPM_UART_CONSOLE       NULL
+#endif
+
+static struct uart_driver cpm_reg = {
+       .owner          = THIS_MODULE,
+       .driver_name    = "ttyCPM",
+       .dev_name       = "ttyCPM",
+       .major          = SERIAL_CPM_MAJOR,
+       .minor          = SERIAL_CPM_MINOR,
+       .cons           = CPM_UART_CONSOLE,
+};
+
+static int __init cpm_uart_init(void)
+{
+       int ret, i;
+
+       printk(KERN_INFO "Serial: CPM driver $Revision: 0.01 $\n");
+
+#ifndef CONFIG_SERIAL_CPM_CONSOLE
+       ret = cpm_uart_init_portdesc();
+       if (ret)
+               return ret;
+#endif
+
+       cpm_reg.nr = cpm_uart_nr;
+       ret = uart_register_driver(&cpm_reg);
+
+       if (ret)
+               return ret;
+
+       for (i = 0; i < cpm_uart_nr; i++) {
+               int con = cpm_uart_port_map[i];
+               cpm_uart_ports[con].port.line = i;
+               cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF;
+               uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port);
+       }
+
+       return ret;
+}
+
+static void __exit cpm_uart_exit(void)
+{
+       int i;
+
+       for (i = 0; i < cpm_uart_nr; i++) {
+               int con = cpm_uart_port_map[i];
+               uart_remove_one_port(&cpm_reg, &cpm_uart_ports[con].port);
+       }
+
+       uart_unregister_driver(&cpm_reg);
+}
+
+module_init(cpm_uart_init);
+module_exit(cpm_uart_exit);
+
+MODULE_AUTHOR("Kumar Gala/Antoniou Pantelis");
+MODULE_DESCRIPTION("CPM SCC/SMC port driver $Revision: 0.01 $");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV(SERIAL_CPM_MAJOR, SERIAL_CPM_MINOR);
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
new file mode 100644 (file)
index 0000000..7c940b5
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ *  linux/drivers/serial/cpm_uart.c
+ *
+ *  Driver for CPM (SCC/SMC) serial ports; CPM1 definitions
+ *
+ *  Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
+ *              Pantelis Antoniou (panto@intracom.gr) (CPM1)
+ * 
+ *  Copyright (C) 2004 Freescale Semiconductor, Inc.
+ *            (C) 2004 Intracom, S.A.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/device.h>
+#include <linux/bootmem.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <linux/serial_core.h>
+#include <linux/kernel.h>
+
+#include "cpm_uart.h"
+
+/**************************************************************/
+
+void cpm_line_cr_cmd(int line, int cmd)
+{
+       ushort val;
+       volatile cpm8xx_t *cp = cpmp;
+
+       switch (line) {
+       case UART_SMC1:
+               val = mk_cr_cmd(CPM_CR_CH_SMC1, cmd) | CPM_CR_FLG;
+               break;
+       case UART_SMC2:
+               val = mk_cr_cmd(CPM_CR_CH_SMC2, cmd) | CPM_CR_FLG;
+               break;
+       case UART_SCC1:
+               val = mk_cr_cmd(CPM_CR_CH_SCC1, cmd) | CPM_CR_FLG;
+               break;
+       case UART_SCC2:
+               val = mk_cr_cmd(CPM_CR_CH_SCC2, cmd) | CPM_CR_FLG;
+               break;
+       case UART_SCC3:
+               val = mk_cr_cmd(CPM_CR_CH_SCC3, cmd) | CPM_CR_FLG;
+               break;
+       case UART_SCC4:
+               val = mk_cr_cmd(CPM_CR_CH_SCC4, cmd) | CPM_CR_FLG;
+               break;
+       default:
+               return;
+
+       }
+       cp->cp_cpcr = val;
+       while (cp->cp_cpcr & CPM_CR_FLG) ;
+}
+
+void smc1_lineif(struct uart_cpm_port *pinfo)
+{
+       volatile cpm8xx_t *cp = cpmp;
+
+       cp->cp_pbpar |= 0x000000c0;
+       cp->cp_pbdir &= ~0x000000c0;
+       cp->cp_pbodr &= ~0x000000c0;
+
+       pinfo->brg = 1;
+}
+
+void smc2_lineif(struct uart_cpm_port *pinfo)
+{
+       /* XXX SMC2: insert port configuration here */
+       pinfo->brg = 2;
+}
+
+void scc1_lineif(struct uart_cpm_port *pinfo)
+{
+       /* XXX SCC1: insert port configuration here */
+       pinfo->brg = 1;
+}
+
+void scc2_lineif(struct uart_cpm_port *pinfo)
+{
+       /* XXX SCC2: insert port configuration here */
+       pinfo->brg = 2;
+}
+
+void scc3_lineif(struct uart_cpm_port *pinfo)
+{
+       /* XXX SCC3: insert port configuration here */
+       pinfo->brg = 3;
+}
+
+void scc4_lineif(struct uart_cpm_port *pinfo)
+{
+       /* XXX SCC4: insert port configuration here */
+       pinfo->brg = 4;
+}
+
+/*
+ * Allocate DP-Ram and memory buffers. We need to allocate a transmit and 
+ * receive buffer descriptors from dual port ram, and a character
+ * buffer area from host mem. If we are allocating for the console we need
+ * to do it from bootmem
+ */
+int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
+{
+       int dpmemsz, memsz;
+       u8 *dp_mem;
+       uint dp_addr;
+       u8 *mem_addr;
+       dma_addr_t dma_addr;
+
+       pr_debug("CPM uart[%d]:allocbuf\n", pinfo->port.line);
+
+       dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos);
+       dp_mem = m8xx_cpm_dpalloc(dpmemsz);
+       if (dp_mem == NULL) {
+               printk(KERN_ERR
+                      "cpm_uart_cpm1.c: could not allocate buffer descriptors\n");
+               return -ENOMEM;
+       }
+       dp_addr = m8xx_cpm_dpram_offset(dp_mem);
+
+       memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
+           L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
+       if (is_con) {
+               mem_addr = (u8 *) m8xx_cpm_hostalloc(memsz);
+               dma_addr = 0;
+       } else
+               mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
+                                             GFP_KERNEL);
+
+       if (mem_addr == NULL) {
+               m8xx_cpm_dpfree(dp_mem);
+               printk(KERN_ERR
+                      "cpm_uart_cpm1.c: could not allocate coherent memory\n");
+               return -ENOMEM;
+       }
+
+       pinfo->dp_addr = dp_addr;
+       pinfo->mem_addr = mem_addr;
+       pinfo->dma_addr = dma_addr;
+
+       pinfo->rx_buf = mem_addr;
+       pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
+                                                      * pinfo->rx_fifosize);
+
+       pinfo->rx_bd_base = (volatile cbd_t *)dp_mem;
+       pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;
+
+       return 0;
+}
+
+void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
+{
+       dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
+                                              pinfo->rx_fifosize) +
+                         L1_CACHE_ALIGN(pinfo->tx_nrfifos *
+                                        pinfo->tx_fifosize), pinfo->mem_addr,
+                         pinfo->dma_addr);
+
+       m8xx_cpm_dpfree(m8xx_cpm_dpram_addr(pinfo->dp_addr));
+}
+
+/* Setup any dynamic params in the uart desc */
+int cpm_uart_init_portdesc(void)
+{
+       pr_debug("CPM uart[-]:init portdesc\n");
+
+       cpm_uart_nr = 0;
+#ifdef CONFIG_SERIAL_CPM_SMC1
+       cpm_uart_ports[UART_SMC1].smcp = &cpmp->cp_smc[0];
+       cpm_uart_ports[UART_SMC1].smcup =
+           (smc_uart_t *) & cpmp->cp_dparam[PROFF_SMC1];
+       cpm_uart_ports[UART_SMC1].port.mapbase =
+           (unsigned long)&cpmp->cp_smc[0];
+       cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
+       cpm_uart_ports[UART_SMC1].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+       cpm_uart_ports[UART_SMC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+       cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SMC2
+       cpm_uart_ports[UART_SMC2].smcp = &cpmp->cp_smc[1];
+       cpm_uart_ports[UART_SMC2].smcup =
+           (smc_uart_t *) & cpmp->cp_dparam[PROFF_SMC2];
+       cpm_uart_ports[UART_SMC2].port.mapbase =
+           (unsigned long)&cpmp->cp_smc[1];
+       cpm_uart_ports[UART_SMC2].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
+       cpm_uart_ports[UART_SMC2].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+       cpm_uart_ports[UART_SMC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+       cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC1
+       cpm_uart_ports[UART_SCC1].sccp = &cpmp->cp_scc[0];
+       cpm_uart_ports[UART_SCC1].sccup =
+           (scc_uart_t *) & cpmp->cp_dparam[PROFF_SCC1];
+       cpm_uart_ports[UART_SCC1].port.mapbase =
+           (unsigned long)&cpmp->cp_scc[0];
+       cpm_uart_ports[UART_SCC1].sccp->scc_sccm &=
+           ~(UART_SCCM_TX | UART_SCCM_RX);
+       cpm_uart_ports[UART_SCC1].sccp->scc_gsmrl &=
+           ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+       cpm_uart_ports[UART_SCC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+       cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC2
+       cpm_uart_ports[UART_SCC2].sccp = &cpmp->cp_scc[1];
+       cpm_uart_ports[UART_SCC2].sccup =
+           (scc_uart_t *) & cpmp->cp_dparam[PROFF_SCC2];
+       cpm_uart_ports[UART_SCC2].port.mapbase =
+           (unsigned long)&cpmp->cp_scc[1];
+       cpm_uart_ports[UART_SCC2].sccp->scc_sccm &=
+           ~(UART_SCCM_TX | UART_SCCM_RX);
+       cpm_uart_ports[UART_SCC2].sccp->scc_gsmrl &=
+           ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+       cpm_uart_ports[UART_SCC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+       cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC3
+       cpm_uart_ports[UART_SCC3].sccp = &cpmp->cp_scc[2];
+       cpm_uart_ports[UART_SCC3].sccup =
+           (scc_uart_t *) & cpmp->cp_dparam[PROFF_SCC3];
+       cpm_uart_ports[UART_SCC3].port.mapbase =
+           (unsigned long)&cpmp->cp_scc[2];
+       cpm_uart_ports[UART_SCC3].sccp->scc_sccm &=
+           ~(UART_SCCM_TX | UART_SCCM_RX);
+       cpm_uart_ports[UART_SCC3].sccp->scc_gsmrl &=
+           ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+       cpm_uart_ports[UART_SCC3].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+       cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC4
+       cpm_uart_ports[UART_SCC4].sccp = &cpmp->cp_scc[3];
+       cpm_uart_ports[UART_SCC4].sccup =
+           (scc_uart_t *) & cpmp->cp_dparam[PROFF_SCC4];
+       cpm_uart_ports[UART_SCC4].port.mapbase =
+           (unsigned long)&cpmp->cp_scc[3];
+       cpm_uart_ports[UART_SCC4].sccp->scc_sccm &=
+           ~(UART_SCCM_TX | UART_SCCM_RX);
+       cpm_uart_ports[UART_SCC4].sccp->scc_gsmrl &=
+           ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+       cpm_uart_ports[UART_SCC4].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+       cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4;
+#endif
+       return 0;
+}
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.h b/drivers/serial/cpm_uart/cpm_uart_cpm1.h
new file mode 100644 (file)
index 0000000..155050b
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * linux/drivers/serial/cpm_uart_cpm1.h
+ *
+ * Driver for CPM (SCC/SMC) serial ports
+ * 
+ * definitions for cpm1
+ *
+ */
+
+#ifndef CPM_UART_CPM1_H
+#define CPM_UART_CPM1_H
+
+#include <asm/commproc.h>
+
+/* defines for IRQs */
+#define SMC1_IRQ       (CPM_IRQ_OFFSET + CPMVEC_SMC1)
+#define SMC2_IRQ       (CPM_IRQ_OFFSET + CPMVEC_SMC2)
+#define SCC1_IRQ       (CPM_IRQ_OFFSET + CPMVEC_SCC1)
+#define SCC2_IRQ       (CPM_IRQ_OFFSET + CPMVEC_SCC2)
+#define SCC3_IRQ       (CPM_IRQ_OFFSET + CPMVEC_SCC3)
+#define SCC4_IRQ       (CPM_IRQ_OFFSET + CPMVEC_SCC4)
+
+/* the CPM address */
+#define CPM_ADDR       IMAP_ADDR
+
+static inline void cpm_set_brg(int brg, int baud)
+{
+       m8xx_cpm_setbrg(brg, baud);
+}
+
+static inline void cpm_set_scc_fcr(volatile scc_uart_t * sup)
+{
+       sup->scc_genscc.scc_rfcr = SMC_EB;
+       sup->scc_genscc.scc_tfcr = SMC_EB;
+}
+
+static inline void cpm_set_smc_fcr(volatile smc_uart_t * up)
+{
+       up->smc_rfcr = SMC_EB;
+       up->smc_tfcr = SMC_EB;
+}
+
+#define DPRAM_BASE     ((unsigned char *)&cpmp->cp_dpmem[0])
+
+#endif
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
new file mode 100644 (file)
index 0000000..d256688
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ *  linux/drivers/serial/cpm_uart_cpm2.c
+ *
+ *  Driver for CPM (SCC/SMC) serial ports; CPM2 definitions
+ *
+ *  Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
+ *              Pantelis Antoniou (panto@intracom.gr) (CPM1)
+ * 
+ *  Copyright (C) 2004 Freescale Semiconductor, Inc.
+ *            (C) 2004 Intracom, S.A.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/device.h>
+#include <linux/bootmem.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <linux/serial_core.h>
+#include <linux/kernel.h>
+
+#include "cpm_uart.h"
+
+/**************************************************************/
+
+void cpm_line_cr_cmd(int line, int cmd)
+{
+       volatile cpm_cpm2_t *cp = cpmp;
+       ulong val;
+
+       switch (line) {
+       case UART_SMC1:
+               val = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0,
+                               cmd) | CPM_CR_FLG;
+               break;
+       case UART_SMC2:
+               val = mk_cr_cmd(CPM_CR_SMC2_PAGE, CPM_CR_SMC2_SBLOCK, 0,
+                               cmd) | CPM_CR_FLG;
+               break;
+       case UART_SCC1:
+               val = mk_cr_cmd(CPM_CR_SCC1_PAGE, CPM_CR_SCC1_SBLOCK, 0,
+                               cmd) | CPM_CR_FLG;
+               break;
+       case UART_SCC2:
+               val = mk_cr_cmd(CPM_CR_SCC2_PAGE, CPM_CR_SCC2_SBLOCK, 0,
+                               cmd) | CPM_CR_FLG;
+               break;
+       case UART_SCC3:
+               val = mk_cr_cmd(CPM_CR_SCC3_PAGE, CPM_CR_SCC3_SBLOCK, 0,
+                               cmd) | CPM_CR_FLG;
+               break;
+       case UART_SCC4:
+               val = mk_cr_cmd(CPM_CR_SCC4_PAGE, CPM_CR_SCC4_SBLOCK, 0,
+                               cmd) | CPM_CR_FLG;
+               break;
+       default:
+               return;
+
+       }
+       cp->cp_cpcr = val;
+       while (cp->cp_cpcr & CPM_CR_FLG) ;
+}
+
+void smc1_lineif(struct uart_cpm_port *pinfo)
+{
+       volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+
+       /* SMC1 is only on port D */
+       io->iop_ppard |= 0x00c00000;
+       io->iop_pdird |= 0x00400000;
+       io->iop_pdird &= ~0x00800000;
+       io->iop_psord &= ~0x00c00000;
+
+       /* Wire BRG1 to SMC1 */
+       cpm2_immr->im_cpmux.cmx_smr &= 0x0f;
+       pinfo->brg = 1;
+}
+
+void smc2_lineif(struct uart_cpm_port *pinfo)
+{
+       volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+
+       /* SMC2 is only on port A */
+       io->iop_ppara |= 0x00c00000;
+       io->iop_pdira |= 0x00400000;
+       io->iop_pdira &= ~0x00800000;
+       io->iop_psora &= ~0x00c00000;
+
+       /* Wire BRG2 to SMC2 */
+       cpm2_immr->im_cpmux.cmx_smr &= 0xf0;
+       pinfo->brg = 2;
+}
+
+void scc1_lineif(struct uart_cpm_port *pinfo)
+{
+       volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+
+       /* Use Port D for SCC1 instead of other functions.  */
+       io->iop_ppard |= 0x00000003;
+       io->iop_psord &= ~0x00000001;   /* Rx */
+       io->iop_psord |= 0x00000002;    /* Tx */
+       io->iop_pdird &= ~0x00000001;   /* Rx */
+       io->iop_pdird |= 0x00000002;    /* Tx */
+
+       /* Wire BRG1 to SCC1 */
+       cpm2_immr->im_cpmux.cmx_scr &= ~0x00ffffff;
+       cpm2_immr->im_cpmux.cmx_scr |= 0x00000000;
+       pinfo->brg = 1;
+}
+
+void scc2_lineif(struct uart_cpm_port *pinfo)
+{
+       volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+       io->iop_pparb |= 0x008b0000;
+       io->iop_pdirb |= 0x00880000;
+       io->iop_psorb |= 0x00880000;
+       io->iop_pdirb &= ~0x00030000;
+       io->iop_psorb &= ~0x00030000;
+       cpm2_immr->im_cpmux.cmx_scr &= ~0xff00ffff;
+       cpm2_immr->im_cpmux.cmx_scr |= 0x00090000;
+       pinfo->brg = 2;
+}
+
+void scc3_lineif(struct uart_cpm_port *pinfo)
+{
+       volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+       io->iop_pparb |= 0x008b0000;
+       io->iop_pdirb |= 0x00880000;
+       io->iop_psorb |= 0x00880000;
+       io->iop_pdirb &= ~0x00030000;
+       io->iop_psorb &= ~0x00030000;
+       cpm2_immr->im_cpmux.cmx_scr &= ~0xffff00ff;
+       cpm2_immr->im_cpmux.cmx_scr |= 0x00001200;
+       pinfo->brg = 3;
+}
+
+void scc4_lineif(struct uart_cpm_port *pinfo)
+{
+       volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+
+       io->iop_ppard |= 0x00000600;
+       io->iop_psord &= ~0x00000600;   /* Tx/Rx */
+       io->iop_pdird &= ~0x00000200;   /* Rx */
+       io->iop_pdird |= 0x00000400;    /* Tx */
+
+       cpm2_immr->im_cpmux.cmx_scr &= ~0xffffff00;
+       cpm2_immr->im_cpmux.cmx_scr |= 0x0000001b;
+       pinfo->brg = 4;
+}
+
+/*
+ * Allocate DP-Ram and memory buffers. We need to allocate a transmit and 
+ * receive buffer descriptors from dual port ram, and a character
+ * buffer area from host mem. If we are allocating for the console we need
+ * to do it from bootmem
+ */
+int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
+{
+       int dpmemsz, memsz;
+       u8 *dp_mem;
+       uint dp_addr;
+       u8 *mem_addr;
+       dma_addr_t dma_addr = 0;
+
+       pr_debug("CPM uart[%d]:allocbuf\n", pinfo->port.line);
+
+       dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos);
+       dp_mem = cpm2_dpalloc(dpmemsz, 8);
+       if (dp_mem == NULL) {
+               printk(KERN_ERR
+                      "cpm_uart_cpm1.c: could not allocate buffer descriptors\n");
+               return -ENOMEM;
+       }
+
+       dp_addr = cpm2_dpram_offset(dp_mem);
+
+       memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
+           L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
+       if (is_con)
+               mem_addr = alloc_bootmem(memsz);
+       else
+               mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
+                                             GFP_KERNEL);
+
+       if (mem_addr == NULL) {
+               cpm2_dpfree(dp_mem);
+               printk(KERN_ERR
+                      "cpm_uart_cpm1.c: could not allocate coherent memory\n");
+               return -ENOMEM;
+       }
+
+       pinfo->dp_addr = dp_addr;
+       pinfo->mem_addr = mem_addr;
+       pinfo->dma_addr = dma_addr;
+
+       pinfo->rx_buf = mem_addr;
+       pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
+                                                      * pinfo->rx_fifosize);
+
+       pinfo->rx_bd_base = (volatile cbd_t *)dp_mem;
+       pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;
+
+       return 0;
+}
+
+void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
+{
+       dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
+                                              pinfo->rx_fifosize) +
+                         L1_CACHE_ALIGN(pinfo->tx_nrfifos *
+                                        pinfo->tx_fifosize), pinfo->mem_addr,
+                         pinfo->dma_addr);
+
+       cpm2_dpfree(&pinfo->dp_addr);
+}
+
+/* Setup any dynamic params in the uart desc */
+int cpm_uart_init_portdesc(void)
+{
+       pr_debug("CPM uart[-]:init portdesc\n");
+
+       cpm_uart_nr = 0;
+#ifdef CONFIG_SERIAL_CPM_SMC1
+       cpm_uart_ports[UART_SMC1].smcp = (smc_t *) & cpm2_immr->im_smc[0];
+       cpm_uart_ports[UART_SMC1].smcup =
+           (smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC1];
+       cpm_uart_ports[UART_SMC1].port.mapbase =
+           (unsigned long)&cpm2_immr->im_smc[0];
+       cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
+       cpm_uart_ports[UART_SMC1].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+       cpm_uart_ports[UART_SMC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+       cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SMC2
+       cpm_uart_ports[UART_SMC2].smcp = (smc_t *) & cpm2_immr->im_smc[1];
+       cpm_uart_ports[UART_SMC2].smcup =
+           (smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC2];
+       cpm_uart_ports[UART_SMC2].port.mapbase =
+           (unsigned long)&cpm2_immr->im_smc[1];
+       cpm_uart_ports[UART_SMC2].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
+       cpm_uart_ports[UART_SMC2].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+       cpm_uart_ports[UART_SMC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+       cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC1
+       cpm_uart_ports[UART_SCC1].sccp = (scc_t *) & cpm2_immr->im_scc[0];
+       cpm_uart_ports[UART_SCC1].sccup =
+           (scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC1];
+       cpm_uart_ports[UART_SCC1].port.mapbase =
+           (unsigned long)&cpm2_immr->im_scc[0];
+       cpm_uart_ports[UART_SCC1].sccp->scc_sccm &=
+           ~(UART_SCCM_TX | UART_SCCM_RX);
+       cpm_uart_ports[UART_SCC1].sccp->scc_gsmrl &=
+           ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+       cpm_uart_ports[UART_SCC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+       cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC2
+       cpm_uart_ports[UART_SCC2].sccp = (scc_t *) & cpm2_immr->im_scc[1];
+       cpm_uart_ports[UART_SCC2].sccup =
+           (scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC2];
+       cpm_uart_ports[UART_SCC2].port.mapbase =
+           (unsigned long)&cpm2_immr->im_scc[1];
+       cpm_uart_ports[UART_SCC2].sccp->scc_sccm &=
+           ~(UART_SCCM_TX | UART_SCCM_RX);
+       cpm_uart_ports[UART_SCC2].sccp->scc_gsmrl &=
+           ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+       cpm_uart_ports[UART_SCC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+       cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC3
+       cpm_uart_ports[UART_SCC3].sccp = (scc_t *) & cpm2_immr->im_scc[2];
+       cpm_uart_ports[UART_SCC3].sccup =
+           (scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC3];
+       cpm_uart_ports[UART_SCC3].port.mapbase =
+           (unsigned long)&cpm2_immr->im_scc[2];
+       cpm_uart_ports[UART_SCC3].sccp->scc_sccm &=
+           ~(UART_SCCM_TX | UART_SCCM_RX);
+       cpm_uart_ports[UART_SCC3].sccp->scc_gsmrl &=
+           ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+       cpm_uart_ports[UART_SCC3].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+       cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC4
+       cpm_uart_ports[UART_SCC4].sccp = (scc_t *) & cpm2_immr->im_scc[3];
+       cpm_uart_ports[UART_SCC4].sccup =
+           (scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC4];
+       cpm_uart_ports[UART_SCC4].port.mapbase =
+           (unsigned long)&cpm2_immr->im_scc[3];
+       cpm_uart_ports[UART_SCC4].sccp->scc_sccm &=
+           ~(UART_SCCM_TX | UART_SCCM_RX);
+       cpm_uart_ports[UART_SCC4].sccp->scc_gsmrl &=
+           ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+       cpm_uart_ports[UART_SCC4].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+       cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4;
+#endif
+
+       return 0;
+}
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.h b/drivers/serial/cpm_uart/cpm_uart_cpm2.h
new file mode 100644 (file)
index 0000000..eb620bd
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * linux/drivers/serial/cpm_uart_cpm2.h
+ *
+ * Driver for CPM (SCC/SMC) serial ports
+ * 
+ * definitions for cpm2
+ *
+ */
+
+#ifndef CPM_UART_CPM2_H
+#define CPM_UART_CPM2_H
+
+#include <asm/cpm2.h>
+
+/* defines for IRQs */
+#define SMC1_IRQ       SIU_INT_SMC1
+#define SMC2_IRQ       SIU_INT_SMC2
+#define SCC1_IRQ       SIU_INT_SCC1
+#define SCC2_IRQ       SIU_INT_SCC2
+#define SCC3_IRQ       SIU_INT_SCC3
+#define SCC4_IRQ       SIU_INT_SCC4
+
+/* the CPM address */
+#define CPM_ADDR       CPM_MAP_ADDR
+
+static inline void cpm_set_brg(int brg, int baud)
+{
+       cpm2_setbrg(brg, baud);
+}
+
+static inline void cpm_set_scc_fcr(volatile scc_uart_t * sup)
+{
+       sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+       sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+}
+
+static inline void cpm_set_smc_fcr(volatile smc_uart_t * up)
+{
+       up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+       up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+}
+
+#define DPRAM_BASE     ((unsigned char *)&cpm2_immr->im_dprambase[0])
+
+#endif
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
new file mode 100644 (file)
index 0000000..f416b64
--- /dev/null
@@ -0,0 +1,31 @@
+menu "Dallas's 1-wire bus"
+
+config W1
+       tristate "Dallas's 1-wire support"
+       ---help---
+         Dallas's 1-wire bus is usefull to connect slow 1-pin devices 
+         such as iButtons and thermal sensors.
+         
+         If you want W1 support, you should say Y here.
+
+         This W1 support can also be built as a module.  If so, the module
+         will be called wire.ko.
+
+config W1_MATROX
+       tristate "Matrox G400 transport layer for 1-wire"
+       depends on W1
+       help
+         Say Y here if you want to communicate with your 1-wire devices
+         using Matrox's G400 GPIO pins.
+         
+         This support is also available as a module.  If so, the module 
+         will be called matrox_w1.ko.
+
+config W1_THERM
+       tristate "Thermal family implementation"
+       depends on W1
+       help
+         Say Y here if you want to connect 1-wire thermal sensors to you
+         wire.
+
+endmenu
diff --git a/drivers/w1/matrox_w1.c b/drivers/w1/matrox_w1.c
new file mode 100644 (file)
index 0000000..55b1faf
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ *     matrox_w1.c
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <asm/atomic.h>
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/pci_ids.h>
+#include <linux/pci.h>
+#include <linux/timer.h>
+
+#include "w1.h"
+#include "w1_int.h"
+#include "w1_log.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_DESCRIPTION("Driver for transport(Dallas 1-wire prtocol) over VGA DDC(matrox gpio).");
+
+static struct pci_device_id matrox_w1_tbl[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400) },
+       { },
+};
+MODULE_DEVICE_TABLE(pci, matrox_w1_tbl);
+
+static int __devinit matrox_w1_probe(struct pci_dev *, const struct pci_device_id *);
+static void __devexit matrox_w1_remove(struct pci_dev *);
+
+static struct pci_driver matrox_w1_pci_driver = {
+       .name = "matrox_w1",
+       .id_table = matrox_w1_tbl,
+       .probe = matrox_w1_probe,
+       .remove = __devexit_p(matrox_w1_remove),
+};
+
+/* 
+ * Matrox G400 DDC registers.
+ */
+
+#define MATROX_G400_DDC_CLK            (1<<4)
+#define MATROX_G400_DDC_DATA           (1<<1)
+
+#define MATROX_BASE                    0x3C00
+#define MATROX_STATUS                  0x1e14
+
+#define MATROX_PORT_INDEX_OFFSET       0x00
+#define MATROX_PORT_DATA_OFFSET                0x0A
+
+#define MATROX_GET_CONTROL             0x2A
+#define MATROX_GET_DATA                        0x2B
+#define MATROX_CURSOR_CTL              0x06
+
+struct matrox_device
+{
+       unsigned long base_addr;
+       unsigned long port_index, port_data;
+       u8 data_mask;
+
+       unsigned long phys_addr, virt_addr;
+       unsigned long found;
+
+       struct w1_bus_master *bus_master;
+};
+
+static u8 matrox_w1_read_ddc_bit(unsigned long);
+static void matrox_w1_write_ddc_bit(unsigned long, u8);
+
+/*
+ * These functions read and write DDC Data bit.
+ *
+ * Using tristate pins, since i can't  fin any open-drain pin in whole motherboard.
+ * Unfortunately we can't connect to Intel's 82801xx IO controller
+ * since we don't know motherboard schema, wich has pretty unused(may be not) GPIO.
+ *
+ * I've heard that PIIX also has open drain pin.
+ *
+ * Port mapping.
+ */
+static __inline__ u8 matrox_w1_read_reg(struct matrox_device *dev, u8 reg)
+{
+       u8 ret;
+
+       writeb(reg, dev->port_index);
+       ret = readb(dev->port_data);
+       barrier();
+
+       return ret;
+}
+
+static __inline__ void matrox_w1_write_reg(struct matrox_device *dev, u8 reg, u8 val)
+{
+       writeb(reg, dev->port_index);
+       writeb(val, dev->port_data);
+       wmb();
+}
+
+static void matrox_w1_write_ddc_bit(unsigned long data, u8 bit)
+{
+       u8 ret;
+       struct matrox_device *dev = (struct matrox_device *) data;
+
+       if (bit)
+               bit = 0;
+       else
+               bit = dev->data_mask;
+
+       ret = matrox_w1_read_reg(dev, MATROX_GET_CONTROL);
+       matrox_w1_write_reg(dev, MATROX_GET_CONTROL, ((ret & ~dev->data_mask) | bit));
+       matrox_w1_write_reg(dev, MATROX_GET_DATA, 0x00);
+}
+
+static u8 matrox_w1_read_ddc_bit(unsigned long data)
+{
+       u8 ret;
+       struct matrox_device *dev = (struct matrox_device *) data;
+
+       ret = matrox_w1_read_reg(dev, MATROX_GET_DATA);
+
+       return ret;
+}
+
+static void matrox_w1_hw_init(struct matrox_device *dev)
+{
+       matrox_w1_write_reg(dev, MATROX_GET_DATA, 0xFF);
+       matrox_w1_write_reg(dev, MATROX_GET_CONTROL, 0x00);
+}
+
+static int __devinit matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       struct matrox_device *dev;
+       int err;
+
+       assert(pdev != NULL);
+       assert(ent != NULL);
+
+       if (pdev->vendor != PCI_VENDOR_ID_MATROX || pdev->device != PCI_DEVICE_ID_MATROX_G400)
+               return -ENODEV;
+
+       dev = kmalloc(sizeof(struct matrox_device) +
+                      sizeof(struct w1_bus_master), GFP_KERNEL);
+       if (!dev) {
+               dev_err(&pdev->dev,
+                       "%s: Failed to create new matrox_device object.\n",
+                       __func__);
+               return -ENOMEM;
+       }
+
+       memset(dev, 0, sizeof(struct matrox_device) + sizeof(struct w1_bus_master));
+
+       dev->bus_master = (struct w1_bus_master *)(dev + 1);
+
+       /* 
+        * True for G400, for some other we need resource 0, see drivers/video/matrox/matroxfb_base.c 
+        */
+
+       dev->phys_addr = pci_resource_start(pdev, 1);
+
+       dev->virt_addr =
+               (unsigned long) ioremap_nocache(dev->phys_addr, 16384);
+       if (!dev->virt_addr) {
+               dev_err(&pdev->dev, "%s: failed to ioremap(0x%lx, %d).\n",
+                       __func__, dev->phys_addr, 16384);
+               err = -EIO;
+               goto err_out_free_device;
+       }
+
+       dev->base_addr = dev->virt_addr + MATROX_BASE;
+       dev->port_index = dev->base_addr + MATROX_PORT_INDEX_OFFSET;
+       dev->port_data = dev->base_addr + MATROX_PORT_DATA_OFFSET;
+       dev->data_mask = (MATROX_G400_DDC_DATA);
+
+       matrox_w1_hw_init(dev);
+
+       dev->bus_master->data = (unsigned long) dev;
+       dev->bus_master->read_bit = &matrox_w1_read_ddc_bit;
+       dev->bus_master->write_bit = &matrox_w1_write_ddc_bit;
+
+       err = w1_add_master_device(dev->bus_master);
+       if (err)
+               goto err_out_free_device;
+
+       pci_set_drvdata(pdev, dev);
+
+       dev->found = 1;
+
+       dev_info(&pdev->dev, "Matrox G400 GPIO transport layer for 1-wire.\n");
+
+       return 0;
+
+err_out_free_device:
+       kfree(dev);
+
+       return err;
+}
+
+static void __devexit matrox_w1_remove(struct pci_dev *pdev)
+{
+       struct matrox_device *dev = pci_get_drvdata(pdev);
+
+       assert(dev != NULL);
+
+       if (dev->found) {
+               w1_remove_master_device(dev->bus_master);
+               iounmap((void *) dev->virt_addr);
+       }
+       kfree(dev);
+}
+
+static int __init matrox_w1_init(void)
+{
+       return pci_module_init(&matrox_w1_pci_driver);
+}
+
+static void __exit matrox_w1_fini(void)
+{
+       pci_unregister_driver(&matrox_w1_pci_driver);
+}
+
+module_init(matrox_w1_init);
+module_exit(matrox_w1_fini);
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
new file mode 100644 (file)
index 0000000..d956f5e
--- /dev/null
@@ -0,0 +1,623 @@
+/*
+ *     w1.c
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <asm/atomic.h>
+#include <asm/delay.h>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/suspend.h>
+
+#include "w1.h"
+#include "w1_io.h"
+#include "w1_log.h"
+#include "w1_int.h"
+#include "w1_family.h"
+#include "w1_netlink.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol.");
+
+static int w1_timeout = 5 * HZ;
+int w1_max_slave_count = 10;
+
+module_param_named(timeout, w1_timeout, int, 0);
+module_param_named(max_slave_count, w1_max_slave_count, int, 0);
+
+spinlock_t w1_mlock = SPIN_LOCK_UNLOCKED;
+LIST_HEAD(w1_masters);
+
+static pid_t control_thread;
+static int control_needs_exit;
+static DECLARE_COMPLETION(w1_control_complete);
+static DECLARE_WAIT_QUEUE_HEAD(w1_control_wait);
+
+static int w1_master_match(struct device *dev, struct device_driver *drv)
+{
+       return 1;
+}
+
+static int w1_master_probe(struct device *dev)
+{
+       return -ENODEV;
+}
+
+static int w1_master_remove(struct device *dev)
+{
+       return 0;
+}
+
+static void w1_master_release(struct device *dev)
+{
+       struct w1_master *md = container_of(dev, struct w1_master, dev);
+
+       complete(&md->dev_released);
+}
+
+static void w1_slave_release(struct device *dev)
+{
+       struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+
+       complete(&sl->dev_released);
+}
+
+static ssize_t w1_default_read_name(struct device *dev, char *buf)
+{
+       return sprintf(buf, "No family registered.\n");
+}
+
+static ssize_t w1_default_read_bin(struct kobject *kobj, char *buf, loff_t off,
+                    size_t count)
+{
+       return sprintf(buf, "No family registered.\n");
+}
+
+struct bus_type w1_bus_type = {
+       .name = "w1",
+       .match = w1_master_match,
+};
+
+struct device_driver w1_driver = {
+       .name = "w1_driver",
+       .bus = &w1_bus_type,
+       .probe = w1_master_probe,
+       .remove = w1_master_remove,
+};
+
+struct device w1_device = {
+       .parent = NULL,
+       .bus = &w1_bus_type,
+       .bus_id = "w1 bus master",
+       .driver = &w1_driver,
+       .release = &w1_master_release
+};
+
+static struct device_attribute w1_slave_attribute = {
+       .attr = {
+                       .name = "name",
+                       .mode = S_IRUGO,
+                       .owner = THIS_MODULE
+       },
+       .show = &w1_default_read_name,
+};
+
+static struct device_attribute w1_slave_attribute_val = {
+       .attr = {
+                       .name = "value",
+                       .mode = S_IRUGO,
+                       .owner = THIS_MODULE
+       },
+       .show = &w1_default_read_name,
+};
+
+static ssize_t w1_master_attribute_show(struct device *dev, char *buf)
+{
+       return sprintf(buf, "please fix me\n");
+#if 0
+       struct w1_master *md = container_of(dev, struct w1_master, dev);
+       int c = PAGE_SIZE;
+
+       if (down_interruptible(&md->mutex))
+               return -EBUSY;
+
+       c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", md->name);
+       c -= snprintf(buf + PAGE_SIZE - c, c,
+                      "bus_master=0x%p, timeout=%d, max_slave_count=%d, attempts=%lu\n",
+                      md->bus_master, w1_timeout, md->max_slave_count,
+                      md->attempts);
+       c -= snprintf(buf + PAGE_SIZE - c, c, "%d slaves: ",
+                      md->slave_count);
+       if (md->slave_count == 0)
+               c -= snprintf(buf + PAGE_SIZE - c, c, "no.\n");
+       else {
+               struct list_head *ent, *n;
+               struct w1_slave *sl;
+
+               list_for_each_safe(ent, n, &md->slist) {
+                       sl = list_entry(ent, struct w1_slave, w1_slave_entry);
+
+                       c -= snprintf(buf + PAGE_SIZE - c, c, "%s[%p] ",
+                                      sl->name, sl);
+               }
+               c -= snprintf(buf + PAGE_SIZE - c, c, "\n");
+       }
+
+       up(&md->mutex);
+
+       return PAGE_SIZE - c;
+#endif
+}
+
+struct device_attribute w1_master_attribute = {
+       .attr = {
+                       .name = "w1_master_stats",
+                       .mode = S_IRUGO,
+                       .owner = THIS_MODULE,
+       },
+       .show = &w1_master_attribute_show,
+};
+
+static struct bin_attribute w1_slave_bin_attribute = {
+       .attr = {
+                       .name = "w1_slave",
+                       .mode = S_IRUGO,
+                       .owner = THIS_MODULE,
+       },
+       .size = W1_SLAVE_DATA_SIZE,
+       .read = &w1_default_read_bin,
+};
+
+static int __w1_attach_slave_device(struct w1_slave *sl)
+{
+       int err;
+
+       sl->dev.parent = &sl->master->dev;
+       sl->dev.driver = sl->master->driver;
+       sl->dev.bus = &w1_bus_type;
+       sl->dev.release = &w1_slave_release;
+
+       snprintf(&sl->dev.bus_id[0], sizeof(sl->dev.bus_id),
+                 "%x-%llx",
+                 (unsigned int) sl->reg_num.family,
+                 (unsigned long long) sl->reg_num.id);
+       snprintf (&sl->name[0], sizeof(sl->name),
+                 "%x-%llx",
+                 (unsigned int) sl->reg_num.family,
+                 (unsigned long long) sl->reg_num.id);
+
+       dev_dbg(&sl->dev, "%s: registering %s.\n", __func__,
+               &sl->dev.bus_id[0]);
+
+       err = device_register(&sl->dev);
+       if (err < 0) {
+               dev_err(&sl->dev,
+                        "Device registration [%s] failed. err=%d\n",
+                        sl->dev.bus_id, err);
+               return err;
+       }
+
+       w1_slave_bin_attribute.read = sl->family->fops->rbin;
+       w1_slave_attribute.show = sl->family->fops->rname;
+       w1_slave_attribute_val.show = sl->family->fops->rval;
+       w1_slave_attribute_val.attr.name = sl->family->fops->rvalname;
+
+       err = device_create_file(&sl->dev, &w1_slave_attribute);
+       if (err < 0) {
+               dev_err(&sl->dev,
+                        "sysfs file creation for [%s] failed. err=%d\n",
+                        sl->dev.bus_id, err);
+               device_unregister(&sl->dev);
+               return err;
+       }
+
+       err = device_create_file(&sl->dev, &w1_slave_attribute_val);
+       if (err < 0) {
+               dev_err(&sl->dev,
+                        "sysfs file creation for [%s] failed. err=%d\n",
+                        sl->dev.bus_id, err);
+               device_remove_file(&sl->dev, &w1_slave_attribute);
+               device_unregister(&sl->dev);
+               return err;
+       }
+
+       err = sysfs_create_bin_file(&sl->dev.kobj, &w1_slave_bin_attribute);
+       if (err < 0) {
+               dev_err(&sl->dev,
+                        "sysfs file creation for [%s] failed. err=%d\n",
+                        sl->dev.bus_id, err);
+               device_remove_file(&sl->dev, &w1_slave_attribute);
+               device_remove_file(&sl->dev, &w1_slave_attribute_val);
+               device_unregister(&sl->dev);
+               return err;
+       }
+
+       list_add_tail(&sl->w1_slave_entry, &sl->master->slist);
+
+       return 0;
+}
+
+static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
+{
+       struct w1_slave *sl;
+       struct w1_family *f;
+       int err;
+
+       sl = kmalloc(sizeof(struct w1_slave), GFP_KERNEL);
+       if (!sl) {
+               dev_err(&dev->dev,
+                        "%s: failed to allocate new slave device.\n",
+                        __func__);
+               return -ENOMEM;
+       }
+
+       memset(sl, 0, sizeof(*sl));
+
+       sl->owner = THIS_MODULE;
+       sl->master = dev;
+
+       memcpy(&sl->reg_num, rn, sizeof(sl->reg_num));
+       atomic_set(&sl->refcnt, 0);
+       init_completion(&sl->dev_released);
+
+       spin_lock(&w1_flock);
+       f = w1_family_registered(rn->family);
+       if (!f) {
+               spin_unlock(&w1_flock);
+               dev_info(&dev->dev, "Family %x is not registered.\n",
+                         rn->family);
+               kfree(sl);
+               return -ENODEV;
+       }
+       __w1_family_get(f);
+       spin_unlock(&w1_flock);
+
+       sl->family = f;
+
+
+       err = __w1_attach_slave_device(sl);
+       if (err < 0) {
+               dev_err(&dev->dev, "%s: Attaching %s failed.\n", __func__,
+                        sl->name);
+               w1_family_put(sl->family);
+               kfree(sl);
+               return err;
+       }
+
+       dev->slave_count++;
+
+       return 0;
+}
+
+static void w1_slave_detach(struct w1_slave *sl)
+{
+       dev_info(&sl->dev, "%s: detaching %s.\n", __func__, sl->name);
+
+       while (atomic_read(&sl->refcnt))
+               schedule_timeout(10);
+
+       sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_bin_attribute);
+       device_remove_file(&sl->dev, &w1_slave_attribute);
+       device_unregister(&sl->dev);
+       w1_family_put(sl->family);
+}
+
+static void w1_search(struct w1_master *dev)
+{
+       u64 last, rn, tmp;
+       int i, count = 0, slave_count;
+       int last_family_desc, last_zero, last_device;
+       int search_bit, id_bit, comp_bit, desc_bit;
+       struct list_head *ent;
+       struct w1_slave *sl;
+       int family_found = 0;
+       struct w1_netlink_msg msg;
+
+       dev->attempts++;
+
+       memset(&msg, 0, sizeof(msg));
+
+       search_bit = id_bit = comp_bit = 0;
+       rn = tmp = last = 0;
+       last_device = last_zero = last_family_desc = 0;
+
+       desc_bit = 64;
+
+       while (!(id_bit && comp_bit) && !last_device
+               && count++ < dev->max_slave_count) {
+               last = rn;
+               rn = 0;
+
+               last_family_desc = 0;
+
+               /*
+                * Reset bus and all 1-wire device state machines
+                * so they can respond to our requests.
+                *
+                * Return 0 - device(s) present, 1 - no devices present.
+                */
+               if (w1_reset_bus(dev)) {
+                       dev_info(&dev->dev, "No devices present on the wire.\n");
+                       break;
+               }
+
+#if 1
+               memset(&msg, 0, sizeof(msg));
+
+               w1_write_8(dev, W1_SEARCH);
+               for (i = 0; i < 64; ++i) {
+                       /*
+                        * Read 2 bits from bus.
+                        * All who don't sleep must send ID bit and COMPLEMENT ID bit.
+                        * They actually are ANDed between all senders.
+                        */
+                       id_bit = w1_read_bit(dev);
+                       comp_bit = w1_read_bit(dev);
+
+                       if (id_bit && comp_bit)
+                               break;
+
+                       if (id_bit == 0 && comp_bit == 0) {
+                               if (i == desc_bit)
+                                       search_bit = 1;
+                               else if (i > desc_bit)
+                                       search_bit = 0;
+                               else
+                                       search_bit = ((last >> i) & 0x1);
+
+                               if (search_bit == 0) {
+                                       last_zero = i;
+                                       if (last_zero < 9)
+                                               last_family_desc = last_zero;
+                               }
+
+                       }
+                       else
+                               search_bit = id_bit;
+
+                       tmp = search_bit;
+                       rn |= (tmp << i);
+
+                       /*
+                        * Write 1 bit to bus
+                        * and make all who don't have "search_bit" in "i"'th position
+                        * in it's registration number sleep.
+                        */
+                       w1_write_bit(dev, search_bit);
+
+               }
+#endif
+               msg.id.w1_id = rn;
+               msg.val = w1_calc_crc8((u8 *) & rn, 7);
+               w1_netlink_send(dev, &msg);
+
+               if (desc_bit == last_zero)
+                       last_device = 1;
+
+               desc_bit = last_zero;
+
+               slave_count = 0;
+               list_for_each(ent, &dev->slist) {
+                       struct w1_reg_num *tmp;
+
+                       tmp = (struct w1_reg_num *) &rn;
+
+                       sl = list_entry(ent, struct w1_slave, w1_slave_entry);
+
+                       if (sl->reg_num.family == tmp->family &&
+                           sl->reg_num.id == tmp->id &&
+                           sl->reg_num.crc == tmp->crc)
+                               break;
+                       else if (sl->reg_num.family == tmp->family) {
+                               family_found = 1;
+                               break;
+                       }
+
+                       slave_count++;
+               }
+
+               if (slave_count == dev->slave_count &&
+                   msg.val && (*((__u8 *) & msg.val) == msg.id.id.crc)) {
+                       w1_attach_slave_device(dev, (struct w1_reg_num *) &rn);
+               }
+       }
+}
+
+int w1_control(void *data)
+{
+       struct w1_slave *sl;
+       struct w1_master *dev;
+       struct list_head *ent, *ment, *n, *mn;
+       int err, have_to_wait = 0, timeout;
+
+       daemonize("w1_control");
+       allow_signal(SIGTERM);
+
+       while (!control_needs_exit || have_to_wait) {
+               have_to_wait = 0;
+
+               timeout = w1_timeout;
+               do {
+                       timeout = interruptible_sleep_on_timeout(&w1_control_wait, timeout);
+                       if (current->flags & PF_FREEZE)
+                               refrigerator(PF_FREEZE);
+               } while (!signal_pending(current) && (timeout > 0));
+
+               if (signal_pending(current))
+                       flush_signals(current);
+
+               list_for_each_safe(ment, mn, &w1_masters) {
+                       dev = list_entry(ment, struct w1_master, w1_master_entry);
+
+                       if (!control_needs_exit && !dev->need_exit)
+                               continue;
+                       /*
+                        * Little race: we can create thread but not set the flag.
+                        * Get a chance for external process to set flag up.
+                        */
+                       if (!dev->initialized) {
+                               have_to_wait = 1;
+                               continue;
+                       }
+
+                       spin_lock(&w1_mlock);
+                       list_del(&dev->w1_master_entry);
+                       spin_unlock(&w1_mlock);
+
+                       if (control_needs_exit) {
+                               dev->need_exit = 1;
+
+                               err = kill_proc(dev->kpid, SIGTERM, 1);
+                               if (err)
+                                       dev_err(&dev->dev,
+                                                "Failed to send signal to w1 kernel thread %d.\n",
+                                                dev->kpid);
+                       }
+
+                       wait_for_completion(&dev->dev_exited);
+
+                       list_for_each_safe(ent, n, &dev->slist) {
+                               sl = list_entry(ent, struct w1_slave, w1_slave_entry);
+
+                               if (!sl)
+                                       dev_warn(&dev->dev,
+                                                 "%s: slave entry is NULL.\n",
+                                                 __func__);
+                               else {
+                                       list_del(&sl->w1_slave_entry);
+
+                                       w1_slave_detach(sl);
+                                       kfree(sl);
+                               }
+                       }
+                       device_remove_file(&dev->dev, &w1_master_attribute);
+                       atomic_dec(&dev->refcnt);
+               }
+       }
+
+       complete_and_exit(&w1_control_complete, 0);
+}
+
+int w1_process(void *data)
+{
+       struct w1_master *dev = (struct w1_master *) data;
+       unsigned long timeout;
+
+       daemonize("%s", dev->name);
+       allow_signal(SIGTERM);
+
+       while (!dev->need_exit) {
+               timeout = w1_timeout;
+               do {
+                       timeout = interruptible_sleep_on_timeout(&dev->kwait, timeout);
+                       if (current->flags & PF_FREEZE)
+                               refrigerator(PF_FREEZE);
+               } while (!signal_pending(current) && (timeout > 0));
+
+               if (signal_pending(current))
+                       flush_signals(current);
+
+               if (dev->need_exit)
+                       break;
+
+               if (!dev->initialized)
+                       continue;
+
+               if (down_interruptible(&dev->mutex))
+                       continue;
+               w1_search(dev);
+               up(&dev->mutex);
+       }
+
+       atomic_dec(&dev->refcnt);
+       complete_and_exit(&dev->dev_exited, 0);
+
+       return 0;
+}
+
+int w1_init(void)
+{
+       int retval;
+
+       printk(KERN_INFO "Driver for 1-wire Dallas network protocol.\n");
+
+       retval = bus_register(&w1_bus_type);
+       if (retval) {
+               printk(KERN_ERR "Failed to register bus. err=%d.\n", retval);
+               goto err_out_exit_init;
+       }
+
+       retval = driver_register(&w1_driver);
+       if (retval) {
+               printk(KERN_ERR
+                       "Failed to register master driver. err=%d.\n",
+                       retval);
+               goto err_out_bus_unregister;
+       }
+
+       control_thread = kernel_thread(&w1_control, NULL, 0);
+       if (control_thread < 0) {
+               printk(KERN_ERR "Failed to create control thread. err=%d\n",
+                       control_thread);
+               retval = control_thread;
+               goto err_out_driver_unregister;
+       }
+
+       return 0;
+
+err_out_driver_unregister:
+       driver_unregister(&w1_driver);
+
+err_out_bus_unregister:
+       bus_unregister(&w1_bus_type);
+
+err_out_exit_init:
+       return retval;
+}
+
+void w1_fini(void)
+{
+       struct w1_master *dev;
+       struct list_head *ent, *n;
+
+       list_for_each_safe(ent, n, &w1_masters) {
+               dev = list_entry(ent, struct w1_master, w1_master_entry);
+               __w1_remove_master_device(dev);
+       }
+
+       control_needs_exit = 1;
+
+       wait_for_completion(&w1_control_complete);
+
+       driver_unregister(&w1_driver);
+       bus_unregister(&w1_bus_type);
+}
+
+module_init(w1_init);
+module_exit(w1_fini);
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
new file mode 100644 (file)
index 0000000..291a6d1
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ *     w1_int.c
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+
+#include "w1.h"
+#include "w1_log.h"
+
+static u32 w1_ids = 1;
+
+extern struct device_driver w1_driver;
+extern struct bus_type w1_bus_type;
+extern struct device w1_device;
+extern struct device_attribute w1_master_attribute;
+extern int w1_max_slave_count;
+extern struct list_head w1_masters;
+extern spinlock_t w1_mlock;
+
+extern int w1_process(void *);
+
+struct w1_master * w1_alloc_dev(u32 id, int slave_count,
+             struct device_driver *driver, struct device *device)
+{
+       struct w1_master *dev;
+       int err;
+
+       /*
+        * We are in process context(kernel thread), so can sleep.
+        */
+       dev = kmalloc(sizeof(struct w1_master) + sizeof(struct w1_bus_master), GFP_KERNEL);
+       if (!dev) {
+               printk(KERN_ERR
+                       "Failed to allocate %d bytes for new w1 device.\n",
+                       sizeof(struct w1_master));
+               return NULL;
+       }
+
+       memset(dev, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master));
+
+       dev->bus_master = (struct w1_bus_master *)(dev + 1);
+
+       dev->owner              = THIS_MODULE;
+       dev->max_slave_count    = slave_count;
+       dev->slave_count        = 0;
+       dev->attempts           = 0;
+       dev->kpid               = -1;
+       dev->initialized        = 0;
+       dev->id                 = id;
+
+       atomic_set(&dev->refcnt, 2);
+
+       INIT_LIST_HEAD(&dev->slist);
+       init_MUTEX(&dev->mutex);
+
+       init_waitqueue_head(&dev->kwait);
+       init_completion(&dev->dev_released);
+       init_completion(&dev->dev_exited);
+
+       memcpy(&dev->dev, device, sizeof(struct device));
+       snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
+                 "w1_bus_master%u", dev->id);
+       snprintf(dev->name, sizeof(dev->name), "w1_bus_master%u", dev->id);
+
+       dev->driver = driver;
+
+       dev->groups = 23;
+       dev->seq = 1;
+       dev->nls = netlink_kernel_create(NETLINK_NFLOG, NULL);
+       if (!dev->nls) {
+               printk(KERN_ERR "Failed to create new netlink socket(%u).\n",
+                       NETLINK_NFLOG);
+               memset(dev, 0, sizeof(struct w1_master));
+               kfree(dev);
+               dev = NULL;
+       }
+
+       err = device_register(&dev->dev);
+       if (err) {
+               printk(KERN_ERR "Failed to register master device. err=%d\n", err);
+               if (dev->nls->sk_socket)
+                       sock_release(dev->nls->sk_socket);
+               memset(dev, 0, sizeof(struct w1_master));
+               kfree(dev);
+               dev = NULL;
+       }
+
+       return dev;
+}
+
+void w1_free_dev(struct w1_master *dev)
+{
+       device_unregister(&dev->dev);
+       if (dev->nls->sk_socket)
+               sock_release(dev->nls->sk_socket);
+       memset(dev, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master));
+       kfree(dev);
+}
+
+int w1_add_master_device(struct w1_bus_master *master)
+{
+       struct w1_master *dev;
+       int retval = 0;
+
+       dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, &w1_driver, &w1_device);
+       if (!dev)
+               return -ENOMEM;
+
+       dev->kpid = kernel_thread(&w1_process, dev, 0);
+       if (dev->kpid < 0) {
+               dev_err(&dev->dev,
+                        "Failed to create new kernel thread. err=%d\n",
+                        dev->kpid);
+               retval = dev->kpid;
+               goto err_out_free_dev;
+       }
+
+       retval = device_create_file(&dev->dev, &w1_master_attribute);
+       if (retval)
+               goto err_out_kill_thread;
+
+       memcpy(dev->bus_master, master, sizeof(struct w1_bus_master));
+
+       dev->initialized = 1;
+
+       spin_lock(&w1_mlock);
+       list_add(&dev->w1_master_entry, &w1_masters);
+       spin_unlock(&w1_mlock);
+
+       return 0;
+
+err_out_kill_thread:
+       dev->need_exit = 1;
+       if (kill_proc(dev->kpid, SIGTERM, 1))
+               dev_err(&dev->dev,
+                        "Failed to send signal to w1 kernel thread %d.\n",
+                        dev->kpid);
+       wait_for_completion(&dev->dev_exited);
+
+err_out_free_dev:
+       w1_free_dev(dev);
+
+       return retval;
+}
+
+void __w1_remove_master_device(struct w1_master *dev)
+{
+       int err;
+
+       dev->need_exit = 1;
+       err = kill_proc(dev->kpid, SIGTERM, 1);
+       if (err)
+               dev_err(&dev->dev,
+                        "%s: Failed to send signal to w1 kernel thread %d.\n",
+                        __func__, dev->kpid);
+
+       while (atomic_read(&dev->refcnt))
+               schedule_timeout(10);
+
+       w1_free_dev(dev);
+}
+
+void w1_remove_master_device(struct w1_bus_master *bm)
+{
+       struct w1_master *dev = NULL;
+       struct list_head *ent, *n;
+
+       list_for_each_safe(ent, n, &w1_masters) {
+               dev = list_entry(ent, struct w1_master, w1_master_entry);
+               if (!dev->initialized)
+                       continue;
+
+               if (dev->bus_master->data == bm->data)
+                       break;
+       }
+
+       if (!dev) {
+               printk(KERN_ERR "Device doesn't exist.\n");
+               return;
+       }
+
+       __w1_remove_master_device(dev);
+}
+
+EXPORT_SYMBOL(w1_alloc_dev);
+EXPORT_SYMBOL(w1_free_dev);
+EXPORT_SYMBOL(w1_add_master_device);
+EXPORT_SYMBOL(w1_remove_master_device);
+EXPORT_SYMBOL(__w1_remove_master_device);
diff --git a/drivers/w1/w1_int.h b/drivers/w1/w1_int.h
new file mode 100644 (file)
index 0000000..a5aeb76
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *     w1_int.h
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __W1_INT_H
+#define __W1_INT_H
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+
+#include "w1.h"
+
+struct w1_master * w1_alloc_dev(int, struct device_driver *, struct device *);
+void w1_free_dev(struct w1_master *dev);
+int w1_add_master_device(struct w1_bus_master *);
+void w1_remove_master_device(struct w1_bus_master *);
+void __w1_remove_master_device(struct w1_master *);
+
+#endif /* __W1_INT_H */
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
new file mode 100644 (file)
index 0000000..75d538b
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ *     w1_io.c
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <asm/io.h>
+#include <asm/delay.h>
+
+#include <linux/moduleparam.h>
+
+#include "w1.h"
+#include "w1_log.h"
+#include "w1_io.h"
+
+int w1_delay_parm = 1;
+module_param_named(delay_coef, w1_delay_parm, int, 0);
+
+static u8 w1_crc8_table[] = {
+       0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
+       157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
+       35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
+       190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
+       70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
+       219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
+       101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
+       248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
+       140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
+       17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
+       175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
+       50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
+       202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
+       87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
+       233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
+       116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53
+};
+
+void w1_delay(unsigned long tm)
+{
+       udelay(tm * w1_delay_parm);
+}
+
+void w1_write_bit(struct w1_master *dev, int bit)
+{
+       if (bit) {
+               dev->bus_master->write_bit(dev->bus_master->data, 0);
+               w1_delay(6);
+               dev->bus_master->write_bit(dev->bus_master->data, 1);
+               w1_delay(64);
+       } else {
+               dev->bus_master->write_bit(dev->bus_master->data, 0);
+               w1_delay(60);
+               dev->bus_master->write_bit(dev->bus_master->data, 1);
+               w1_delay(10);
+       }
+}
+
+void w1_write_8(struct w1_master *dev, u8 byte)
+{
+       int i;
+
+       for (i = 0; i < 8; ++i)
+               w1_write_bit(dev, (byte >> i) & 0x1);
+}
+
+u8 w1_read_bit(struct w1_master *dev)
+{
+       int result;
+
+       dev->bus_master->write_bit(dev->bus_master->data, 0);
+       w1_delay(6);
+       dev->bus_master->write_bit(dev->bus_master->data, 1);
+       w1_delay(9);
+
+       result = dev->bus_master->read_bit(dev->bus_master->data);
+       w1_delay(55);
+
+       return result & 0x1;
+}
+
+u8 w1_read_8(struct w1_master * dev)
+{
+       int i;
+       u8 res = 0;
+
+       for (i = 0; i < 8; ++i)
+               res |= (w1_read_bit(dev) << i);
+
+       return res;
+}
+
+int w1_reset_bus(struct w1_master *dev)
+{
+       int result;
+
+       dev->bus_master->write_bit(dev->bus_master->data, 0);
+       w1_delay(480);
+       dev->bus_master->write_bit(dev->bus_master->data, 1);
+       w1_delay(70);
+
+       result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1;
+       w1_delay(410);
+
+       return result;
+}
+
+u8 w1_calc_crc8(u8 * data, int len)
+{
+       u8 crc = 0;
+
+       while (len--)
+               crc = w1_crc8_table[crc ^ *data++];
+
+       return crc;
+}
+
+EXPORT_SYMBOL(w1_write_bit);
+EXPORT_SYMBOL(w1_write_8);
+EXPORT_SYMBOL(w1_read_bit);
+EXPORT_SYMBOL(w1_read_8);
+EXPORT_SYMBOL(w1_reset_bus);
+EXPORT_SYMBOL(w1_calc_crc8);
+EXPORT_SYMBOL(w1_delay);
diff --git a/drivers/w1/w1_log.h b/drivers/w1/w1_log.h
new file mode 100644 (file)
index 0000000..a6bf6f4
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *     w1_log.h
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __W1_LOG_H
+#define __W1_LOG_H
+
+#define DEBUG
+
+#ifdef W1_DEBUG
+#  define assert(expr) do {} while (0)
+#else
+#  define assert(expr) \
+        if(unlikely(!(expr))) {                                        \
+        printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n",        \
+        #expr,__FILE__,__FUNCTION__,__LINE__);                 \
+        }
+#endif
+
+#endif /* __W1_LOG_H */
+
diff --git a/fs/ntfs/collate.c b/fs/ntfs/collate.c
new file mode 100644 (file)
index 0000000..2a4a25f
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * collate.c - NTFS kernel collation handling.  Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ *
+ * This program/include file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program/include file is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (in the main directory of the Linux-NTFS
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ntfs.h"
+#include "collate.h"
+
+static int ntfs_collate_binary(ntfs_volume *vol,
+               const void *data1, const int data1_len,
+               const void *data2, const int data2_len)
+{
+       int rc;
+
+       ntfs_debug("Entering.");
+       rc = memcmp(data1, data2, min(data1_len, data2_len));
+       if (!rc && (data1_len != data2_len)) {
+               if (data1_len < data2_len)
+                       rc = -1;
+               else
+                       rc = 1;
+       }
+       ntfs_debug("Done, returning %i", rc);
+       return rc;
+}
+
+static int ntfs_collate_ntofs_ulong(ntfs_volume *vol,
+               const void *data1, const int data1_len,
+               const void *data2, const int data2_len)
+{
+       int rc;
+       u32 d1, d2;
+
+       ntfs_debug("Entering.");
+       // FIXME:  We don't really want to bug here.
+       BUG_ON(data1_len != data2_len);
+       BUG_ON(data1_len != 4);
+       d1 = le32_to_cpup(data1);
+       d2 = le32_to_cpup(data2);
+       if (d1 < d2)
+               rc = -1;
+       else {
+               if (d1 == d2)
+                       rc = 0;
+               else
+                       rc = 1;
+       }
+       ntfs_debug("Done, returning %i", rc);
+       return rc;
+}
+
+typedef int (*ntfs_collate_func_t)(ntfs_volume *, const void *, const int,
+               const void *, const int);
+
+static ntfs_collate_func_t ntfs_do_collate0x0[3] = {
+       ntfs_collate_binary,
+       NULL/*ntfs_collate_file_name*/,
+       NULL/*ntfs_collate_unicode_string*/,
+};
+
+static ntfs_collate_func_t ntfs_do_collate0x1[4] = {
+       ntfs_collate_ntofs_ulong,
+       NULL/*ntfs_collate_ntofs_sid*/,
+       NULL/*ntfs_collate_ntofs_security_hash*/,
+       NULL/*ntfs_collate_ntofs_ulongs*/,
+};
+
+/**
+ * ntfs_collate - collate two data items using a specified collation rule
+ * @vol:       ntfs volume to which the data items belong
+ * @cr:                collation rule to use when comparing the items
+ * @data1:     first data item to collate
+ * @data1_len: length in bytes of @data1
+ * @data2:     second data item to collate
+ * @data2_len: length in bytes of @data2
+ *
+ * Collate the two data items @data1 and @data2 using the collation rule @cr
+ * and return -1, 0, ir 1 if @data1 is found, respectively, to collate before,
+ * to match, or to collate after @data2.
+ *
+ * For speed we use the collation rule @cr as an index into two tables of
+ * function pointers to call the appropriate collation function.
+ */
+int ntfs_collate(ntfs_volume *vol, COLLATION_RULES cr,
+               const void *data1, const int data1_len,
+               const void *data2, const int data2_len) {
+       ntfs_debug("Entering.");
+       /*
+        * FIXME:  At the moment we only support COLLATION_BINARY and
+        * COLLATION_NTOFS_ULONG, so we BUG() for everything else for now.
+        */
+       BUG_ON(cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG);
+       cr = le32_to_cpu(cr);
+       BUG_ON(cr < 0);
+       if (cr <= 0x02)
+               return ntfs_do_collate0x0[cr](vol, data1, data1_len,
+                               data2, data2_len);
+       BUG_ON(cr < 0x10);
+       cr -= 0x10;
+       if (likely(cr <= 3))
+               return ntfs_do_collate0x1[cr](vol, data1, data1_len,
+                               data2, data2_len);
+       BUG();
+       return 0;
+}
diff --git a/include/asm-alpha/setup.h b/include/asm-alpha/setup.h
new file mode 100644 (file)
index 0000000..2e023a4
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ALPHA_SETUP_H
+#define __ALPHA_SETUP_H
+
+#define COMMAND_LINE_SIZE      256
+
+#endif
diff --git a/include/asm-generic/netdump.h b/include/asm-generic/netdump.h
new file mode 100644 (file)
index 0000000..5cf447f
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef _ASM_GENERIC_NETDUMP_H_
+#define _ASM_GENERIC_NETDUMP_H_
+
+/*
+ * linux/include/asm-generic/netdump.h
+ *
+ * Copyright (c) 2003, 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef __KERNEL__
+
+#warning netdump is not supported on this platform
+const static int platform_supports_netdump = 0;
+
+static inline int page_is_ram(unsigned long x) { return 0; }
+
+#define platform_timestamp(x) do { (x) = 0; } while (0)  
+
+#define platform_fix_regs() do { } while (0)
+#define platform_init_stack(stackptr) do { } while (0)
+#define platform_cleanup_stack(stackptr) do { } while (0)
+#define platform_start_netdump(stackptr,regs) do { } while (0)
+#define platform_max_pfn() do { int ret = 0; } while (0)
+
+#undef ELF_CORE_COPY_REGS
+#define ELF_CORE_COPY_REGS(x, y) do { struct pt_regs *z; z = (y); } while (0)
+
+#define show_mem() do {} while (0)
+
+#define show_state() do {} while (0)
+
+#define show_regs(x) do { struct pt_regs *z; z = (x); } while (0)
+
+#undef ZERO_PAGE
+static inline struct page *ZERO_PAGE(void *x) { return NULL; }
+
+#undef KM_NETDUMP
+#define KM_NETDUMP 0
+
+#undef kmap_atomic
+#undef kunmap_atomic
+static inline char *kmap_atomic(void *page, int idx)  { return NULL; }
+#define kunmap_atomic(addr, idx)  do { } while (0)
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_GENERIC_NETDUMP_H */
diff --git a/include/asm-i386/netdump.h b/include/asm-i386/netdump.h
new file mode 100644 (file)
index 0000000..988c276
--- /dev/null
@@ -0,0 +1,100 @@
+#ifndef _ASM_I386_NETDUMP_H
+#define _ASM_I386_NETDUMP_H
+
+/*
+ * linux/include/asm-i386/netdump.h
+ *
+ * Copyright (c) 2003, 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifdef __KERNEL__
+
+#include <asm/irq.h>
+
+extern int page_is_ram (unsigned long);
+const static int platform_supports_netdump = 1;
+extern union irq_ctx *netdump_irq_ctx;
+
+#define platform_timestamp(x) rdtscll(x)
+
+#define platform_fix_regs()                                            \
+{                                                                      \
+       unsigned long esp;                                              \
+       unsigned short ss;                                              \
+       esp = (unsigned long) ((char *)regs + sizeof (struct pt_regs)); \
+       ss = __KERNEL_DS;                                               \
+       if (regs->xcs & 3) {                                            \
+               esp = regs->esp;                                                \
+               ss = regs->xss & 0xffff;                                        \
+       }                                                               \
+       myregs = *regs;                                                 \
+       myregs.esp = esp;                                               \
+       myregs.xss = (myregs.xss & 0xffff0000) | ss;                    \
+};
+
+static inline void platform_init_stack(void **stackptr)
+{
+       *stackptr = (void *)kmalloc(sizeof(union irq_ctx), GFP_KERNEL);
+       if (*stackptr)
+               memset(*stackptr, 0, sizeof(union irq_ctx));
+       else
+               printk(KERN_WARNING
+                      "netdump: unable to allocate separate stack\n");
+}
+
+static inline void platform_start_netdump(void *stackptr, struct pt_regs *regs)
+{
+       u32 *dsp;
+       union irq_ctx * curctx;
+       union irq_ctx * dumpctx;
+
+       if (!stackptr)
+               netpoll_netdump(regs);
+       else {
+               curctx = (union irq_ctx *) current_thread_info();
+               dumpctx = (union irq_ctx *) stackptr;
+
+               /* build the stack frame on the IRQ stack */
+               dsp = (u32*) ((char*)dumpctx + sizeof(*dumpctx));
+               dumpctx->tinfo.task = curctx->tinfo.task;
+               dumpctx->tinfo.real_stack = curctx->tinfo.real_stack;
+               dumpctx->tinfo.virtual_stack = curctx->tinfo.virtual_stack;
+               dumpctx->tinfo.previous_esp = current_stack_pointer();
+
+               *--dsp = (u32) regs;
+
+               asm volatile(
+                       "       xchgl   %%ebx,%%esp     \n"
+                       "       call    netpoll_netdump \n"
+                       "       xchgl   %%ebx,%%esp     \n"
+                       : : "b"(dsp) :  "memory", "cc", "edx", "ecx"
+               );
+       }
+}
+
+#define platform_cleanup_stack(stackptr)       \
+do {                                           \
+       if (stackptr)                           \
+               kfree(stackptr);                \
+} while (0)
+
+#define platform_max_pfn() (num_physpages)
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_I386_NETDUMP_H */
diff --git a/include/asm-ia64/netdump.h b/include/asm-ia64/netdump.h
new file mode 100644 (file)
index 0000000..49f3fbd
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_IA64_NETDUMP_H_
+#define _ASM_IA64_NETDUMP_H_
+
+#include <asm-generic/netdump.h>
+
+#endif /* _ASM_IA64_NETDUMP_H_ */
diff --git a/include/asm-ia64/setup.h b/include/asm-ia64/setup.h
new file mode 100644 (file)
index 0000000..ea29b57
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __IA64_SETUP_H
+#define __IA64_SETUP_H
+
+#define COMMAND_LINE_SIZE      512
+
+#endif
diff --git a/include/asm-mips/gt64240.h b/include/asm-mips/gt64240.h
new file mode 100644 (file)
index 0000000..8f9bd34
--- /dev/null
@@ -0,0 +1,1235 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright - Galileo technology.
+ * Copyright (C) 2004 by Ralf Baechle
+ */
+#ifndef __ASM_MIPS_MV64240_H
+#define __ASM_MIPS_MV64240_H
+
+#include <asm/addrspace.h>
+#include <asm/marvell.h>
+
+/*
+ * CPU Control Registers
+ */
+
+#define CPU_CONFIGURATION                                      0x000
+#define CPU_MODE                                               0x120
+#define CPU_READ_RESPONSE_CROSSBAR_LOW                         0x170
+#define CPU_READ_RESPONSE_CROSSBAR_HIGH                                0x178
+
+/*
+ * Processor Address Space
+ */
+
+/* Sdram's BAR'S */
+#define SCS_0_LOW_DECODE_ADDRESS                               0x008
+#define SCS_0_HIGH_DECODE_ADDRESS                              0x010
+#define SCS_1_LOW_DECODE_ADDRESS                               0x208
+#define SCS_1_HIGH_DECODE_ADDRESS                              0x210
+#define SCS_2_LOW_DECODE_ADDRESS                               0x018
+#define SCS_2_HIGH_DECODE_ADDRESS                              0x020
+#define SCS_3_LOW_DECODE_ADDRESS                               0x218
+#define SCS_3_HIGH_DECODE_ADDRESS                              0x220
+/* Devices BAR'S */
+#define CS_0_LOW_DECODE_ADDRESS                                        0x028
+#define CS_0_HIGH_DECODE_ADDRESS                               0x030
+#define CS_1_LOW_DECODE_ADDRESS                                        0x228
+#define CS_1_HIGH_DECODE_ADDRESS                               0x230
+#define CS_2_LOW_DECODE_ADDRESS                                        0x248
+#define CS_2_HIGH_DECODE_ADDRESS                               0x250
+#define CS_3_LOW_DECODE_ADDRESS                                        0x038
+#define CS_3_HIGH_DECODE_ADDRESS                               0x040
+#define BOOTCS_LOW_DECODE_ADDRESS                              0x238
+#define BOOTCS_HIGH_DECODE_ADDRESS                             0x240
+
+#define PCI_0I_O_LOW_DECODE_ADDRESS                            0x048
+#define PCI_0I_O_HIGH_DECODE_ADDRESS                           0x050
+#define PCI_0MEMORY0_LOW_DECODE_ADDRESS                                0x058
+#define PCI_0MEMORY0_HIGH_DECODE_ADDRESS                       0x060
+#define PCI_0MEMORY1_LOW_DECODE_ADDRESS                                0x080
+#define PCI_0MEMORY1_HIGH_DECODE_ADDRESS                       0x088
+#define PCI_0MEMORY2_LOW_DECODE_ADDRESS                                0x258
+#define PCI_0MEMORY2_HIGH_DECODE_ADDRESS                       0x260
+#define PCI_0MEMORY3_LOW_DECODE_ADDRESS                                0x280
+#define PCI_0MEMORY3_HIGH_DECODE_ADDRESS                       0x288
+
+#define PCI_1I_O_LOW_DECODE_ADDRESS                            0x090
+#define PCI_1I_O_HIGH_DECODE_ADDRESS                           0x098
+#define PCI_1MEMORY0_LOW_DECODE_ADDRESS                                0x0a0
+#define PCI_1MEMORY0_HIGH_DECODE_ADDRESS                       0x0a8
+#define PCI_1MEMORY1_LOW_DECODE_ADDRESS                                0x0b0
+#define PCI_1MEMORY1_HIGH_DECODE_ADDRESS                       0x0b8
+#define PCI_1MEMORY2_LOW_DECODE_ADDRESS                                0x2a0
+#define PCI_1MEMORY2_HIGH_DECODE_ADDRESS                       0x2a8
+#define PCI_1MEMORY3_LOW_DECODE_ADDRESS                                0x2b0
+#define PCI_1MEMORY3_HIGH_DECODE_ADDRESS                       0x2b8
+
+#define INTERNAL_SPACE_DECODE                                  0x068
+
+#define CPU_0_LOW_DECODE_ADDRESS                               0x290
+#define CPU_0_HIGH_DECODE_ADDRESS                              0x298
+#define CPU_1_LOW_DECODE_ADDRESS                               0x2c0
+#define CPU_1_HIGH_DECODE_ADDRESS                              0x2c8
+
+#define PCI_0I_O_ADDRESS_REMAP                                 0x0f0
+#define PCI_0MEMORY0_ADDRESS_REMAP                             0x0f8
+#define PCI_0MEMORY0_HIGH_ADDRESS_REMAP                                0x320
+#define PCI_0MEMORY1_ADDRESS_REMAP                             0x100
+#define PCI_0MEMORY1_HIGH_ADDRESS_REMAP                                0x328
+#define PCI_0MEMORY2_ADDRESS_REMAP                             0x2f8
+#define PCI_0MEMORY2_HIGH_ADDRESS_REMAP                                0x330
+#define PCI_0MEMORY3_ADDRESS_REMAP                             0x300
+#define PCI_0MEMORY3_HIGH_ADDRESS_REMAP                                0x338
+
+#define PCI_1I_O_ADDRESS_REMAP                                 0x108
+#define PCI_1MEMORY0_ADDRESS_REMAP                             0x110
+#define PCI_1MEMORY0_HIGH_ADDRESS_REMAP                                0x340
+#define PCI_1MEMORY1_ADDRESS_REMAP                             0x118
+#define PCI_1MEMORY1_HIGH_ADDRESS_REMAP                                0x348
+#define PCI_1MEMORY2_ADDRESS_REMAP                             0x310
+#define PCI_1MEMORY2_HIGH_ADDRESS_REMAP                                0x350
+#define PCI_1MEMORY3_ADDRESS_REMAP                             0x318
+#define PCI_1MEMORY3_HIGH_ADDRESS_REMAP                                0x358
+
+/*
+ * CPU Sync Barrier
+ */
+
+#define PCI_0SYNC_BARIER_VIRTUAL_REGISTER                      0x0c0
+#define PCI_1SYNC_BARIER_VIRTUAL_REGISTER                      0x0c8
+
+
+/*
+ * CPU Access Protect
+ */
+
+#define CPU_LOW_PROTECT_ADDRESS_0                              0X180
+#define CPU_HIGH_PROTECT_ADDRESS_0                             0X188
+#define CPU_LOW_PROTECT_ADDRESS_1                              0X190
+#define CPU_HIGH_PROTECT_ADDRESS_1                             0X198
+#define CPU_LOW_PROTECT_ADDRESS_2                              0X1a0
+#define CPU_HIGH_PROTECT_ADDRESS_2                             0X1a8
+#define CPU_LOW_PROTECT_ADDRESS_3                              0X1b0
+#define CPU_HIGH_PROTECT_ADDRESS_3                             0X1b8
+#define CPU_LOW_PROTECT_ADDRESS_4                              0X1c0
+#define CPU_HIGH_PROTECT_ADDRESS_4                             0X1c8
+#define CPU_LOW_PROTECT_ADDRESS_5                              0X1d0
+#define CPU_HIGH_PROTECT_ADDRESS_5                             0X1d8
+#define CPU_LOW_PROTECT_ADDRESS_6                              0X1e0
+#define CPU_HIGH_PROTECT_ADDRESS_6                             0X1e8
+#define CPU_LOW_PROTECT_ADDRESS_7                              0X1f0
+#define CPU_HIGH_PROTECT_ADDRESS_7                             0X1f8
+
+
+/*
+ * Snoop Control
+ */
+
+#define SNOOP_BASE_ADDRESS_0                                   0x380
+#define SNOOP_TOP_ADDRESS_0                                    0x388
+#define SNOOP_BASE_ADDRESS_1                                   0x390
+#define SNOOP_TOP_ADDRESS_1                                    0x398
+#define SNOOP_BASE_ADDRESS_2                                   0x3a0
+#define SNOOP_TOP_ADDRESS_2                                    0x3a8
+#define SNOOP_BASE_ADDRESS_3                                   0x3b0
+#define SNOOP_TOP_ADDRESS_3                                    0x3b8
+
+/*
+ * CPU Error Report
+ */
+
+#define CPU_ERROR_ADDRESS_LOW                                  0x070
+#define CPU_ERROR_ADDRESS_HIGH                                 0x078
+#define CPU_ERROR_DATA_LOW                                     0x128
+#define CPU_ERROR_DATA_HIGH                                    0x130
+#define CPU_ERROR_PARITY                                       0x138
+#define CPU_ERROR_CAUSE                                                0x140
+#define CPU_ERROR_MASK                                         0x148
+
+/*
+ * Pslave Debug
+ */
+
+#define X_0_ADDRESS                                            0x360
+#define X_0_COMMAND_ID                                         0x368
+#define X_1_ADDRESS                                            0x370
+#define X_1_COMMAND_ID                                         0x378
+#define WRITE_DATA_LOW                                         0x3c0
+#define WRITE_DATA_HIGH                                                0x3c8
+#define WRITE_BYTE_ENABLE                                      0X3e0
+#define READ_DATA_LOW                                          0x3d0
+#define READ_DATA_HIGH                                         0x3d8
+#define READ_ID                                                        0x3e8
+
+
+/*
+ * SDRAM and Device Address Space
+ */
+
+
+/*
+ * SDRAM Configuration
+ */
+
+#define SDRAM_CONFIGURATION                                    0x448
+#define SDRAM_OPERATION_MODE                                   0x474
+#define SDRAM_ADDRESS_DECODE                                   0x47C
+#define SDRAM_TIMING_PARAMETERS                                        0x4b4
+#define SDRAM_UMA_CONTROL                                      0x4a4
+#define SDRAM_CROSS_BAR_CONTROL_LOW                            0x4a8
+#define SDRAM_CROSS_BAR_CONTROL_HIGH                           0x4ac
+#define SDRAM_CROSS_BAR_TIMEOUT                                        0x4b0
+
+
+/*
+ * SDRAM Parameters
+ */
+
+#define SDRAM_BANK0PARAMETERS                                  0x44C
+#define SDRAM_BANK1PARAMETERS                                  0x450
+#define SDRAM_BANK2PARAMETERS                                  0x454
+#define SDRAM_BANK3PARAMETERS                                  0x458
+
+
+/*
+ * SDRAM Error Report
+ */
+
+#define SDRAM_ERROR_DATA_LOW                                   0x484
+#define SDRAM_ERROR_DATA_HIGH                                  0x480
+#define SDRAM_AND_DEVICE_ERROR_ADDRESS                         0x490
+#define SDRAM_RECEIVED_ECC                                     0x488
+#define SDRAM_CALCULATED_ECC                                   0x48c
+#define SDRAM_ECC_CONTROL                                      0x494
+#define SDRAM_ECC_ERROR_COUNTER                                        0x498
+
+
+/*
+ * SDunit Debug (for internal use)
+ */
+
+#define X0_ADDRESS                                             0x500
+#define X0_COMMAND_AND_ID                                      0x504
+#define X0_WRITE_DATA_LOW                                      0x508
+#define X0_WRITE_DATA_HIGH                                     0x50c
+#define X0_WRITE_BYTE_ENABLE                                   0x518
+#define X0_READ_DATA_LOW                                       0x510
+#define X0_READ_DATA_HIGH                                      0x514
+#define X0_READ_ID                                             0x51c
+#define X1_ADDRESS                                             0x520
+#define X1_COMMAND_AND_ID                                      0x524
+#define X1_WRITE_DATA_LOW                                      0x528
+#define X1_WRITE_DATA_HIGH                                     0x52c
+#define X1_WRITE_BYTE_ENABLE                                   0x538
+#define X1_READ_DATA_LOW                                       0x530
+#define X1_READ_DATA_HIGH                                      0x534
+#define X1_READ_ID                                             0x53c
+#define X0_SNOOP_ADDRESS                                       0x540
+#define X0_SNOOP_COMMAND                                       0x544
+#define X1_SNOOP_ADDRESS                                       0x548
+#define X1_SNOOP_COMMAND                                       0x54c
+
+
+/*
+ * Device Parameters
+ */
+
+#define DEVICE_BANK0PARAMETERS                                 0x45c
+#define DEVICE_BANK1PARAMETERS                                 0x460
+#define DEVICE_BANK2PARAMETERS                                 0x464
+#define DEVICE_BANK3PARAMETERS                                 0x468
+#define DEVICE_BOOT_BANK_PARAMETERS                            0x46c
+#define DEVICE_CONTROL                                         0x4c0
+#define DEVICE_CROSS_BAR_CONTROL_LOW                           0x4c8
+#define DEVICE_CROSS_BAR_CONTROL_HIGH                          0x4cc
+#define DEVICE_CROSS_BAR_TIMEOUT                               0x4c4
+
+
+/*
+ * Device Interrupt
+ */
+
+#define DEVICE_INTERRUPT_CAUSE                                 0x4d0
+#define DEVICE_INTERRUPT_MASK                                  0x4d4
+#define DEVICE_ERROR_ADDRESS                                   0x4d8
+
+/*
+ * DMA Record
+ */
+
+#define CHANNEL0_DMA_BYTE_COUNT                                        0x800
+#define CHANNEL1_DMA_BYTE_COUNT                                        0x804
+#define CHANNEL2_DMA_BYTE_COUNT                                        0x808
+#define CHANNEL3_DMA_BYTE_COUNT                                        0x80C
+#define CHANNEL4_DMA_BYTE_COUNT                                        0x900
+#define CHANNEL5_DMA_BYTE_COUNT                                        0x904
+#define CHANNEL6_DMA_BYTE_COUNT                                        0x908
+#define CHANNEL7_DMA_BYTE_COUNT                                        0x90C
+#define CHANNEL0_DMA_SOURCE_ADDRESS                            0x810
+#define CHANNEL1_DMA_SOURCE_ADDRESS                            0x814
+#define CHANNEL2_DMA_SOURCE_ADDRESS                            0x818
+#define CHANNEL3_DMA_SOURCE_ADDRESS                            0x81C
+#define CHANNEL4_DMA_SOURCE_ADDRESS                            0x910
+#define CHANNEL5_DMA_SOURCE_ADDRESS                            0x914
+#define CHANNEL6_DMA_SOURCE_ADDRESS                            0x918
+#define CHANNEL7_DMA_SOURCE_ADDRESS                            0x91C
+#define CHANNEL0_DMA_DESTINATION_ADDRESS                       0x820
+#define CHANNEL1_DMA_DESTINATION_ADDRESS                       0x824
+#define CHANNEL2_DMA_DESTINATION_ADDRESS                       0x828
+#define CHANNEL3_DMA_DESTINATION_ADDRESS                       0x82C
+#define CHANNEL4_DMA_DESTINATION_ADDRESS                       0x920
+#define CHANNEL5_DMA_DESTINATION_ADDRESS                       0x924
+#define CHANNEL6_DMA_DESTINATION_ADDRESS                       0x928
+#define CHANNEL7_DMA_DESTINATION_ADDRESS                       0x92C
+#define CHANNEL0NEXT_RECORD_POINTER                            0x830
+#define CHANNEL1NEXT_RECORD_POINTER                            0x834
+#define CHANNEL2NEXT_RECORD_POINTER                            0x838
+#define CHANNEL3NEXT_RECORD_POINTER                            0x83C
+#define CHANNEL4NEXT_RECORD_POINTER                            0x930
+#define CHANNEL5NEXT_RECORD_POINTER                            0x934
+#define CHANNEL6NEXT_RECORD_POINTER                            0x938
+#define CHANNEL7NEXT_RECORD_POINTER                            0x93C
+#define CHANNEL0CURRENT_DESCRIPTOR_POINTER                     0x870
+#define CHANNEL1CURRENT_DESCRIPTOR_POINTER                     0x874
+#define CHANNEL2CURRENT_DESCRIPTOR_POINTER                     0x878
+#define CHANNEL3CURRENT_DESCRIPTOR_POINTER                     0x87C
+#define CHANNEL4CURRENT_DESCRIPTOR_POINTER                     0x970
+#define CHANNEL5CURRENT_DESCRIPTOR_POINTER                     0x974
+#define CHANNEL6CURRENT_DESCRIPTOR_POINTER                     0x978
+#define CHANNEL7CURRENT_DESCRIPTOR_POINTER                     0x97C
+#define CHANNEL0_DMA_SOURCE_HIGH_PCI_ADDRESS                   0x890
+#define CHANNEL1_DMA_SOURCE_HIGH_PCI_ADDRESS                   0x894
+#define CHANNEL2_DMA_SOURCE_HIGH_PCI_ADDRESS                   0x898
+#define CHANNEL3_DMA_SOURCE_HIGH_PCI_ADDRESS                   0x89c
+#define CHANNEL4_DMA_SOURCE_HIGH_PCI_ADDRESS                   0x990
+#define CHANNEL5_DMA_SOURCE_HIGH_PCI_ADDRESS                   0x994
+#define CHANNEL6_DMA_SOURCE_HIGH_PCI_ADDRESS                   0x998
+#define CHANNEL7_DMA_SOURCE_HIGH_PCI_ADDRESS                   0x99c
+#define CHANNEL0_DMA_DESTINATION_HIGH_PCI_ADDRESS              0x8a0
+#define CHANNEL1_DMA_DESTINATION_HIGH_PCI_ADDRESS              0x8a4
+#define CHANNEL2_DMA_DESTINATION_HIGH_PCI_ADDRESS              0x8a8
+#define CHANNEL3_DMA_DESTINATION_HIGH_PCI_ADDRESS              0x8ac
+#define CHANNEL4_DMA_DESTINATION_HIGH_PCI_ADDRESS              0x9a0
+#define CHANNEL5_DMA_DESTINATION_HIGH_PCI_ADDRESS              0x9a4
+#define CHANNEL6_DMA_DESTINATION_HIGH_PCI_ADDRESS              0x9a8
+#define CHANNEL7_DMA_DESTINATION_HIGH_PCI_ADDRESS              0x9ac
+#define CHANNEL0_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS      0x8b0
+#define CHANNEL1_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS      0x8b4
+#define CHANNEL2_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS      0x8b8
+#define CHANNEL3_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS      0x8bc
+#define CHANNEL4_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS      0x9b0
+#define CHANNEL5_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS      0x9b4
+#define CHANNEL6_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS      0x9b8
+#define CHANNEL7_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS      0x9bc
+
+/*
+ * DMA Channel Control
+ */
+
+#define CHANNEL0CONTROL                                                0x840
+#define CHANNEL0CONTROL_HIGH                                   0x880
+
+#define CHANNEL1CONTROL                                                0x844
+#define CHANNEL1CONTROL_HIGH                                   0x884
+
+#define CHANNEL2CONTROL                                                0x848
+#define CHANNEL2CONTROL_HIGH                                   0x888
+
+#define CHANNEL3CONTROL                                                0x84C
+#define CHANNEL3CONTROL_HIGH                                   0x88C
+
+#define CHANNEL4CONTROL                                                0x940
+#define CHANNEL4CONTROL_HIGH                                   0x980
+
+#define CHANNEL5CONTROL                                                0x944
+#define CHANNEL5CONTROL_HIGH                                   0x984
+
+#define CHANNEL6CONTROL                                                0x948
+#define CHANNEL6CONTROL_HIGH                                   0x988
+
+#define CHANNEL7CONTROL                                                0x94C
+#define CHANNEL7CONTROL_HIGH                                   0x98C
+
+
+/*
+ * DMA Arbiter
+ */
+
+#define ARBITER_CONTROL_0_3                                    0x860
+#define ARBITER_CONTROL_4_7                                    0x960
+
+
+/*
+ * DMA Interrupt
+ */
+
+#define CHANELS0_3_INTERRUPT_CAUSE                             0x8c0
+#define CHANELS0_3_INTERRUPT_MASK                              0x8c4
+#define CHANELS0_3_ERROR_ADDRESS                               0x8c8
+#define CHANELS0_3_ERROR_SELECT                                        0x8cc
+#define CHANELS4_7_INTERRUPT_CAUSE                             0x9c0
+#define CHANELS4_7_INTERRUPT_MASK                              0x9c4
+#define CHANELS4_7_ERROR_ADDRESS                               0x9c8
+#define CHANELS4_7_ERROR_SELECT                                        0x9cc
+
+
+/*
+ * DMA Debug (for internal use)
+ */
+
+#define DMA_X0_ADDRESS                                         0x8e0
+#define DMA_X0_COMMAND_AND_ID                                  0x8e4
+#define DMA_X0_WRITE_DATA_LOW                                  0x8e8
+#define DMA_X0_WRITE_DATA_HIGH                                 0x8ec
+#define DMA_X0_WRITE_BYTE_ENABLE                               0x8f8
+#define DMA_X0_READ_DATA_LOW                                   0x8f0
+#define DMA_X0_READ_DATA_HIGH                                  0x8f4
+#define DMA_X0_READ_ID                                         0x8fc
+#define DMA_X1_ADDRESS                                         0x9e0
+#define DMA_X1_COMMAND_AND_ID                                  0x9e4
+#define DMA_X1_WRITE_DATA_LOW                                  0x9e8
+#define DMA_X1_WRITE_DATA_HIGH                                 0x9ec
+#define DMA_X1_WRITE_BYTE_ENABLE                               0x9f8
+#define DMA_X1_READ_DATA_LOW                                   0x9f0
+#define DMA_X1_READ_DATA_HIGH                                  0x9f4
+#define DMA_X1_READ_ID                                         0x9fc
+
+/*
+ * Timer_Counter
+ */
+
+#define TIMER_COUNTER0                                         0x850
+#define TIMER_COUNTER1                                         0x854
+#define TIMER_COUNTER2                                         0x858
+#define TIMER_COUNTER3                                         0x85C
+#define TIMER_COUNTER_0_3_CONTROL                              0x864
+#define TIMER_COUNTER_0_3_INTERRUPT_CAUSE                      0x868
+#define TIMER_COUNTER_0_3_INTERRUPT_MASK                       0x86c
+#define TIMER_COUNTER4                                         0x950
+#define TIMER_COUNTER5                                         0x954
+#define TIMER_COUNTER6                                         0x958
+#define TIMER_COUNTER7                                         0x95C
+#define TIMER_COUNTER_4_7_CONTROL                              0x964
+#define TIMER_COUNTER_4_7_INTERRUPT_CAUSE                      0x968
+#define TIMER_COUNTER_4_7_INTERRUPT_MASK                       0x96c
+
+/*
+ * PCI Slave Address Decoding
+ */
+
+#define PCI_0SCS_0_BANK_SIZE                                   0xc08
+#define PCI_1SCS_0_BANK_SIZE                                   0xc88
+#define PCI_0SCS_1_BANK_SIZE                                   0xd08
+#define PCI_1SCS_1_BANK_SIZE                                   0xd88
+#define PCI_0SCS_2_BANK_SIZE                                   0xc0c
+#define PCI_1SCS_2_BANK_SIZE                                   0xc8c
+#define PCI_0SCS_3_BANK_SIZE                                   0xd0c
+#define PCI_1SCS_3_BANK_SIZE                                   0xd8c
+#define PCI_0CS_0_BANK_SIZE                                    0xc10
+#define PCI_1CS_0_BANK_SIZE                                    0xc90
+#define PCI_0CS_1_BANK_SIZE                                    0xd10
+#define PCI_1CS_1_BANK_SIZE                                    0xd90
+#define PCI_0CS_2_BANK_SIZE                                    0xd18
+#define PCI_1CS_2_BANK_SIZE                                    0xd98
+#define PCI_0CS_3_BANK_SIZE                                    0xc14
+#define PCI_1CS_3_BANK_SIZE                                    0xc94
+#define PCI_0CS_BOOT_BANK_SIZE                                 0xd14
+#define PCI_1CS_BOOT_BANK_SIZE                                 0xd94
+#define PCI_0P2P_MEM0_BAR_SIZE                                 0xd1c
+#define PCI_1P2P_MEM0_BAR_SIZE                                 0xd9c
+#define PCI_0P2P_MEM1_BAR_SIZE                                 0xd20
+#define PCI_1P2P_MEM1_BAR_SIZE                                 0xda0
+#define PCI_0P2P_I_O_BAR_SIZE                                  0xd24
+#define PCI_1P2P_I_O_BAR_SIZE                                  0xda4
+#define PCI_0CPU_BAR_SIZE                                      0xd28
+#define PCI_1CPU_BAR_SIZE                                      0xda8
+#define PCI_0DAC_SCS_0_BANK_SIZE                               0xe00
+#define PCI_1DAC_SCS_0_BANK_SIZE                               0xe80
+#define PCI_0DAC_SCS_1_BANK_SIZE                               0xe04
+#define PCI_1DAC_SCS_1_BANK_SIZE                               0xe84
+#define PCI_0DAC_SCS_2_BANK_SIZE                               0xe08
+#define PCI_1DAC_SCS_2_BANK_SIZE                               0xe88
+#define PCI_0DAC_SCS_3_BANK_SIZE                               0xe0c
+#define PCI_1DAC_SCS_3_BANK_SIZE                               0xe8c
+#define PCI_0DAC_CS_0_BANK_SIZE                                        0xe10
+#define PCI_1DAC_CS_0_BANK_SIZE                                        0xe90
+#define PCI_0DAC_CS_1_BANK_SIZE                                        0xe14
+#define PCI_1DAC_CS_1_BANK_SIZE                                        0xe94
+#define PCI_0DAC_CS_2_BANK_SIZE                                        0xe18
+#define PCI_1DAC_CS_2_BANK_SIZE                                        0xe98
+#define PCI_0DAC_CS_3_BANK_SIZE                                        0xe1c
+#define PCI_1DAC_CS_3_BANK_SIZE                                        0xe9c
+#define PCI_0DAC_BOOTCS_BANK_SIZE                              0xe20
+#define PCI_1DAC_BOOTCS_BANK_SIZE                              0xea0
+#define PCI_0DAC_P2P_MEM0_BAR_SIZE                             0xe24
+#define PCI_1DAC_P2P_MEM0_BAR_SIZE                             0xea4
+#define PCI_0DAC_P2P_MEM1_BAR_SIZE                             0xe28
+#define PCI_1DAC_P2P_MEM1_BAR_SIZE                             0xea8
+#define PCI_0DAC_CPU_BAR_SIZE                                  0xe2c
+#define PCI_1DAC_CPU_BAR_SIZE                                  0xeac
+#define PCI_0EXPANSION_ROM_BAR_SIZE                            0xd2c
+#define PCI_1EXPANSION_ROM_BAR_SIZE                            0xdac
+#define PCI_0BASE_ADDRESS_REGISTERS_ENABLE                     0xc3c
+#define PCI_1BASE_ADDRESS_REGISTERS_ENABLE                     0xcbc
+#define PCI_0SCS_0_BASE_ADDRESS_REMAP                          0xc48
+#define PCI_1SCS_0_BASE_ADDRESS_REMAP                          0xcc8
+#define PCI_0SCS_1_BASE_ADDRESS_REMAP                          0xd48
+#define PCI_1SCS_1_BASE_ADDRESS_REMAP                          0xdc8
+#define PCI_0SCS_2_BASE_ADDRESS_REMAP                          0xc4c
+#define PCI_1SCS_2_BASE_ADDRESS_REMAP                          0xccc
+#define PCI_0SCS_3_BASE_ADDRESS_REMAP                          0xd4c
+#define PCI_1SCS_3_BASE_ADDRESS_REMAP                          0xdcc
+#define PCI_0CS_0_BASE_ADDRESS_REMAP                           0xc50
+#define PCI_1CS_0_BASE_ADDRESS_REMAP                           0xcd0
+#define PCI_0CS_1_BASE_ADDRESS_REMAP                           0xd50
+#define PCI_1CS_1_BASE_ADDRESS_REMAP                           0xdd0
+#define PCI_0CS_2_BASE_ADDRESS_REMAP                           0xd58
+#define PCI_1CS_2_BASE_ADDRESS_REMAP                           0xdd8
+#define PCI_0CS_3_BASE_ADDRESS_REMAP                           0xc54
+#define PCI_1CS_3_BASE_ADDRESS_REMAP                           0xcd4
+#define PCI_0CS_BOOTCS_BASE_ADDRESS_REMAP                      0xd54
+#define PCI_1CS_BOOTCS_BASE_ADDRESS_REMAP                      0xdd4
+#define PCI_0P2P_MEM0_BASE_ADDRESS_REMAP_LOW                   0xd5c
+#define PCI_1P2P_MEM0_BASE_ADDRESS_REMAP_LOW                   0xddc
+#define PCI_0P2P_MEM0_BASE_ADDRESS_REMAP_HIGH                  0xd60
+#define PCI_1P2P_MEM0_BASE_ADDRESS_REMAP_HIGH                  0xde0
+#define PCI_0P2P_MEM1_BASE_ADDRESS_REMAP_LOW                   0xd64
+#define PCI_1P2P_MEM1_BASE_ADDRESS_REMAP_LOW                   0xde4
+#define PCI_0P2P_MEM1_BASE_ADDRESS_REMAP_HIGH                  0xd68
+#define PCI_1P2P_MEM1_BASE_ADDRESS_REMAP_HIGH                  0xde8
+#define PCI_0P2P_I_O_BASE_ADDRESS_REMAP                                0xd6c
+#define PCI_1P2P_I_O_BASE_ADDRESS_REMAP                                0xdec
+#define PCI_0CPU_BASE_ADDRESS_REMAP                            0xd70
+#define PCI_1CPU_BASE_ADDRESS_REMAP                            0xdf0
+#define PCI_0DAC_SCS_0_BASE_ADDRESS_REMAP                      0xf00
+#define PCI_1DAC_SCS_0_BASE_ADDRESS_REMAP                      0xff0
+#define PCI_0DAC_SCS_1_BASE_ADDRESS_REMAP                      0xf04
+#define PCI_1DAC_SCS_1_BASE_ADDRESS_REMAP                      0xf84
+#define PCI_0DAC_SCS_2_BASE_ADDRESS_REMAP                      0xf08
+#define PCI_1DAC_SCS_2_BASE_ADDRESS_REMAP                      0xf88
+#define PCI_0DAC_SCS_3_BASE_ADDRESS_REMAP                      0xf0c
+#define PCI_1DAC_SCS_3_BASE_ADDRESS_REMAP                      0xf8c
+#define PCI_0DAC_CS_0_BASE_ADDRESS_REMAP                       0xf10
+#define PCI_1DAC_CS_0_BASE_ADDRESS_REMAP                       0xf90
+#define PCI_0DAC_CS_1_BASE_ADDRESS_REMAP                       0xf14
+#define PCI_1DAC_CS_1_BASE_ADDRESS_REMAP                       0xf94
+#define PCI_0DAC_CS_2_BASE_ADDRESS_REMAP                       0xf18
+#define PCI_1DAC_CS_2_BASE_ADDRESS_REMAP                       0xf98
+#define PCI_0DAC_CS_3_BASE_ADDRESS_REMAP                       0xf1c
+#define PCI_1DAC_CS_3_BASE_ADDRESS_REMAP                       0xf9c
+#define PCI_0DAC_BOOTCS_BASE_ADDRESS_REMAP                     0xf20
+#define PCI_1DAC_BOOTCS_BASE_ADDRESS_REMAP                     0xfa0
+#define PCI_0DAC_P2P_MEM0_BASE_ADDRESS_REMAP_LOW               0xf24
+#define PCI_1DAC_P2P_MEM0_BASE_ADDRESS_REMAP_LOW               0xfa4
+#define PCI_0DAC_P2P_MEM0_BASE_ADDRESS_REMAP_HIGH              0xf28
+#define PCI_1DAC_P2P_MEM0_BASE_ADDRESS_REMAP_HIGH              0xfa8
+#define PCI_0DAC_P2P_MEM1_BASE_ADDRESS_REMAP_LOW               0xf2c
+#define PCI_1DAC_P2P_MEM1_BASE_ADDRESS_REMAP_LOW               0xfac
+#define PCI_0DAC_P2P_MEM1_BASE_ADDRESS_REMAP_HIGH              0xf30
+#define PCI_1DAC_P2P_MEM1_BASE_ADDRESS_REMAP_HIGH              0xfb0
+#define PCI_0DAC_CPU_BASE_ADDRESS_REMAP                                0xf34
+#define PCI_1DAC_CPU_BASE_ADDRESS_REMAP                                0xfb4
+#define PCI_0EXPANSION_ROM_BASE_ADDRESS_REMAP                  0xf38
+#define PCI_1EXPANSION_ROM_BASE_ADDRESS_REMAP                  0xfb8
+#define PCI_0ADDRESS_DECODE_CONTROL                            0xd3c
+#define PCI_1ADDRESS_DECODE_CONTROL                            0xdbc
+
+/*
+ * PCI Control
+ */
+
+#define PCI_0COMMAND                                           0xc00
+#define PCI_1COMMAND                                           0xc80
+#define PCI_0MODE                                              0xd00
+#define PCI_1MODE                                              0xd80
+#define PCI_0TIMEOUT_RETRY                                     0xc04
+#define PCI_1TIMEOUT_RETRY                                     0xc84
+#define PCI_0READ_BUFFER_DISCARD_TIMER                         0xd04
+#define PCI_1READ_BUFFER_DISCARD_TIMER                         0xd84
+#define MSI_0TRIGGER_TIMER                                     0xc38
+#define MSI_1TRIGGER_TIMER                                     0xcb8
+#define PCI_0ARBITER_CONTROL                                   0x1d00
+#define PCI_1ARBITER_CONTROL                                   0x1d80
+/* changing untill here */
+#define PCI_0CROSS_BAR_CONTROL_LOW                              0x1d08
+#define PCI_0CROSS_BAR_CONTROL_HIGH                             0x1d0c
+#define PCI_0CROSS_BAR_TIMEOUT                                  0x1d04
+#define PCI_0READ_RESPONSE_CROSS_BAR_CONTROL_LOW                0x1d18
+#define PCI_0READ_RESPONSE_CROSS_BAR_CONTROL_HIGH               0x1d1c
+#define PCI_0SYNC_BARRIER_VIRTUAL_REGISTER                      0x1d10
+#define PCI_0P2P_CONFIGURATION                                  0x1d14
+#define PCI_0ACCESS_CONTROL_BASE_0_LOW                          0x1e00
+#define PCI_0ACCESS_CONTROL_BASE_0_HIGH                                 0x1e04
+#define PCI_0ACCESS_CONTROL_TOP_0                               0x1e08
+#define PCI_0ACCESS_CONTROL_BASE_1_LOW                          0c1e10
+#define PCI_0ACCESS_CONTROL_BASE_1_HIGH                                 0x1e14
+#define PCI_0ACCESS_CONTROL_TOP_1                               0x1e18
+#define PCI_0ACCESS_CONTROL_BASE_2_LOW                          0c1e20
+#define PCI_0ACCESS_CONTROL_BASE_2_HIGH                                 0x1e24
+#define PCI_0ACCESS_CONTROL_TOP_2                               0x1e28
+#define PCI_0ACCESS_CONTROL_BASE_3_LOW                          0c1e30
+#define PCI_0ACCESS_CONTROL_BASE_3_HIGH                                 0x1e34
+#define PCI_0ACCESS_CONTROL_TOP_3                               0x1e38
+#define PCI_0ACCESS_CONTROL_BASE_4_LOW                          0c1e40
+#define PCI_0ACCESS_CONTROL_BASE_4_HIGH                                 0x1e44
+#define PCI_0ACCESS_CONTROL_TOP_4                               0x1e48
+#define PCI_0ACCESS_CONTROL_BASE_5_LOW                          0c1e50
+#define PCI_0ACCESS_CONTROL_BASE_5_HIGH                                 0x1e54
+#define PCI_0ACCESS_CONTROL_TOP_5                               0x1e58
+#define PCI_0ACCESS_CONTROL_BASE_6_LOW                          0c1e60
+#define PCI_0ACCESS_CONTROL_BASE_6_HIGH                                 0x1e64
+#define PCI_0ACCESS_CONTROL_TOP_6                               0x1e68
+#define PCI_0ACCESS_CONTROL_BASE_7_LOW                          0c1e70
+#define PCI_0ACCESS_CONTROL_BASE_7_HIGH                                 0x1e74
+#define PCI_0ACCESS_CONTROL_TOP_7                               0x1e78
+#define PCI_1CROSS_BAR_CONTROL_LOW                              0x1d88
+#define PCI_1CROSS_BAR_CONTROL_HIGH                             0x1d8c
+#define PCI_1CROSS_BAR_TIMEOUT                                  0x1d84
+#define PCI_1READ_RESPONSE_CROSS_BAR_CONTROL_LOW                0x1d98
+#define PCI_1READ_RESPONSE_CROSS_BAR_CONTROL_HIGH               0x1d9c
+#define PCI_1SYNC_BARRIER_VIRTUAL_REGISTER                      0x1d90
+#define PCI_1P2P_CONFIGURATION                                  0x1d94
+#define PCI_1ACCESS_CONTROL_BASE_0_LOW                          0x1e80
+#define PCI_1ACCESS_CONTROL_BASE_0_HIGH                                 0x1e84
+#define PCI_1ACCESS_CONTROL_TOP_0                               0x1e88
+#define PCI_1ACCESS_CONTROL_BASE_1_LOW                          0c1e90
+#define PCI_1ACCESS_CONTROL_BASE_1_HIGH                                 0x1e94
+#define PCI_1ACCESS_CONTROL_TOP_1                               0x1e98
+#define PCI_1ACCESS_CONTROL_BASE_2_LOW                          0c1ea0
+#define PCI_1ACCESS_CONTROL_BASE_2_HIGH                                 0x1ea4
+#define PCI_1ACCESS_CONTROL_TOP_2                               0x1ea8
+#define PCI_1ACCESS_CONTROL_BASE_3_LOW                          0c1eb0
+#define PCI_1ACCESS_CONTROL_BASE_3_HIGH                                 0x1eb4
+#define PCI_1ACCESS_CONTROL_TOP_3                               0x1eb8
+#define PCI_1ACCESS_CONTROL_BASE_4_LOW                          0c1ec0
+#define PCI_1ACCESS_CONTROL_BASE_4_HIGH                                 0x1ec4
+#define PCI_1ACCESS_CONTROL_TOP_4                               0x1ec8
+#define PCI_1ACCESS_CONTROL_BASE_5_LOW                          0c1ed0
+#define PCI_1ACCESS_CONTROL_BASE_5_HIGH                                 0x1ed4
+#define PCI_1ACCESS_CONTROL_TOP_5                               0x1ed8
+#define PCI_1ACCESS_CONTROL_BASE_6_LOW                          0c1ee0
+#define PCI_1ACCESS_CONTROL_BASE_6_HIGH                                 0x1ee4
+#define PCI_1ACCESS_CONTROL_TOP_6                               0x1ee8
+#define PCI_1ACCESS_CONTROL_BASE_7_LOW                          0c1ef0
+#define PCI_1ACCESS_CONTROL_BASE_7_HIGH                                 0x1ef4
+#define PCI_1ACCESS_CONTROL_TOP_7                               0x1ef8
+
+/*
+ * PCI Snoop Control
+ */
+
+#define PCI_0SNOOP_CONTROL_BASE_0_LOW                           0x1f00
+#define PCI_0SNOOP_CONTROL_BASE_0_HIGH                          0x1f04
+#define PCI_0SNOOP_CONTROL_TOP_0                                0x1f08
+#define PCI_0SNOOP_CONTROL_BASE_1_0_LOW                                 0x1f10
+#define PCI_0SNOOP_CONTROL_BASE_1_0_HIGH                        0x1f14
+#define PCI_0SNOOP_CONTROL_TOP_1                                0x1f18
+#define PCI_0SNOOP_CONTROL_BASE_2_0_LOW                                 0x1f20
+#define PCI_0SNOOP_CONTROL_BASE_2_0_HIGH                        0x1f24
+#define PCI_0SNOOP_CONTROL_TOP_2                                0x1f28
+#define PCI_0SNOOP_CONTROL_BASE_3_0_LOW                                 0x1f30
+#define PCI_0SNOOP_CONTROL_BASE_3_0_HIGH                        0x1f34
+#define PCI_0SNOOP_CONTROL_TOP_3                                0x1f38
+#define PCI_1SNOOP_CONTROL_BASE_0_LOW                           0x1f80
+#define PCI_1SNOOP_CONTROL_BASE_0_HIGH                          0x1f84
+#define PCI_1SNOOP_CONTROL_TOP_0                                0x1f88
+#define PCI_1SNOOP_CONTROL_BASE_1_0_LOW                                 0x1f90
+#define PCI_1SNOOP_CONTROL_BASE_1_0_HIGH                        0x1f94
+#define PCI_1SNOOP_CONTROL_TOP_1                                0x1f98
+#define PCI_1SNOOP_CONTROL_BASE_2_0_LOW                                 0x1fa0
+#define PCI_1SNOOP_CONTROL_BASE_2_0_HIGH                        0x1fa4
+#define PCI_1SNOOP_CONTROL_TOP_2                                0x1fa8
+#define PCI_1SNOOP_CONTROL_BASE_3_0_LOW                                 0x1fb0
+#define PCI_1SNOOP_CONTROL_BASE_3_0_HIGH                        0x1fb4
+#define PCI_1SNOOP_CONTROL_TOP_3                                0x1fb8
+
+/*
+ * PCI Configuration Address
+ */
+
+#define PCI_0CONFIGURATION_ADDRESS                             0xcf8
+#define PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER               0xcfc
+#define PCI_1CONFIGURATION_ADDRESS                             0xc78
+#define PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER               0xc7c
+#define PCI_0INTERRUPT_ACKNOWLEDGE_VIRTUAL_REGISTER            0xc34
+#define PCI_1INTERRUPT_ACKNOWLEDGE_VIRTUAL_REGISTER            0xcb4
+
+/*
+ * PCI Error Report
+ */
+
+#define PCI_0SERR_MASK                                          0xc28
+#define PCI_0ERROR_ADDRESS_LOW                                  0x1d40
+#define PCI_0ERROR_ADDRESS_HIGH                                         0x1d44
+#define PCI_0ERROR_DATA_LOW                                     0x1d48
+#define PCI_0ERROR_DATA_HIGH                                    0x1d4c
+#define PCI_0ERROR_COMMAND                                      0x1d50
+#define PCI_0ERROR_CAUSE                                        0x1d58
+#define PCI_0ERROR_MASK                                                 0x1d5c
+
+#define PCI_1SERR_MASK                                          0xca8
+#define PCI_1ERROR_ADDRESS_LOW                                  0x1dc0
+#define PCI_1ERROR_ADDRESS_HIGH                                         0x1dc4
+#define PCI_1ERROR_DATA_LOW                                     0x1dc8
+#define PCI_1ERROR_DATA_HIGH                                    0x1dcc
+#define PCI_1ERROR_COMMAND                                      0x1dd0
+#define PCI_1ERROR_CAUSE                                        0x1dd8
+#define PCI_1ERROR_MASK                                                 0x1ddc
+
+
+/*
+ * Lslave Debug         (for internal use)
+ */
+
+#define L_SLAVE_X0_ADDRESS                                     0x1d20
+#define L_SLAVE_X0_COMMAND_AND_ID                              0x1d24
+#define L_SLAVE_X1_ADDRESS                                     0x1d28
+#define L_SLAVE_X1_COMMAND_AND_ID                              0x1d2c
+#define L_SLAVE_WRITE_DATA_LOW                                 0x1d30
+#define L_SLAVE_WRITE_DATA_HIGH                                        0x1d34
+#define L_SLAVE_WRITE_BYTE_ENABLE                              0x1d60
+#define L_SLAVE_READ_DATA_LOW                                  0x1d38
+#define L_SLAVE_READ_DATA_HIGH                                 0x1d3c
+#define L_SLAVE_READ_ID                                                0x1d64
+
+#if 0 /* Disabled because PCI_* namespace belongs to PCI subsystem ... */
+
+/*
+ * PCI Configuration Function 0
+ */
+
+#define PCI_DEVICE_AND_VENDOR_ID                               0x000
+#define PCI_STATUS_AND_COMMAND                                 0x004
+#define PCI_CLASS_CODE_AND_REVISION_ID                         0x008
+#define PCI_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE          0x00C
+#define PCI_SCS_0_BASE_ADDRESS                                 0x010
+#define PCI_SCS_1_BASE_ADDRESS                                 0x014
+#define PCI_SCS_2_BASE_ADDRESS                                 0x018
+#define PCI_SCS_3_BASE_ADDRESS                                 0x01C
+#define PCI_INTERNAL_REGISTERS_MEMORY_MAPPED_BASE_ADDRESS      0x020
+#define PCI_INTERNAL_REGISTERS_I_OMAPPED_BASE_ADDRESS          0x024
+#define PCI_SUBSYSTEM_ID_AND_SUBSYSTEM_VENDOR_ID               0x02C
+#define PCI_EXPANSION_ROM_BASE_ADDRESS_REGISTER                        0x030
+#define PCI_CAPABILTY_LIST_POINTER                             0x034
+#define PCI_INTERRUPT_PIN_AND_LINE                             0x03C
+#define PCI_POWER_MANAGEMENT_CAPABILITY                                0x040
+#define PCI_POWER_MANAGEMENT_STATUS_AND_CONTROL                        0x044
+#define PCI_VPD_ADDRESS                                                0x048
+#define PCI_VPD_DATA                                           0X04c
+#define PCI_MSI_MESSAGE_CONTROL                                        0x050
+#define PCI_MSI_MESSAGE_ADDRESS                                        0x054
+#define PCI_MSI_MESSAGE_UPPER_ADDRESS                          0x058
+#define PCI_MSI_MESSAGE_DATA                                   0x05c
+#define PCI_COMPACT_PCI_HOT_SWAP_CAPABILITY                    0x058
+
+/*
+ * PCI Configuration Function 1
+ */
+
+#define PCI_CS_0_BASE_ADDRESS                                  0x110
+#define PCI_CS_1_BASE_ADDRESS                                  0x114
+#define PCI_CS_2_BASE_ADDRESS                                  0x118
+#define PCI_CS_3_BASE_ADDRESS                                  0x11c
+#define PCI_BOOTCS_BASE_ADDRESS                                        0x120
+
+/*
+ * PCI Configuration Function 2
+ */
+
+#define PCI_P2P_MEM0_BASE_ADDRESS                              0x210
+#define PCI_P2P_MEM1_BASE_ADDRESS                              0x214
+#define PCI_P2P_I_O_BASE_ADDRESS                               0x218
+#define PCI_CPU_BASE_ADDRESS                                   0x21c
+
+/*
+ * PCI Configuration Function 4
+ */
+
+#define PCI_DAC_SCS_0_BASE_ADDRESS_LOW                         0x410
+#define PCI_DAC_SCS_0_BASE_ADDRESS_HIGH                                0x414
+#define PCI_DAC_SCS_1_BASE_ADDRESS_LOW                         0x418
+#define PCI_DAC_SCS_1_BASE_ADDRESS_HIGH                                0x41c
+#define PCI_DAC_P2P_MEM0_BASE_ADDRESS_LOW                      0x420
+#define PCI_DAC_P2P_MEM0_BASE_ADDRESS_HIGH                     0x424
+
+
+/*
+ * PCI Configuration Function 5
+ */
+
+#define PCI_DAC_SCS_2_BASE_ADDRESS_LOW                         0x510
+#define PCI_DAC_SCS_2_BASE_ADDRESS_HIGH                                0x514
+#define PCI_DAC_SCS_3_BASE_ADDRESS_LOW                         0x518
+#define PCI_DAC_SCS_3_BASE_ADDRESS_HIGH                                0x51c
+#define PCI_DAC_P2P_MEM1_BASE_ADDRESS_LOW                      0x520
+#define PCI_DAC_P2P_MEM1_BASE_ADDRESS_HIGH                     0x524
+
+
+/*
+ * PCI Configuration Function 6
+ */
+
+#define PCI_DAC_CS_0_BASE_ADDRESS_LOW                          0x610
+#define PCI_DAC_CS_0_BASE_ADDRESS_HIGH                         0x614
+#define PCI_DAC_CS_1_BASE_ADDRESS_LOW                          0x618
+#define PCI_DAC_CS_1_BASE_ADDRESS_HIGH                         0x61c
+#define PCI_DAC_CS_2_BASE_ADDRESS_LOW                          0x620
+#define PCI_DAC_CS_2_BASE_ADDRESS_HIGH                         0x624
+
+/*
+ * PCI Configuration Function 7
+ */
+
+#define PCI_DAC_CS_3_BASE_ADDRESS_LOW                          0x710
+#define PCI_DAC_CS_3_BASE_ADDRESS_HIGH                         0x714
+#define PCI_DAC_BOOTCS_BASE_ADDRESS_LOW                                0x718
+#define PCI_DAC_BOOTCS_BASE_ADDRESS_HIGH                       0x71c
+#define PCI_DAC_CPU_BASE_ADDRESS_LOW                           0x720
+#define PCI_DAC_CPU_BASE_ADDRESS_HIGH                          0x724
+#endif
+
+/*
+ * Interrupts
+ */
+
+#define LOW_INTERRUPT_CAUSE_REGISTER                           0xc18
+#define HIGH_INTERRUPT_CAUSE_REGISTER                          0xc68
+#define CPU_INTERRUPT_MASK_REGISTER_LOW                                0xc1c
+#define CPU_INTERRUPT_MASK_REGISTER_HIGH                       0xc6c
+#define CPU_SELECT_CAUSE_REGISTER                              0xc70
+#define PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW                 0xc24
+#define PCI_0INTERRUPT_CAUSE_MASK_REGISTER_HIGH                        0xc64
+#define PCI_0SELECT_CAUSE                                      0xc74
+#define PCI_1INTERRUPT_CAUSE_MASK_REGISTER_LOW                 0xca4
+#define PCI_1INTERRUPT_CAUSE_MASK_REGISTER_HIGH                        0xce4
+#define PCI_1SELECT_CAUSE                                      0xcf4
+#define CPU_INT_0_MASK                                         0xe60
+#define CPU_INT_1_MASK                                         0xe64
+#define CPU_INT_2_MASK                                         0xe68
+#define CPU_INT_3_MASK                                         0xe6c
+
+/*
+ * I20 Support registers
+ */
+
+#define INBOUND_MESSAGE_REGISTER0_PCI0_SIDE                    0x010
+#define INBOUND_MESSAGE_REGISTER1_PCI0_SIDE                    0x014
+#define OUTBOUND_MESSAGE_REGISTER0_PCI0_SIDE                   0x018
+#define OUTBOUND_MESSAGE_REGISTER1_PCI0_SIDE                   0x01C
+#define INBOUND_DOORBELL_REGISTER_PCI0_SIDE                    0x020
+#define INBOUND_INTERRUPT_CAUSE_REGISTER_PCI0_SIDE             0x024
+#define INBOUND_INTERRUPT_MASK_REGISTER_PCI0_SIDE              0x028
+#define OUTBOUND_DOORBELL_REGISTER_PCI0_SIDE                   0x02C
+#define OUTBOUND_INTERRUPT_CAUSE_REGISTER_PCI0_SIDE            0x030
+#define OUTBOUND_INTERRUPT_MASK_REGISTER_PCI0_SIDE             0x034
+#define INBOUND_QUEUE_PORT_VIRTUAL_REGISTER_PCI0_SIDE          0x040
+#define OUTBOUND_QUEUE_PORT_VIRTUAL_REGISTER_PCI0_SIDE         0x044
+#define QUEUE_CONTROL_REGISTER_PCI0_SIDE                       0x050
+#define QUEUE_BASE_ADDRESS_REGISTER_PCI0_SIDE                  0x054
+#define INBOUND_FREE_HEAD_POINTER_REGISTER_PCI0_SIDE           0x060
+#define INBOUND_FREE_TAIL_POINTER_REGISTER_PCI0_SIDE           0x064
+#define INBOUND_POST_HEAD_POINTER_REGISTER_PCI0_SIDE           0x068
+#define INBOUND_POST_TAIL_POINTER_REGISTER_PCI0_SIDE           0x06C
+#define OUTBOUND_FREE_HEAD_POINTER_REGISTER_PCI0_SIDE          0x070
+#define OUTBOUND_FREE_TAIL_POINTER_REGISTER_PCI0_SIDE          0x074
+#define OUTBOUND_POST_HEAD_POINTER_REGISTER_PCI0_SIDE          0x0F8
+#define OUTBOUND_POST_TAIL_POINTER_REGISTER_PCI0_SIDE          0x0FC
+
+#define INBOUND_MESSAGE_REGISTER0_PCI1_SIDE                    0x090
+#define INBOUND_MESSAGE_REGISTER1_PCI1_SIDE                    0x094
+#define OUTBOUND_MESSAGE_REGISTER0_PCI1_SIDE                   0x098
+#define OUTBOUND_MESSAGE_REGISTER1_PCI1_SIDE                   0x09C
+#define INBOUND_DOORBELL_REGISTER_PCI1_SIDE                    0x0A0
+#define INBOUND_INTERRUPT_CAUSE_REGISTER_PCI1_SIDE             0x0A4
+#define INBOUND_INTERRUPT_MASK_REGISTER_PCI1_SIDE              0x0A8
+#define OUTBOUND_DOORBELL_REGISTER_PCI1_SIDE                   0x0AC
+#define OUTBOUND_INTERRUPT_CAUSE_REGISTER_PCI1_SIDE            0x0B0
+#define OUTBOUND_INTERRUPT_MASK_REGISTER_PCI1_SIDE             0x0B4
+#define INBOUND_QUEUE_PORT_VIRTUAL_REGISTER_PCI1_SIDE          0x0C0
+#define OUTBOUND_QUEUE_PORT_VIRTUAL_REGISTER_PCI1_SIDE         0x0C4
+#define QUEUE_CONTROL_REGISTER_PCI1_SIDE                       0x0D0
+#define QUEUE_BASE_ADDRESS_REGISTER_PCI1_SIDE                  0x0D4
+#define INBOUND_FREE_HEAD_POINTER_REGISTER_PCI1_SIDE           0x0E0
+#define INBOUND_FREE_TAIL_POINTER_REGISTER_PCI1_SIDE           0x0E4
+#define INBOUND_POST_HEAD_POINTER_REGISTER_PCI1_SIDE           0x0E8
+#define INBOUND_POST_TAIL_POINTER_REGISTER_PCI1_SIDE           0x0EC
+#define OUTBOUND_FREE_HEAD_POINTER_REGISTER_PCI1_SIDE          0x0F0
+#define OUTBOUND_FREE_TAIL_POINTER_REGISTER_PCI1_SIDE          0x0F4
+#define OUTBOUND_POST_HEAD_POINTER_REGISTER_PCI1_SIDE          0x078
+#define OUTBOUND_POST_TAIL_POINTER_REGISTER_PCI1_SIDE          0x07C
+
+#define INBOUND_MESSAGE_REGISTER0_CPU0_SIDE                    0X1C10
+#define INBOUND_MESSAGE_REGISTER1_CPU0_SIDE                    0X1C14
+#define OUTBOUND_MESSAGE_REGISTER0_CPU0_SIDE                   0X1C18
+#define OUTBOUND_MESSAGE_REGISTER1_CPU0_SIDE                   0X1C1C
+#define INBOUND_DOORBELL_REGISTER_CPU0_SIDE                    0X1C20
+#define INBOUND_INTERRUPT_CAUSE_REGISTER_CPU0_SIDE             0X1C24
+#define INBOUND_INTERRUPT_MASK_REGISTER_CPU0_SIDE              0X1C28
+#define OUTBOUND_DOORBELL_REGISTER_CPU0_SIDE                   0X1C2C
+#define OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU0_SIDE            0X1C30
+#define OUTBOUND_INTERRUPT_MASK_REGISTER_CPU0_SIDE             0X1C34
+#define INBOUND_QUEUE_PORT_VIRTUAL_REGISTER_CPU0_SIDE          0X1C40
+#define OUTBOUND_QUEUE_PORT_VIRTUAL_REGISTER_CPU0_SIDE         0X1C44
+#define QUEUE_CONTROL_REGISTER_CPU0_SIDE                       0X1C50
+#define QUEUE_BASE_ADDRESS_REGISTER_CPU0_SIDE                  0X1C54
+#define INBOUND_FREE_HEAD_POINTER_REGISTER_CPU0_SIDE           0X1C60
+#define INBOUND_FREE_TAIL_POINTER_REGISTER_CPU0_SIDE           0X1C64
+#define INBOUND_POST_HEAD_POINTER_REGISTER_CPU0_SIDE           0X1C68
+#define INBOUND_POST_TAIL_POINTER_REGISTER_CPU0_SIDE           0X1C6C
+#define OUTBOUND_FREE_HEAD_POINTER_REGISTER_CPU0_SIDE          0X1C70
+#define OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU0_SIDE          0X1C74
+#define OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU0_SIDE          0X1CF8
+#define OUTBOUND_POST_TAIL_POINTER_REGISTER_CPU0_SIDE          0X1CFC
+
+#define INBOUND_MESSAGE_REGISTER0_CPU1_SIDE                    0X1C90
+#define INBOUND_MESSAGE_REGISTER1_CPU1_SIDE                    0X1C94
+#define OUTBOUND_MESSAGE_REGISTER0_CPU1_SIDE                   0X1C98
+#define OUTBOUND_MESSAGE_REGISTER1_CPU1_SIDE                   0X1C9C
+#define INBOUND_DOORBELL_REGISTER_CPU1_SIDE                    0X1CA0
+#define INBOUND_INTERRUPT_CAUSE_REGISTER_CPU1_SIDE             0X1CA4
+#define INBOUND_INTERRUPT_MASK_REGISTER_CPU1_SIDE              0X1CA8
+#define OUTBOUND_DOORBELL_REGISTER_CPU1_SIDE                   0X1CAC
+#define OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU1_SIDE            0X1CB0
+#define OUTBOUND_INTERRUPT_MASK_REGISTER_CPU1_SIDE             0X1CB4
+#define INBOUND_QUEUE_PORT_VIRTUAL_REGISTER_CPU1_SIDE          0X1CC0
+#define OUTBOUND_QUEUE_PORT_VIRTUAL_REGISTER_CPU1_SIDE         0X1CC4
+#define QUEUE_CONTROL_REGISTER_CPU1_SIDE                       0X1CD0
+#define QUEUE_BASE_ADDRESS_REGISTER_CPU1_SIDE                  0X1CD4
+#define INBOUND_FREE_HEAD_POINTER_REGISTER_CPU1_SIDE           0X1CE0
+#define INBOUND_FREE_TAIL_POINTER_REGISTER_CPU1_SIDE           0X1CE4
+#define INBOUND_POST_HEAD_POINTER_REGISTER_CPU1_SIDE           0X1CE8
+#define INBOUND_POST_TAIL_POINTER_REGISTER_CPU1_SIDE           0X1CEC
+#define OUTBOUND_FREE_HEAD_POINTER_REGISTER_CPU1_SIDE          0X1CF0
+#define OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU1_SIDE          0X1CF4
+#define OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU1_SIDE          0X1C78
+#define OUTBOUND_POST_TAIL_POINTER_REGISTER_CPU1_SIDE          0X1C7C
+
+/*
+ * Communication Unit Registers
+ */
+
+#define ETHERNET_0_ADDRESS_CONTROL_LOW
+#define ETHERNET_0_ADDRESS_CONTROL_HIGH                                0xf204
+#define ETHERNET_0_RECEIVE_BUFFER_PCI_HIGH_ADDRESS             0xf208
+#define ETHERNET_0_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS            0xf20c
+#define ETHERNET_0_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS         0xf210
+#define ETHERNET_0_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS                0xf214
+#define ETHERNET_0_HASH_TABLE_PCI_HIGH_ADDRESS                 0xf218
+#define ETHERNET_1_ADDRESS_CONTROL_LOW                         0xf220
+#define ETHERNET_1_ADDRESS_CONTROL_HIGH                                0xf224
+#define ETHERNET_1_RECEIVE_BUFFER_PCI_HIGH_ADDRESS             0xf228
+#define ETHERNET_1_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS            0xf22c
+#define ETHERNET_1_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS         0xf230
+#define ETHERNET_1_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS                0xf234
+#define ETHERNET_1_HASH_TABLE_PCI_HIGH_ADDRESS                 0xf238
+#define ETHERNET_2_ADDRESS_CONTROL_LOW                         0xf240
+#define ETHERNET_2_ADDRESS_CONTROL_HIGH                                0xf244
+#define ETHERNET_2_RECEIVE_BUFFER_PCI_HIGH_ADDRESS             0xf248
+#define ETHERNET_2_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS            0xf24c
+#define ETHERNET_2_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS         0xf250
+#define ETHERNET_2_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS                0xf254
+#define ETHERNET_2_HASH_TABLE_PCI_HIGH_ADDRESS                 0xf258
+#define MPSC_0_ADDRESS_CONTROL_LOW                             0xf280
+#define MPSC_0_ADDRESS_CONTROL_HIGH                            0xf284
+#define MPSC_0_RECEIVE_BUFFER_PCI_HIGH_ADDRESS                 0xf288
+#define MPSC_0_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS                        0xf28c
+#define MPSC_0_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS             0xf290
+#define MPSC_0_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS            0xf294
+#define MPSC_1_ADDRESS_CONTROL_LOW                             0xf2a0
+#define MPSC_1_ADDRESS_CONTROL_HIGH                            0xf2a4
+#define MPSC_1_RECEIVE_BUFFER_PCI_HIGH_ADDRESS                 0xf2a8
+#define MPSC_1_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS                        0xf2ac
+#define MPSC_1_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS             0xf2b0
+#define MPSC_1_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS            0xf2b4
+#define MPSC_2_ADDRESS_CONTROL_LOW                             0xf2c0
+#define MPSC_2_ADDRESS_CONTROL_HIGH                            0xf2c4
+#define MPSC_2_RECEIVE_BUFFER_PCI_HIGH_ADDRESS                 0xf2c8
+#define MPSC_2_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS                        0xf2cc
+#define MPSC_2_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS             0xf2d0
+#define MPSC_2_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS            0xf2d4
+#define SERIAL_INIT_PCI_HIGH_ADDRESS                           0xf320
+#define SERIAL_INIT_LAST_DATA                                  0xf324
+#define SERIAL_INIT_STATUS_AND_CONTROL                         0xf328
+#define COMM_UNIT_ARBITER_CONTROL                              0xf300
+#define COMM_UNIT_CROSS_BAR_TIMEOUT                            0xf304
+#define COMM_UNIT_INTERRUPT_CAUSE                              0xf310
+#define COMM_UNIT_INTERRUPT_MASK                               0xf314
+#define COMM_UNIT_ERROR_ADDRESS                                        0xf314
+
+/*
+ * Cunit Debug (for internal use)
+ */
+
+#define CUNIT_ADDRESS                                          0xf340
+#define CUNIT_COMMAND_AND_ID                                   0xf344
+#define CUNIT_WRITE_DATA_LOW                                   0xf348
+#define CUNIT_WRITE_DATA_HIGH                                  0xf34c
+#define CUNIT_WRITE_BYTE_ENABLE                                        0xf358
+#define CUNIT_READ_DATA_LOW                                    0xf350
+#define CUNIT_READ_DATA_HIGH                                   0xf354
+#define CUNIT_READ_ID                                          0xf35c
+
+/*
+ * Fast Ethernet Unit Registers
+ */
+
+/* Ethernet */
+
+#define ETHERNET_PHY_ADDRESS_REGISTER                          0x2000
+#define ETHERNET_SMI_REGISTER                                  0x2010
+
+/* Ethernet 0 */
+
+#define ETHERNET0_PORT_CONFIGURATION_REGISTER                  0x2400
+#define ETHERNET0_PORT_CONFIGURATION_EXTEND_REGISTER           0x2408
+#define ETHERNET0_PORT_COMMAND_REGISTER                                0x2410
+#define ETHERNET0_PORT_STATUS_REGISTER                         0x2418
+#define ETHERNET0_SERIAL_PARAMETRS_REGISTER                    0x2420
+#define ETHERNET0_HASH_TABLE_POINTER_REGISTER                  0x2428
+#define ETHERNET0_FLOW_CONTROL_SOURCE_ADDRESS_LOW              0x2430
+#define ETHERNET0_FLOW_CONTROL_SOURCE_ADDRESS_HIGH             0x2438
+#define ETHERNET0_SDMA_CONFIGURATION_REGISTER                  0x2440
+#define ETHERNET0_SDMA_COMMAND_REGISTER                                0x2448
+#define ETHERNET0_INTERRUPT_CAUSE_REGISTER                     0x2450
+#define ETHERNET0_INTERRUPT_MASK_REGISTER                      0x2458
+#define ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER0                 0x2480
+#define ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER1                 0x2484
+#define ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER2                 0x2488
+#define ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER3                 0x248c
+#define ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER0               0x24a0
+#define ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER1               0x24a4
+#define ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER2               0x24a8
+#define ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER3               0x24ac
+#define ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER0               0x24e0
+#define ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER1               0x24e4
+#define ETHERNET0_MIB_COUNTER_BASE                             0x2500
+
+/* Ethernet 1 */
+
+#define ETHERNET1_PORT_CONFIGURATION_REGISTER                  0x2800
+#define ETHERNET1_PORT_CONFIGURATION_EXTEND_REGISTER           0x2808
+#define ETHERNET1_PORT_COMMAND_REGISTER                                0x2810
+#define ETHERNET1_PORT_STATUS_REGISTER                         0x2818
+#define ETHERNET1_SERIAL_PARAMETRS_REGISTER                    0x2820
+#define ETHERNET1_HASH_TABLE_POINTER_REGISTER                  0x2828
+#define ETHERNET1_FLOW_CONTROL_SOURCE_ADDRESS_LOW              0x2830
+#define ETHERNET1_FLOW_CONTROL_SOURCE_ADDRESS_HIGH             0x2838
+#define ETHERNET1_SDMA_CONFIGURATION_REGISTER                  0x2840
+#define ETHERNET1_SDMA_COMMAND_REGISTER                                0x2848
+#define ETHERNET1_INTERRUPT_CAUSE_REGISTER                     0x2850
+#define ETHERNET1_INTERRUPT_MASK_REGISTER                      0x2858
+#define ETHERNET1_FIRST_RX_DESCRIPTOR_POINTER0                 0x2880
+#define ETHERNET1_FIRST_RX_DESCRIPTOR_POINTER1                 0x2884
+#define ETHERNET1_FIRST_RX_DESCRIPTOR_POINTER2                 0x2888
+#define ETHERNET1_FIRST_RX_DESCRIPTOR_POINTER3                 0x288c
+#define ETHERNET1_CURRENT_RX_DESCRIPTOR_POINTER0               0x28a0
+#define ETHERNET1_CURRENT_RX_DESCRIPTOR_POINTER1               0x28a4
+#define ETHERNET1_CURRENT_RX_DESCRIPTOR_POINTER2               0x28a8
+#define ETHERNET1_CURRENT_RX_DESCRIPTOR_POINTER3               0x28ac
+#define ETHERNET1_CURRENT_TX_DESCRIPTOR_POINTER0               0x28e0
+#define ETHERNET1_CURRENT_TX_DESCRIPTOR_POINTER1               0x28e4
+#define ETHERNET1_MIB_COUNTER_BASE                             0x2900
+
+/* Ethernet 2 */
+
+#define ETHERNET2_PORT_CONFIGURATION_REGISTER                  0x2c00
+#define ETHERNET2_PORT_CONFIGURATION_EXTEND_REGISTER           0x2c08
+#define ETHERNET2_PORT_COMMAND_REGISTER                                0x2c10
+#define ETHERNET2_PORT_STATUS_REGISTER                         0x2c18
+#define ETHERNET2_SERIAL_PARAMETRS_REGISTER                    0x2c20
+#define ETHERNET2_HASH_TABLE_POINTER_REGISTER                  0x2c28
+#define ETHERNET2_FLOW_CONTROL_SOURCE_ADDRESS_LOW              0x2c30
+#define ETHERNET2_FLOW_CONTROL_SOURCE_ADDRESS_HIGH             0x2c38
+#define ETHERNET2_SDMA_CONFIGURATION_REGISTER                  0x2c40
+#define ETHERNET2_SDMA_COMMAND_REGISTER                                0x2c48
+#define ETHERNET2_INTERRUPT_CAUSE_REGISTER                     0x2c50
+#define ETHERNET2_INTERRUPT_MASK_REGISTER                      0x2c58
+#define ETHERNET2_FIRST_RX_DESCRIPTOR_POINTER0                 0x2c80
+#define ETHERNET2_FIRST_RX_DESCRIPTOR_POINTER1                 0x2c84
+#define ETHERNET2_FIRST_RX_DESCRIPTOR_POINTER2                 0x2c88
+#define ETHERNET2_FIRST_RX_DESCRIPTOR_POINTER3                 0x2c8c
+#define ETHERNET2_CURRENT_RX_DESCRIPTOR_POINTER0               0x2ca0
+#define ETHERNET2_CURRENT_RX_DESCRIPTOR_POINTER1               0x2ca4
+#define ETHERNET2_CURRENT_RX_DESCRIPTOR_POINTER2               0x2ca8
+#define ETHERNET2_CURRENT_RX_DESCRIPTOR_POINTER3               0x2cac
+#define ETHERNET2_CURRENT_TX_DESCRIPTOR_POINTER0               0x2ce0
+#define ETHERNET2_CURRENT_TX_DESCRIPTOR_POINTER1               0x2ce4
+#define ETHERNET2_MIB_COUNTER_BASE                             0x2d00
+
+/*
+ * SDMA Registers
+ */
+
+#define SDMA_GROUP_CONFIGURATION_REGISTER                      0xb1f0
+#define CHANNEL0_CONFIGURATION_REGISTER                                0x4000
+#define CHANNEL0_COMMAND_REGISTER                              0x4008
+#define CHANNEL0_RX_CMD_STATUS                                 0x4800
+#define CHANNEL0_RX_PACKET_AND_BUFFER_SIZES                    0x4804
+#define CHANNEL0_RX_BUFFER_POINTER                             0x4808
+#define CHANNEL0_RX_NEXT_POINTER                               0x480c
+#define CHANNEL0_CURRENT_RX_DESCRIPTOR_POINTER                 0x4810
+#define CHANNEL0_TX_CMD_STATUS                                 0x4C00
+#define CHANNEL0_TX_PACKET_SIZE                                        0x4C04
+#define CHANNEL0_TX_BUFFER_POINTER                             0x4C08
+#define CHANNEL0_TX_NEXT_POINTER                               0x4C0c
+#define CHANNEL0_CURRENT_TX_DESCRIPTOR_POINTER                 0x4c10
+#define CHANNEL0_FIRST_TX_DESCRIPTOR_POINTER                   0x4c14
+#define CHANNEL1_CONFIGURATION_REGISTER                                0x6000
+#define CHANNEL1_COMMAND_REGISTER                              0x6008
+#define CHANNEL1_RX_CMD_STATUS                                 0x6800
+#define CHANNEL1_RX_PACKET_AND_BUFFER_SIZES                    0x6804
+#define CHANNEL1_RX_BUFFER_POINTER                             0x6808
+#define CHANNEL1_RX_NEXT_POINTER                               0x680c
+#define CHANNEL1_CURRENT_RX_DESCRIPTOR_POINTER                 0x6810
+#define CHANNEL1_TX_CMD_STATUS                                 0x6C00
+#define CHANNEL1_TX_PACKET_SIZE                                        0x6C04
+#define CHANNEL1_TX_BUFFER_POINTER                             0x6C08
+#define CHANNEL1_TX_NEXT_POINTER                               0x6C0c
+#define CHANNEL1_CURRENT_RX_DESCRIPTOR_POINTER                 0x6810
+#define CHANNEL1_CURRENT_TX_DESCRIPTOR_POINTER                 0x6c10
+#define CHANNEL1_FIRST_TX_DESCRIPTOR_POINTER                   0x6c14
+
+/* SDMA Interrupt */
+
+#define SDMA_CAUSE                                             0xb820
+#define SDMA_MASK                                              0xb8a0
+
+
+/*
+ * Baude Rate Generators Registers
+ */
+
+/* BRG 0 */
+
+#define BRG0_CONFIGURATION_REGISTER                            0xb200
+#define BRG0_BAUDE_TUNING_REGISTER                             0xb204
+
+/* BRG 1 */
+
+#define BRG1_CONFIGURATION_REGISTER                            0xb208
+#define BRG1_BAUDE_TUNING_REGISTER                             0xb20c
+
+/* BRG 2 */
+
+#define BRG2_CONFIGURATION_REGISTER                            0xb210
+#define BRG2_BAUDE_TUNING_REGISTER                             0xb214
+
+/* BRG Interrupts */
+
+#define BRG_CAUSE_REGISTER                                     0xb834
+#define BRG_MASK_REGISTER                                      0xb8b4
+
+/* MISC */
+
+#define MAIN_ROUTING_REGISTER                                  0xb400
+#define RECEIVE_CLOCK_ROUTING_REGISTER                         0xb404
+#define TRANSMIT_CLOCK_ROUTING_REGISTER                                0xb408
+#define COMM_UNIT_ARBITER_CONFIGURATION_REGISTER               0xb40c
+#define WATCHDOG_CONFIGURATION_REGISTER                                0xb410
+#define WATCHDOG_VALUE_REGISTER                                        0xb414
+
+
+/*
+ * Flex TDM Registers
+ */
+
+/* FTDM Port */
+
+#define FLEXTDM_TRANSMIT_READ_POINTER                          0xa800
+#define FLEXTDM_RECEIVE_READ_POINTER                           0xa804
+#define FLEXTDM_CONFIGURATION_REGISTER                         0xa808
+#define FLEXTDM_AUX_CHANNELA_TX_REGISTER                       0xa80c
+#define FLEXTDM_AUX_CHANNELA_RX_REGISTER                       0xa810
+#define FLEXTDM_AUX_CHANNELB_TX_REGISTER                       0xa814
+#define FLEXTDM_AUX_CHANNELB_RX_REGISTER                       0xa818
+
+/* FTDM Interrupts */
+
+#define FTDM_CAUSE_REGISTER                                    0xb830
+#define FTDM_MASK_REGISTER                                     0xb8b0
+
+
+/*
+ * GPP Interface Registers
+ */
+
+#define GPP_IO_CONTROL                                         0xf100
+#define GPP_LEVEL_CONTROL                                      0xf110
+#define GPP_VALUE                                              0xf104
+#define GPP_INTERRUPT_CAUSE                                    0xf108
+#define GPP_INTERRUPT_MASK                                     0xf10c
+
+#define MPP_CONTROL0                                           0xf000
+#define MPP_CONTROL1                                           0xf004
+#define MPP_CONTROL2                                           0xf008
+#define MPP_CONTROL3                                           0xf00c
+#define DEBUG_PORT_MULTIPLEX                                   0xf014
+#define SERIAL_PORT_MULTIPLEX                                  0xf010
+
+/*
+ * I2C Registers
+ */
+
+#define I2C_SLAVE_ADDRESS                                      0xc000
+#define I2C_EXTENDED_SLAVE_ADDRESS                             0xc040
+#define I2C_DATA                                               0xc004
+#define I2C_CONTROL                                            0xc008
+#define I2C_STATUS_BAUDE_RATE                                  0xc00C
+#define I2C_SOFT_RESET                                         0xc01c
+
+/*
+ * MPSC Registers
+ */
+
+/*
+ * MPSC0
+ */
+
+#define MPSC0_MAIN_CONFIGURATION_LOW                           0x8000
+#define MPSC0_MAIN_CONFIGURATION_HIGH                          0x8004
+#define MPSC0_PROTOCOL_CONFIGURATION                           0x8008
+#define CHANNEL0_REGISTER1                                     0x800c
+#define CHANNEL0_REGISTER2                                     0x8010
+#define CHANNEL0_REGISTER3                                     0x8014
+#define CHANNEL0_REGISTER4                                     0x8018
+#define CHANNEL0_REGISTER5                                     0x801c
+#define CHANNEL0_REGISTER6                                     0x8020
+#define CHANNEL0_REGISTER7                                     0x8024
+#define CHANNEL0_REGISTER8                                     0x8028
+#define CHANNEL0_REGISTER9                                     0x802c
+#define CHANNEL0_REGISTER10                                    0x8030
+#define CHANNEL0_REGISTER11                                    0x8034
+
+/*
+ * MPSC1
+ */
+
+#define MPSC1_MAIN_CONFIGURATION_LOW                           0x9000
+#define MPSC1_MAIN_CONFIGURATION_HIGH                          0x9004
+#define MPSC1_PROTOCOL_CONFIGURATION                           0x9008
+#define CHANNEL1_REGISTER1                                     0x900c
+#define CHANNEL1_REGISTER2                                     0x9010
+#define CHANNEL1_REGISTER3                                     0x9014
+#define CHANNEL1_REGISTER4                                     0x9018
+#define CHANNEL1_REGISTER5                                     0x901c
+#define CHANNEL1_REGISTER6                                     0x9020
+#define CHANNEL1_REGISTER7                                     0x9024
+#define CHANNEL1_REGISTER8                                     0x9028
+#define CHANNEL1_REGISTER9                                     0x902c
+#define CHANNEL1_REGISTER10                                    0x9030
+#define CHANNEL1_REGISTER11                                    0x9034
+
+/*
+ * MPSCs Interupts
+ */
+
+#define MPSC0_CAUSE                                            0xb804
+#define MPSC0_MASK                                             0xb884
+#define MPSC1_CAUSE                                            0xb80c
+#define MPSC1_MASK                                             0xb88c
+
+#endif /* __ASM_MIPS_MV64240_H */
diff --git a/include/asm-ppc/cpm2.h b/include/asm-ppc/cpm2.h
new file mode 100644 (file)
index 0000000..dc899d3
--- /dev/null
@@ -0,0 +1,1041 @@
+/*
+ * Communication Processor Module v2.
+ *
+ * This file contains structures and information for the communication
+ * processor channels found in the dual port RAM or parameter RAM.
+ * All CPM control and status is available through the CPM2 internal
+ * memory map.  See immap_cpm2.h for details.
+ */
+#ifdef __KERNEL__
+#ifndef __CPM2__
+#define __CPM2__
+
+#include <asm/immap_cpm2.h>
+
+/* CPM Command register.
+*/
+#define CPM_CR_RST     ((uint)0x80000000)
+#define CPM_CR_PAGE    ((uint)0x7c000000)
+#define CPM_CR_SBLOCK  ((uint)0x03e00000)
+#define CPM_CR_FLG     ((uint)0x00010000)
+#define CPM_CR_MCN     ((uint)0x00003fc0)
+#define CPM_CR_OPCODE  ((uint)0x0000000f)
+
+/* Device sub-block and page codes.
+*/
+#define CPM_CR_SCC1_SBLOCK     (0x04)
+#define CPM_CR_SCC2_SBLOCK     (0x05)
+#define CPM_CR_SCC3_SBLOCK     (0x06)
+#define CPM_CR_SCC4_SBLOCK     (0x07)
+#define CPM_CR_SMC1_SBLOCK     (0x08)
+#define CPM_CR_SMC2_SBLOCK     (0x09)
+#define CPM_CR_SPI_SBLOCK      (0x0a)
+#define CPM_CR_I2C_SBLOCK      (0x0b)
+#define CPM_CR_TIMER_SBLOCK    (0x0f)
+#define CPM_CR_RAND_SBLOCK     (0x0e)
+#define CPM_CR_FCC1_SBLOCK     (0x10)
+#define CPM_CR_FCC2_SBLOCK     (0x11)
+#define CPM_CR_FCC3_SBLOCK     (0x12)
+#define CPM_CR_IDMA1_SBLOCK    (0x14)
+#define CPM_CR_IDMA2_SBLOCK    (0x15)
+#define CPM_CR_IDMA3_SBLOCK    (0x16)
+#define CPM_CR_IDMA4_SBLOCK    (0x17)
+#define CPM_CR_MCC1_SBLOCK     (0x1c)
+
+#define CPM_CR_SCC1_PAGE       (0x00)
+#define CPM_CR_SCC2_PAGE       (0x01)
+#define CPM_CR_SCC3_PAGE       (0x02)
+#define CPM_CR_SCC4_PAGE       (0x03)
+#define CPM_CR_SMC1_PAGE       (0x07)
+#define CPM_CR_SMC2_PAGE       (0x08)
+#define CPM_CR_SPI_PAGE                (0x09)
+#define CPM_CR_I2C_PAGE                (0x0a)
+#define CPM_CR_TIMER_PAGE      (0x0a)
+#define CPM_CR_RAND_PAGE       (0x0a)
+#define CPM_CR_FCC1_PAGE       (0x04)
+#define CPM_CR_FCC2_PAGE       (0x05)
+#define CPM_CR_FCC3_PAGE       (0x06)
+#define CPM_CR_IDMA1_PAGE      (0x07)
+#define CPM_CR_IDMA2_PAGE      (0x08)
+#define CPM_CR_IDMA3_PAGE      (0x09)
+#define CPM_CR_IDMA4_PAGE      (0x0a)
+#define CPM_CR_MCC1_PAGE       (0x07)
+#define CPM_CR_MCC2_PAGE       (0x08)
+
+/* Some opcodes (there are more...later)
+*/
+#define CPM_CR_INIT_TRX                ((ushort)0x0000)
+#define CPM_CR_INIT_RX         ((ushort)0x0001)
+#define CPM_CR_INIT_TX         ((ushort)0x0002)
+#define CPM_CR_HUNT_MODE       ((ushort)0x0003)
+#define CPM_CR_STOP_TX         ((ushort)0x0004)
+#define CPM_CR_RESTART_TX      ((ushort)0x0006)
+#define CPM_CR_SET_GADDR       ((ushort)0x0008)
+#define CPM_CR_START_IDMA      ((ushort)0x0009)
+#define CPM_CR_STOP_IDMA       ((ushort)0x000b)
+
+#define mk_cr_cmd(PG, SBC, MCN, OP) \
+       ((PG << 26) | (SBC << 21) | (MCN << 6) | OP)
+
+/* Dual Port RAM addresses.  The first 16K is available for almost
+ * any CPM use, so we put the BDs there.  The first 128 bytes are
+ * used for SMC1 and SMC2 parameter RAM, so we start allocating
+ * BDs above that.  All of this must change when we start
+ * downloading RAM microcode.
+ */
+#define CPM_DATAONLY_BASE      ((uint)128)
+#define CPM_DP_NOSPACE         ((uint)0x7fffffff)
+#ifdef CONFIG_8272
+#define CPM_DATAONLY_SIZE      ((uint)(8 * 1024) - CPM_DATAONLY_BASE)
+#define CPM_FCC_SPECIAL_BASE   ((uint)0x00009000)
+#else
+#define CPM_DATAONLY_SIZE      ((uint)(16 * 1024) - CPM_DATAONLY_BASE)
+#define CPM_FCC_SPECIAL_BASE   ((uint)0x0000b000)
+#endif
+
+/* The number of pages of host memory we allocate for CPM.  This is
+ * done early in kernel initialization to get physically contiguous
+ * pages.
+ */
+#define NUM_CPM_HOST_PAGES     2
+
+
+/* Export the base address of the communication processor registers
+ * and dual port ram.
+ */
+extern         cpm_cpm2_t      *cpmp;   /* Pointer to comm processor */
+extern void *cpm2_dpalloc(uint size, uint align);
+extern int cpm2_dpfree(void *addr);
+extern void *cpm2_dpalloc_fixed(void *addr, uint size, uint allign);
+extern void cpm2_dpdump(void);
+extern unsigned int cpm2_dpram_offset(void *addr);
+extern void *cpm2_dpram_addr(int offset);
+extern void cpm2_setbrg(uint brg, uint rate);
+extern void cpm2_fastbrg(uint brg, uint rate, int div16);
+
+/* Buffer descriptors used by many of the CPM protocols.
+*/
+typedef struct cpm_buf_desc {
+       ushort  cbd_sc;         /* Status and Control */
+       ushort  cbd_datlen;     /* Data length in buffer */
+       uint    cbd_bufaddr;    /* Buffer address in host memory */
+} cbd_t;
+
+#define BD_SC_EMPTY    ((ushort)0x8000)        /* Receive is empty */
+#define BD_SC_READY    ((ushort)0x8000)        /* Transmit is ready */
+#define BD_SC_WRAP     ((ushort)0x2000)        /* Last buffer descriptor */
+#define BD_SC_INTRPT   ((ushort)0x1000)        /* Interrupt on change */
+#define BD_SC_LAST     ((ushort)0x0800)        /* Last buffer in frame */
+#define BD_SC_CM       ((ushort)0x0200)        /* Continous mode */
+#define BD_SC_ID       ((ushort)0x0100)        /* Rec'd too many idles */
+#define BD_SC_P                ((ushort)0x0100)        /* xmt preamble */
+#define BD_SC_BR       ((ushort)0x0020)        /* Break received */
+#define BD_SC_FR       ((ushort)0x0010)        /* Framing error */
+#define BD_SC_PR       ((ushort)0x0008)        /* Parity error */
+#define BD_SC_OV       ((ushort)0x0002)        /* Overrun */
+#define BD_SC_CD       ((ushort)0x0001)        /* ?? */
+
+/* Function code bits, usually generic to devices.
+*/
+#define CPMFCR_GBL     ((u_char)0x20)  /* Set memory snooping */
+#define CPMFCR_EB      ((u_char)0x10)  /* Set big endian byte order */
+#define CPMFCR_TC2     ((u_char)0x04)  /* Transfer code 2 value */
+#define CPMFCR_DTB     ((u_char)0x02)  /* Use local bus for data when set */
+#define CPMFCR_BDB     ((u_char)0x01)  /* Use local bus for BD when set */
+
+/* Parameter RAM offsets from the base.
+*/
+#define PROFF_SCC1             ((uint)0x8000)
+#define PROFF_SCC2             ((uint)0x8100)
+#define PROFF_SCC3             ((uint)0x8200)
+#define PROFF_SCC4             ((uint)0x8300)
+#define PROFF_FCC1             ((uint)0x8400)
+#define PROFF_FCC2             ((uint)0x8500)
+#define PROFF_FCC3             ((uint)0x8600)
+#define PROFF_MCC1             ((uint)0x8700)
+#define PROFF_SMC1_BASE                ((uint)0x87fc)
+#define PROFF_IDMA1_BASE       ((uint)0x87fe)
+#define PROFF_MCC2             ((uint)0x8800)
+#define PROFF_SMC2_BASE                ((uint)0x88fc)
+#define PROFF_IDMA2_BASE       ((uint)0x88fe)
+#define PROFF_SPI_BASE         ((uint)0x89fc)
+#define PROFF_IDMA3_BASE       ((uint)0x89fe)
+#define PROFF_TIMERS           ((uint)0x8ae0)
+#define PROFF_REVNUM           ((uint)0x8af0)
+#define PROFF_RAND             ((uint)0x8af8)
+#define PROFF_I2C_BASE         ((uint)0x8afc)
+#define PROFF_IDMA4_BASE       ((uint)0x8afe)
+
+/* The SMCs are relocated to any of the first eight DPRAM pages.
+ * We will fix these at the first locations of DPRAM, until we
+ * get some microcode patches :-).
+ * The parameter ram space for the SMCs is fifty-some bytes, and
+ * they are required to start on a 64 byte boundary.
+ */
+#define PROFF_SMC1     (0)
+#define PROFF_SMC2     (64)
+
+
+/* Define enough so I can at least use the serial port as a UART.
+ */
+typedef struct smc_uart {
+       ushort  smc_rbase;      /* Rx Buffer descriptor base address */
+       ushort  smc_tbase;      /* Tx Buffer descriptor base address */
+       u_char  smc_rfcr;       /* Rx function code */
+       u_char  smc_tfcr;       /* Tx function code */
+       ushort  smc_mrblr;      /* Max receive buffer length */
+       uint    smc_rstate;     /* Internal */
+       uint    smc_idp;        /* Internal */
+       ushort  smc_rbptr;      /* Internal */
+       ushort  smc_ibc;        /* Internal */
+       uint    smc_rxtmp;      /* Internal */
+       uint    smc_tstate;     /* Internal */
+       uint    smc_tdp;        /* Internal */
+       ushort  smc_tbptr;      /* Internal */
+       ushort  smc_tbc;        /* Internal */
+       uint    smc_txtmp;      /* Internal */
+       ushort  smc_maxidl;     /* Maximum idle characters */
+       ushort  smc_tmpidl;     /* Temporary idle counter */
+       ushort  smc_brklen;     /* Last received break length */
+       ushort  smc_brkec;      /* rcv'd break condition counter */
+       ushort  smc_brkcr;      /* xmt break count register */
+       ushort  smc_rmask;      /* Temporary bit mask */
+       uint    smc_stmp;       /* SDMA Temp */
+} smc_uart_t;
+
+/* SMC uart mode register (Internal memory map).
+*/
+#define SMCMR_REN      ((ushort)0x0001)
+#define SMCMR_TEN      ((ushort)0x0002)
+#define SMCMR_DM       ((ushort)0x000c)
+#define SMCMR_SM_GCI   ((ushort)0x0000)
+#define SMCMR_SM_UART  ((ushort)0x0020)
+#define SMCMR_SM_TRANS ((ushort)0x0030)
+#define SMCMR_SM_MASK  ((ushort)0x0030)
+#define SMCMR_PM_EVEN  ((ushort)0x0100)        /* Even parity, else odd */
+#define SMCMR_REVD     SMCMR_PM_EVEN
+#define SMCMR_PEN      ((ushort)0x0200)        /* Parity enable */
+#define SMCMR_BS       SMCMR_PEN
+#define SMCMR_SL       ((ushort)0x0400)        /* Two stops, else one */
+#define SMCR_CLEN_MASK ((ushort)0x7800)        /* Character length */
+#define smcr_mk_clen(C)        (((C) << 11) & SMCR_CLEN_MASK)
+
+/* SMC Event and Mask register.
+*/
+#define SMCM_BRKE       ((unsigned char)0x40)   /* When in UART Mode */
+#define SMCM_BRK        ((unsigned char)0x10)   /* When in UART Mode */
+#define SMCM_TXE       ((unsigned char)0x10)
+#define SMCM_BSY       ((unsigned char)0x04)
+#define SMCM_TX                ((unsigned char)0x02)
+#define SMCM_RX                ((unsigned char)0x01)
+
+/* Baud rate generators.
+*/
+#define CPM_BRG_RST            ((uint)0x00020000)
+#define CPM_BRG_EN             ((uint)0x00010000)
+#define CPM_BRG_EXTC_INT       ((uint)0x00000000)
+#define CPM_BRG_EXTC_CLK3_9    ((uint)0x00004000)
+#define CPM_BRG_EXTC_CLK5_15   ((uint)0x00008000)
+#define CPM_BRG_ATB            ((uint)0x00002000)
+#define CPM_BRG_CD_MASK                ((uint)0x00001ffe)
+#define CPM_BRG_DIV16          ((uint)0x00000001)
+
+/* SCCs.
+*/
+#define SCC_GSMRH_IRP          ((uint)0x00040000)
+#define SCC_GSMRH_GDE          ((uint)0x00010000)
+#define SCC_GSMRH_TCRC_CCITT   ((uint)0x00008000)
+#define SCC_GSMRH_TCRC_BISYNC  ((uint)0x00004000)
+#define SCC_GSMRH_TCRC_HDLC    ((uint)0x00000000)
+#define SCC_GSMRH_REVD         ((uint)0x00002000)
+#define SCC_GSMRH_TRX          ((uint)0x00001000)
+#define SCC_GSMRH_TTX          ((uint)0x00000800)
+#define SCC_GSMRH_CDP          ((uint)0x00000400)
+#define SCC_GSMRH_CTSP         ((uint)0x00000200)
+#define SCC_GSMRH_CDS          ((uint)0x00000100)
+#define SCC_GSMRH_CTSS         ((uint)0x00000080)
+#define SCC_GSMRH_TFL          ((uint)0x00000040)
+#define SCC_GSMRH_RFW          ((uint)0x00000020)
+#define SCC_GSMRH_TXSY         ((uint)0x00000010)
+#define SCC_GSMRH_SYNL16       ((uint)0x0000000c)
+#define SCC_GSMRH_SYNL8                ((uint)0x00000008)
+#define SCC_GSMRH_SYNL4                ((uint)0x00000004)
+#define SCC_GSMRH_RTSM         ((uint)0x00000002)
+#define SCC_GSMRH_RSYN         ((uint)0x00000001)
+
+#define SCC_GSMRL_SIR          ((uint)0x80000000)      /* SCC2 only */
+#define SCC_GSMRL_EDGE_NONE    ((uint)0x60000000)
+#define SCC_GSMRL_EDGE_NEG     ((uint)0x40000000)
+#define SCC_GSMRL_EDGE_POS     ((uint)0x20000000)
+#define SCC_GSMRL_EDGE_BOTH    ((uint)0x00000000)
+#define SCC_GSMRL_TCI          ((uint)0x10000000)
+#define SCC_GSMRL_TSNC_3       ((uint)0x0c000000)
+#define SCC_GSMRL_TSNC_4       ((uint)0x08000000)
+#define SCC_GSMRL_TSNC_14      ((uint)0x04000000)
+#define SCC_GSMRL_TSNC_INF     ((uint)0x00000000)
+#define SCC_GSMRL_RINV         ((uint)0x02000000)
+#define SCC_GSMRL_TINV         ((uint)0x01000000)
+#define SCC_GSMRL_TPL_128      ((uint)0x00c00000)
+#define SCC_GSMRL_TPL_64       ((uint)0x00a00000)
+#define SCC_GSMRL_TPL_48       ((uint)0x00800000)
+#define SCC_GSMRL_TPL_32       ((uint)0x00600000)
+#define SCC_GSMRL_TPL_16       ((uint)0x00400000)
+#define SCC_GSMRL_TPL_8                ((uint)0x00200000)
+#define SCC_GSMRL_TPL_NONE     ((uint)0x00000000)
+#define SCC_GSMRL_TPP_ALL1     ((uint)0x00180000)
+#define SCC_GSMRL_TPP_01       ((uint)0x00100000)
+#define SCC_GSMRL_TPP_10       ((uint)0x00080000)
+#define SCC_GSMRL_TPP_ZEROS    ((uint)0x00000000)
+#define SCC_GSMRL_TEND         ((uint)0x00040000)
+#define SCC_GSMRL_TDCR_32      ((uint)0x00030000)
+#define SCC_GSMRL_TDCR_16      ((uint)0x00020000)
+#define SCC_GSMRL_TDCR_8       ((uint)0x00010000)
+#define SCC_GSMRL_TDCR_1       ((uint)0x00000000)
+#define SCC_GSMRL_RDCR_32      ((uint)0x0000c000)
+#define SCC_GSMRL_RDCR_16      ((uint)0x00008000)
+#define SCC_GSMRL_RDCR_8       ((uint)0x00004000)
+#define SCC_GSMRL_RDCR_1       ((uint)0x00000000)
+#define SCC_GSMRL_RENC_DFMAN   ((uint)0x00003000)
+#define SCC_GSMRL_RENC_MANCH   ((uint)0x00002000)
+#define SCC_GSMRL_RENC_FM0     ((uint)0x00001000)
+#define SCC_GSMRL_RENC_NRZI    ((uint)0x00000800)
+#define SCC_GSMRL_RENC_NRZ     ((uint)0x00000000)
+#define SCC_GSMRL_TENC_DFMAN   ((uint)0x00000600)
+#define SCC_GSMRL_TENC_MANCH   ((uint)0x00000400)
+#define SCC_GSMRL_TENC_FM0     ((uint)0x00000200)
+#define SCC_GSMRL_TENC_NRZI    ((uint)0x00000100)
+#define SCC_GSMRL_TENC_NRZ     ((uint)0x00000000)
+#define SCC_GSMRL_DIAG_LE      ((uint)0x000000c0)      /* Loop and echo */
+#define SCC_GSMRL_DIAG_ECHO    ((uint)0x00000080)
+#define SCC_GSMRL_DIAG_LOOP    ((uint)0x00000040)
+#define SCC_GSMRL_DIAG_NORM    ((uint)0x00000000)
+#define SCC_GSMRL_ENR          ((uint)0x00000020)
+#define SCC_GSMRL_ENT          ((uint)0x00000010)
+#define SCC_GSMRL_MODE_ENET    ((uint)0x0000000c)
+#define SCC_GSMRL_MODE_DDCMP   ((uint)0x00000009)
+#define SCC_GSMRL_MODE_BISYNC  ((uint)0x00000008)
+#define SCC_GSMRL_MODE_V14     ((uint)0x00000007)
+#define SCC_GSMRL_MODE_AHDLC   ((uint)0x00000006)
+#define SCC_GSMRL_MODE_PROFIBUS        ((uint)0x00000005)
+#define SCC_GSMRL_MODE_UART    ((uint)0x00000004)
+#define SCC_GSMRL_MODE_SS7     ((uint)0x00000003)
+#define SCC_GSMRL_MODE_ATALK   ((uint)0x00000002)
+#define SCC_GSMRL_MODE_HDLC    ((uint)0x00000000)
+
+#define SCC_TODR_TOD           ((ushort)0x8000)
+
+/* SCC Event and Mask register.
+*/
+#define SCCM_TXE       ((unsigned char)0x10)
+#define SCCM_BSY       ((unsigned char)0x04)
+#define SCCM_TX                ((unsigned char)0x02)
+#define SCCM_RX                ((unsigned char)0x01)
+
+typedef struct scc_param {
+       ushort  scc_rbase;      /* Rx Buffer descriptor base address */
+       ushort  scc_tbase;      /* Tx Buffer descriptor base address */
+       u_char  scc_rfcr;       /* Rx function code */
+       u_char  scc_tfcr;       /* Tx function code */
+       ushort  scc_mrblr;      /* Max receive buffer length */
+       uint    scc_rstate;     /* Internal */
+       uint    scc_idp;        /* Internal */
+       ushort  scc_rbptr;      /* Internal */
+       ushort  scc_ibc;        /* Internal */
+       uint    scc_rxtmp;      /* Internal */
+       uint    scc_tstate;     /* Internal */
+       uint    scc_tdp;        /* Internal */
+       ushort  scc_tbptr;      /* Internal */
+       ushort  scc_tbc;        /* Internal */
+       uint    scc_txtmp;      /* Internal */
+       uint    scc_rcrc;       /* Internal */
+       uint    scc_tcrc;       /* Internal */
+} sccp_t;
+
+/* CPM Ethernet through SCC1.
+ */
+typedef struct scc_enet {
+       sccp_t  sen_genscc;
+       uint    sen_cpres;      /* Preset CRC */
+       uint    sen_cmask;      /* Constant mask for CRC */
+       uint    sen_crcec;      /* CRC Error counter */
+       uint    sen_alec;       /* alignment error counter */
+       uint    sen_disfc;      /* discard frame counter */
+       ushort  sen_pads;       /* Tx short frame pad character */
+       ushort  sen_retlim;     /* Retry limit threshold */
+       ushort  sen_retcnt;     /* Retry limit counter */
+       ushort  sen_maxflr;     /* maximum frame length register */
+       ushort  sen_minflr;     /* minimum frame length register */
+       ushort  sen_maxd1;      /* maximum DMA1 length */
+       ushort  sen_maxd2;      /* maximum DMA2 length */
+       ushort  sen_maxd;       /* Rx max DMA */
+       ushort  sen_dmacnt;     /* Rx DMA counter */
+       ushort  sen_maxb;       /* Max BD byte count */
+       ushort  sen_gaddr1;     /* Group address filter */
+       ushort  sen_gaddr2;
+       ushort  sen_gaddr3;
+       ushort  sen_gaddr4;
+       uint    sen_tbuf0data0; /* Save area 0 - current frame */
+       uint    sen_tbuf0data1; /* Save area 1 - current frame */
+       uint    sen_tbuf0rba;   /* Internal */
+       uint    sen_tbuf0crc;   /* Internal */
+       ushort  sen_tbuf0bcnt;  /* Internal */
+       ushort  sen_paddrh;     /* physical address (MSB) */
+       ushort  sen_paddrm;
+       ushort  sen_paddrl;     /* physical address (LSB) */
+       ushort  sen_pper;       /* persistence */
+       ushort  sen_rfbdptr;    /* Rx first BD pointer */
+       ushort  sen_tfbdptr;    /* Tx first BD pointer */
+       ushort  sen_tlbdptr;    /* Tx last BD pointer */
+       uint    sen_tbuf1data0; /* Save area 0 - current frame */
+       uint    sen_tbuf1data1; /* Save area 1 - current frame */
+       uint    sen_tbuf1rba;   /* Internal */
+       uint    sen_tbuf1crc;   /* Internal */
+       ushort  sen_tbuf1bcnt;  /* Internal */
+       ushort  sen_txlen;      /* Tx Frame length counter */
+       ushort  sen_iaddr1;     /* Individual address filter */
+       ushort  sen_iaddr2;
+       ushort  sen_iaddr3;
+       ushort  sen_iaddr4;
+       ushort  sen_boffcnt;    /* Backoff counter */
+
+       /* NOTE: Some versions of the manual have the following items
+        * incorrectly documented.  Below is the proper order.
+        */
+       ushort  sen_taddrh;     /* temp address (MSB) */
+       ushort  sen_taddrm;
+       ushort  sen_taddrl;     /* temp address (LSB) */
+} scc_enet_t;
+
+
+/* SCC Event register as used by Ethernet.
+*/
+#define SCCE_ENET_GRA  ((ushort)0x0080)        /* Graceful stop complete */
+#define SCCE_ENET_TXE  ((ushort)0x0010)        /* Transmit Error */
+#define SCCE_ENET_RXF  ((ushort)0x0008)        /* Full frame received */
+#define SCCE_ENET_BSY  ((ushort)0x0004)        /* All incoming buffers full */
+#define SCCE_ENET_TXB  ((ushort)0x0002)        /* A buffer was transmitted */
+#define SCCE_ENET_RXB  ((ushort)0x0001)        /* A buffer was received */
+
+/* SCC Mode Register (PSMR) as used by Ethernet.
+*/
+#define SCC_PSMR_HBC   ((ushort)0x8000)        /* Enable heartbeat */
+#define SCC_PSMR_FC    ((ushort)0x4000)        /* Force collision */
+#define SCC_PSMR_RSH   ((ushort)0x2000)        /* Receive short frames */
+#define SCC_PSMR_IAM   ((ushort)0x1000)        /* Check individual hash */
+#define SCC_PSMR_ENCRC ((ushort)0x0800)        /* Ethernet CRC mode */
+#define SCC_PSMR_PRO   ((ushort)0x0200)        /* Promiscuous mode */
+#define SCC_PSMR_BRO   ((ushort)0x0100)        /* Catch broadcast pkts */
+#define SCC_PSMR_SBT   ((ushort)0x0080)        /* Special backoff timer */
+#define SCC_PSMR_LPB   ((ushort)0x0040)        /* Set Loopback mode */
+#define SCC_PSMR_SIP   ((ushort)0x0020)        /* Sample Input Pins */
+#define SCC_PSMR_LCW   ((ushort)0x0010)        /* Late collision window */
+#define SCC_PSMR_NIB22 ((ushort)0x000a)        /* Start frame search */
+#define SCC_PSMR_FDE   ((ushort)0x0001)        /* Full duplex enable */
+
+/* Buffer descriptor control/status used by Ethernet receive.
+ * Common to SCC and FCC.
+ */
+#define BD_ENET_RX_EMPTY       ((ushort)0x8000)
+#define BD_ENET_RX_WRAP                ((ushort)0x2000)
+#define BD_ENET_RX_INTR                ((ushort)0x1000)
+#define BD_ENET_RX_LAST                ((ushort)0x0800)
+#define BD_ENET_RX_FIRST       ((ushort)0x0400)
+#define BD_ENET_RX_MISS                ((ushort)0x0100)
+#define BD_ENET_RX_BC          ((ushort)0x0080)        /* FCC Only */
+#define BD_ENET_RX_MC          ((ushort)0x0040)        /* FCC Only */
+#define BD_ENET_RX_LG          ((ushort)0x0020)
+#define BD_ENET_RX_NO          ((ushort)0x0010)
+#define BD_ENET_RX_SH          ((ushort)0x0008)
+#define BD_ENET_RX_CR          ((ushort)0x0004)
+#define BD_ENET_RX_OV          ((ushort)0x0002)
+#define BD_ENET_RX_CL          ((ushort)0x0001)
+#define BD_ENET_RX_STATS       ((ushort)0x01ff)        /* All status bits */
+
+/* Buffer descriptor control/status used by Ethernet transmit.
+ * Common to SCC and FCC.
+ */
+#define BD_ENET_TX_READY       ((ushort)0x8000)
+#define BD_ENET_TX_PAD         ((ushort)0x4000)
+#define BD_ENET_TX_WRAP                ((ushort)0x2000)
+#define BD_ENET_TX_INTR                ((ushort)0x1000)
+#define BD_ENET_TX_LAST                ((ushort)0x0800)
+#define BD_ENET_TX_TC          ((ushort)0x0400)
+#define BD_ENET_TX_DEF         ((ushort)0x0200)
+#define BD_ENET_TX_HB          ((ushort)0x0100)
+#define BD_ENET_TX_LC          ((ushort)0x0080)
+#define BD_ENET_TX_RL          ((ushort)0x0040)
+#define BD_ENET_TX_RCMASK      ((ushort)0x003c)
+#define BD_ENET_TX_UN          ((ushort)0x0002)
+#define BD_ENET_TX_CSL         ((ushort)0x0001)
+#define BD_ENET_TX_STATS       ((ushort)0x03ff)        /* All status bits */
+
+/* SCC as UART
+*/
+typedef struct scc_uart {
+       sccp_t  scc_genscc;
+       uint    scc_res1;       /* Reserved */
+       uint    scc_res2;       /* Reserved */
+       ushort  scc_maxidl;     /* Maximum idle chars */
+       ushort  scc_idlc;       /* temp idle counter */
+       ushort  scc_brkcr;      /* Break count register */
+       ushort  scc_parec;      /* receive parity error counter */
+       ushort  scc_frmec;      /* receive framing error counter */
+       ushort  scc_nosec;      /* receive noise counter */
+       ushort  scc_brkec;      /* receive break condition counter */
+       ushort  scc_brkln;      /* last received break length */
+       ushort  scc_uaddr1;     /* UART address character 1 */
+       ushort  scc_uaddr2;     /* UART address character 2 */
+       ushort  scc_rtemp;      /* Temp storage */
+       ushort  scc_toseq;      /* Transmit out of sequence char */
+       ushort  scc_char1;      /* control character 1 */
+       ushort  scc_char2;      /* control character 2 */
+       ushort  scc_char3;      /* control character 3 */
+       ushort  scc_char4;      /* control character 4 */
+       ushort  scc_char5;      /* control character 5 */
+       ushort  scc_char6;      /* control character 6 */
+       ushort  scc_char7;      /* control character 7 */
+       ushort  scc_char8;      /* control character 8 */
+       ushort  scc_rccm;       /* receive control character mask */
+       ushort  scc_rccr;       /* receive control character register */
+       ushort  scc_rlbc;       /* receive last break character */
+} scc_uart_t;
+
+/* SCC Event and Mask registers when it is used as a UART.
+*/
+#define UART_SCCM_GLR          ((ushort)0x1000)
+#define UART_SCCM_GLT          ((ushort)0x0800)
+#define UART_SCCM_AB           ((ushort)0x0200)
+#define UART_SCCM_IDL          ((ushort)0x0100)
+#define UART_SCCM_GRA          ((ushort)0x0080)
+#define UART_SCCM_BRKE         ((ushort)0x0040)
+#define UART_SCCM_BRKS         ((ushort)0x0020)
+#define UART_SCCM_CCR          ((ushort)0x0008)
+#define UART_SCCM_BSY          ((ushort)0x0004)
+#define UART_SCCM_TX           ((ushort)0x0002)
+#define UART_SCCM_RX           ((ushort)0x0001)
+
+/* The SCC PSMR when used as a UART.
+*/
+#define SCU_PSMR_FLC           ((ushort)0x8000)
+#define SCU_PSMR_SL            ((ushort)0x4000)
+#define SCU_PSMR_CL            ((ushort)0x3000)
+#define SCU_PSMR_UM            ((ushort)0x0c00)
+#define SCU_PSMR_FRZ           ((ushort)0x0200)
+#define SCU_PSMR_RZS           ((ushort)0x0100)
+#define SCU_PSMR_SYN           ((ushort)0x0080)
+#define SCU_PSMR_DRT           ((ushort)0x0040)
+#define SCU_PSMR_PEN           ((ushort)0x0010)
+#define SCU_PSMR_RPM           ((ushort)0x000c)
+#define SCU_PSMR_REVP          ((ushort)0x0008)
+#define SCU_PSMR_TPM           ((ushort)0x0003)
+#define SCU_PSMR_TEVP          ((ushort)0x0003)
+
+/* CPM Transparent mode SCC.
+ */
+typedef struct scc_trans {
+       sccp_t  st_genscc;
+       uint    st_cpres;       /* Preset CRC */
+       uint    st_cmask;       /* Constant mask for CRC */
+} scc_trans_t;
+
+#define BD_SCC_TX_LAST         ((ushort)0x0800)
+
+/* How about some FCCs.....
+*/
+#define FCC_GFMR_DIAG_NORM     ((uint)0x00000000)
+#define FCC_GFMR_DIAG_LE       ((uint)0x40000000)
+#define FCC_GFMR_DIAG_AE       ((uint)0x80000000)
+#define FCC_GFMR_DIAG_ALE      ((uint)0xc0000000)
+#define FCC_GFMR_TCI           ((uint)0x20000000)
+#define FCC_GFMR_TRX           ((uint)0x10000000)
+#define FCC_GFMR_TTX           ((uint)0x08000000)
+#define FCC_GFMR_TTX           ((uint)0x08000000)
+#define FCC_GFMR_CDP           ((uint)0x04000000)
+#define FCC_GFMR_CTSP          ((uint)0x02000000)
+#define FCC_GFMR_CDS           ((uint)0x01000000)
+#define FCC_GFMR_CTSS          ((uint)0x00800000)
+#define FCC_GFMR_SYNL_NONE     ((uint)0x00000000)
+#define FCC_GFMR_SYNL_AUTO     ((uint)0x00004000)
+#define FCC_GFMR_SYNL_8                ((uint)0x00008000)
+#define FCC_GFMR_SYNL_16       ((uint)0x0000c000)
+#define FCC_GFMR_RTSM          ((uint)0x00002000)
+#define FCC_GFMR_RENC_NRZ      ((uint)0x00000000)
+#define FCC_GFMR_RENC_NRZI     ((uint)0x00000800)
+#define FCC_GFMR_REVD          ((uint)0x00000400)
+#define FCC_GFMR_TENC_NRZ      ((uint)0x00000000)
+#define FCC_GFMR_TENC_NRZI     ((uint)0x00000100)
+#define FCC_GFMR_TCRC_16       ((uint)0x00000000)
+#define FCC_GFMR_TCRC_32       ((uint)0x00000080)
+#define FCC_GFMR_ENR           ((uint)0x00000020)
+#define FCC_GFMR_ENT           ((uint)0x00000010)
+#define FCC_GFMR_MODE_ENET     ((uint)0x0000000c)
+#define FCC_GFMR_MODE_ATM      ((uint)0x0000000a)
+#define FCC_GFMR_MODE_HDLC     ((uint)0x00000000)
+
+/* Generic FCC parameter ram.
+*/
+typedef struct fcc_param {
+       ushort  fcc_riptr;      /* Rx Internal temp pointer */
+       ushort  fcc_tiptr;      /* Tx Internal temp pointer */
+       ushort  fcc_res1;
+       ushort  fcc_mrblr;      /* Max receive buffer length, mod 32 bytes */
+       uint    fcc_rstate;     /* Upper byte is Func code, must be set */
+       uint    fcc_rbase;      /* Receive BD base */
+       ushort  fcc_rbdstat;    /* RxBD status */
+       ushort  fcc_rbdlen;     /* RxBD down counter */
+       uint    fcc_rdptr;      /* RxBD internal data pointer */
+       uint    fcc_tstate;     /* Upper byte is Func code, must be set */
+       uint    fcc_tbase;      /* Transmit BD base */
+       ushort  fcc_tbdstat;    /* TxBD status */
+       ushort  fcc_tbdlen;     /* TxBD down counter */
+       uint    fcc_tdptr;      /* TxBD internal data pointer */
+       uint    fcc_rbptr;      /* Rx BD Internal buf pointer */
+       uint    fcc_tbptr;      /* Tx BD Internal buf pointer */
+       uint    fcc_rcrc;       /* Rx temp CRC */
+       uint    fcc_res2;
+       uint    fcc_tcrc;       /* Tx temp CRC */
+} fccp_t;
+
+
+/* Ethernet controller through FCC.
+*/
+typedef struct fcc_enet {
+       fccp_t  fen_genfcc;
+       uint    fen_statbuf;    /* Internal status buffer */
+       uint    fen_camptr;     /* CAM address */
+       uint    fen_cmask;      /* Constant mask for CRC */
+       uint    fen_cpres;      /* Preset CRC */
+       uint    fen_crcec;      /* CRC Error counter */
+       uint    fen_alec;       /* alignment error counter */
+       uint    fen_disfc;      /* discard frame counter */
+       ushort  fen_retlim;     /* Retry limit */
+       ushort  fen_retcnt;     /* Retry counter */
+       ushort  fen_pper;       /* Persistence */
+       ushort  fen_boffcnt;    /* backoff counter */
+       uint    fen_gaddrh;     /* Group address filter, high 32-bits */
+       uint    fen_gaddrl;     /* Group address filter, low 32-bits */
+       ushort  fen_tfcstat;    /* out of sequence TxBD */
+       ushort  fen_tfclen;
+       uint    fen_tfcptr;
+       ushort  fen_mflr;       /* Maximum frame length (1518) */
+       ushort  fen_paddrh;     /* MAC address */
+       ushort  fen_paddrm;
+       ushort  fen_paddrl;
+       ushort  fen_ibdcount;   /* Internal BD counter */
+       ushort  fen_ibdstart;   /* Internal BD start pointer */
+       ushort  fen_ibdend;     /* Internal BD end pointer */
+       ushort  fen_txlen;      /* Internal Tx frame length counter */
+       uint    fen_ibdbase[8]; /* Internal use */
+       uint    fen_iaddrh;     /* Individual address filter */
+       uint    fen_iaddrl;
+       ushort  fen_minflr;     /* Minimum frame length (64) */
+       ushort  fen_taddrh;     /* Filter transfer MAC address */
+       ushort  fen_taddrm;
+       ushort  fen_taddrl;
+       ushort  fen_padptr;     /* Pointer to pad byte buffer */
+       ushort  fen_cftype;     /* control frame type */
+       ushort  fen_cfrange;    /* control frame range */
+       ushort  fen_maxb;       /* maximum BD count */
+       ushort  fen_maxd1;      /* Max DMA1 length (1520) */
+       ushort  fen_maxd2;      /* Max DMA2 length (1520) */
+       ushort  fen_maxd;       /* internal max DMA count */
+       ushort  fen_dmacnt;     /* internal DMA counter */
+       uint    fen_octc;       /* Total octect counter */
+       uint    fen_colc;       /* Total collision counter */
+       uint    fen_broc;       /* Total broadcast packet counter */
+       uint    fen_mulc;       /* Total multicast packet count */
+       uint    fen_uspc;       /* Total packets < 64 bytes */
+       uint    fen_frgc;       /* Total packets < 64 bytes with errors */
+       uint    fen_ospc;       /* Total packets > 1518 */
+       uint    fen_jbrc;       /* Total packets > 1518 with errors */
+       uint    fen_p64c;       /* Total packets == 64 bytes */
+       uint    fen_p65c;       /* Total packets 64 < bytes <= 127 */
+       uint    fen_p128c;      /* Total packets 127 < bytes <= 255 */
+       uint    fen_p256c;      /* Total packets 256 < bytes <= 511 */
+       uint    fen_p512c;      /* Total packets 512 < bytes <= 1023 */
+       uint    fen_p1024c;     /* Total packets 1024 < bytes <= 1518 */
+       uint    fen_cambuf;     /* Internal CAM buffer poiner */
+       ushort  fen_rfthr;      /* Received frames threshold */
+       ushort  fen_rfcnt;      /* Received frames count */
+} fcc_enet_t;
+
+/* FCC Event/Mask register as used by Ethernet.
+*/
+#define FCC_ENET_GRA   ((ushort)0x0080)        /* Graceful stop complete */
+#define FCC_ENET_RXC   ((ushort)0x0040)        /* Control Frame Received */
+#define FCC_ENET_TXC   ((ushort)0x0020)        /* Out of seq. Tx sent */
+#define FCC_ENET_TXE   ((ushort)0x0010)        /* Transmit Error */
+#define FCC_ENET_RXF   ((ushort)0x0008)        /* Full frame received */
+#define FCC_ENET_BSY   ((ushort)0x0004)        /* Busy.  Rx Frame dropped */
+#define FCC_ENET_TXB   ((ushort)0x0002)        /* A buffer was transmitted */
+#define FCC_ENET_RXB   ((ushort)0x0001)        /* A buffer was received */
+
+/* FCC Mode Register (FPSMR) as used by Ethernet.
+*/
+#define FCC_PSMR_HBC   ((uint)0x80000000)      /* Enable heartbeat */
+#define FCC_PSMR_FC    ((uint)0x40000000)      /* Force Collision */
+#define FCC_PSMR_SBT   ((uint)0x20000000)      /* Stop backoff timer */
+#define FCC_PSMR_LPB   ((uint)0x10000000)      /* Local protect. 1 = FDX */
+#define FCC_PSMR_LCW   ((uint)0x08000000)      /* Late collision select */
+#define FCC_PSMR_FDE   ((uint)0x04000000)      /* Full Duplex Enable */
+#define FCC_PSMR_MON   ((uint)0x02000000)      /* RMON Enable */
+#define FCC_PSMR_PRO   ((uint)0x00400000)      /* Promiscuous Enable */
+#define FCC_PSMR_FCE   ((uint)0x00200000)      /* Flow Control Enable */
+#define FCC_PSMR_RSH   ((uint)0x00100000)      /* Receive Short Frames */
+#define FCC_PSMR_CAM   ((uint)0x00000400)      /* CAM enable */
+#define FCC_PSMR_BRO   ((uint)0x00000200)      /* Broadcast pkt discard */
+#define FCC_PSMR_ENCRC ((uint)0x00000080)      /* Use 32-bit CRC */
+
+/* IIC parameter RAM.
+*/
+typedef struct iic {
+       ushort  iic_rbase;      /* Rx Buffer descriptor base address */
+       ushort  iic_tbase;      /* Tx Buffer descriptor base address */
+       u_char  iic_rfcr;       /* Rx function code */
+       u_char  iic_tfcr;       /* Tx function code */
+       ushort  iic_mrblr;      /* Max receive buffer length */
+       uint    iic_rstate;     /* Internal */
+       uint    iic_rdp;        /* Internal */
+       ushort  iic_rbptr;      /* Internal */
+       ushort  iic_rbc;        /* Internal */
+       uint    iic_rxtmp;      /* Internal */
+       uint    iic_tstate;     /* Internal */
+       uint    iic_tdp;        /* Internal */
+       ushort  iic_tbptr;      /* Internal */
+       ushort  iic_tbc;        /* Internal */
+       uint    iic_txtmp;      /* Internal */
+} iic_t;
+
+/* SPI parameter RAM.
+*/
+typedef struct spi {
+       ushort  spi_rbase;      /* Rx Buffer descriptor base address */
+       ushort  spi_tbase;      /* Tx Buffer descriptor base address */
+       u_char  spi_rfcr;       /* Rx function code */
+       u_char  spi_tfcr;       /* Tx function code */
+       ushort  spi_mrblr;      /* Max receive buffer length */
+       uint    spi_rstate;     /* Internal */
+       uint    spi_rdp;        /* Internal */
+       ushort  spi_rbptr;      /* Internal */
+       ushort  spi_rbc;        /* Internal */
+       uint    spi_rxtmp;      /* Internal */
+       uint    spi_tstate;     /* Internal */
+       uint    spi_tdp;        /* Internal */
+       ushort  spi_tbptr;      /* Internal */
+       ushort  spi_tbc;        /* Internal */
+       uint    spi_txtmp;      /* Internal */
+       uint    spi_res;        /* Tx temp. */
+       uint    spi_res1[4];    /* SDMA temp. */
+} spi_t;
+
+/* SPI Mode register.
+*/
+#define SPMODE_LOOP    ((ushort)0x4000)        /* Loopback */
+#define SPMODE_CI      ((ushort)0x2000)        /* Clock Invert */
+#define SPMODE_CP      ((ushort)0x1000)        /* Clock Phase */
+#define SPMODE_DIV16   ((ushort)0x0800)        /* BRG/16 mode */
+#define SPMODE_REV     ((ushort)0x0400)        /* Reversed Data */
+#define SPMODE_MSTR    ((ushort)0x0200)        /* SPI Master */
+#define SPMODE_EN      ((ushort)0x0100)        /* Enable */
+#define SPMODE_LENMSK  ((ushort)0x00f0)        /* character length */
+#define SPMODE_PMMSK   ((ushort)0x000f)        /* prescale modulus */
+
+#define SPMODE_LEN(x)  ((((x)-1)&0xF)<<4)
+#define SPMODE_PM(x)   ((x) &0xF)
+
+#define SPI_EB         ((u_char)0x10)          /* big endian byte order */
+
+#define BD_IIC_START           ((ushort)0x0400)
+
+/* IDMA parameter RAM
+*/
+typedef struct idma {
+       ushort ibase;           /* IDMA buffer descriptor table base address */
+       ushort dcm;             /* DMA channel mode */
+       ushort ibdptr;          /* IDMA current buffer descriptor pointer */
+       ushort dpr_buf;         /* IDMA transfer buffer base address */
+       ushort buf_inv;         /* internal buffer inventory */
+       ushort ss_max;          /* steady-state maximum transfer size */
+       ushort dpr_in_ptr;      /* write pointer inside the internal buffer */
+       ushort sts;             /* source transfer size */
+       ushort dpr_out_ptr;     /* read pointer inside the internal buffer */
+       ushort seob;            /* source end of burst */
+       ushort deob;            /* destination end of burst */
+       ushort dts;             /* destination transfer size */
+       ushort ret_add;         /* return address when working in ERM=1 mode */
+       ushort res0;            /* reserved */
+       uint   bd_cnt;          /* internal byte count */
+       uint   s_ptr;           /* source internal data pointer */
+       uint   d_ptr;           /* destination internal data pointer */
+       uint   istate;          /* internal state */
+       u_char res1[20];        /* pad to 64-byte length */
+} idma_t;
+
+/* DMA channel mode bit fields
+*/
+#define IDMA_DCM_FB            ((ushort)0x8000) /* fly-by mode */
+#define IDMA_DCM_LP            ((ushort)0x4000) /* low priority */
+#define IDMA_DCM_TC2           ((ushort)0x0400) /* value driven on TC[2] */
+#define IDMA_DCM_DMA_WRAP_MASK ((ushort)0x01c0) /* mask for DMA wrap */
+#define IDMA_DCM_DMA_WRAP_64   ((ushort)0x0000) /* 64-byte DMA xfer buffer */
+#define IDMA_DCM_DMA_WRAP_128  ((ushort)0x0040) /* 128-byte DMA xfer buffer */
+#define IDMA_DCM_DMA_WRAP_256  ((ushort)0x0080) /* 256-byte DMA xfer buffer */
+#define IDMA_DCM_DMA_WRAP_512  ((ushort)0x00c0) /* 512-byte DMA xfer buffer */
+#define IDMA_DCM_DMA_WRAP_1024 ((ushort)0x0100) /* 1024-byte DMA xfer buffer */
+#define IDMA_DCM_DMA_WRAP_2048 ((ushort)0x0140) /* 2048-byte DMA xfer buffer */
+#define IDMA_DCM_SINC          ((ushort)0x0020) /* source inc addr */
+#define IDMA_DCM_DINC          ((ushort)0x0010) /* destination inc addr */
+#define IDMA_DCM_ERM           ((ushort)0x0008) /* external request mode */
+#define IDMA_DCM_DT            ((ushort)0x0004) /* DONE treatment */
+#define IDMA_DCM_SD_MASK       ((ushort)0x0003) /* mask for SD bit field */
+#define IDMA_DCM_SD_MEM2MEM    ((ushort)0x0000) /* memory-to-memory xfer */
+#define IDMA_DCM_SD_PER2MEM    ((ushort)0x0002) /* peripheral-to-memory xfer */
+#define IDMA_DCM_SD_MEM2PER    ((ushort)0x0001) /* memory-to-peripheral xfer */
+
+/* IDMA Buffer Descriptors
+*/
+typedef struct idma_bd {
+       uint flags;
+       uint len;       /* data length */
+       uint src;       /* source data buffer pointer */
+       uint dst;       /* destination data buffer pointer */
+} idma_bd_t;
+
+/* IDMA buffer descriptor flag bit fields
+*/
+#define IDMA_BD_V      ((uint)0x80000000)      /* valid */
+#define IDMA_BD_W      ((uint)0x20000000)      /* wrap */
+#define IDMA_BD_I      ((uint)0x10000000)      /* interrupt */
+#define IDMA_BD_L      ((uint)0x08000000)      /* last */
+#define IDMA_BD_CM     ((uint)0x02000000)      /* continuous mode */
+#define IDMA_BD_SDN    ((uint)0x00400000)      /* source done */
+#define IDMA_BD_DDN    ((uint)0x00200000)      /* destination done */
+#define IDMA_BD_DGBL   ((uint)0x00100000)      /* destination global */
+#define IDMA_BD_DBO_LE ((uint)0x00040000)      /* little-end dest byte order */
+#define IDMA_BD_DBO_BE ((uint)0x00080000)      /* big-end dest byte order */
+#define IDMA_BD_DDTB   ((uint)0x00010000)      /* destination data bus */
+#define IDMA_BD_SGBL   ((uint)0x00002000)      /* source global */
+#define IDMA_BD_SBO_LE ((uint)0x00000800)      /* little-end src byte order */
+#define IDMA_BD_SBO_BE ((uint)0x00001000)      /* big-end src byte order */
+#define IDMA_BD_SDTB   ((uint)0x00000200)      /* source data bus */
+
+/* per-channel IDMA registers
+*/
+typedef struct im_idma {
+       u_char idsr;                    /* IDMAn event status register */
+       u_char res0[3];
+       u_char idmr;                    /* IDMAn event mask register */
+       u_char res1[3];
+} im_idma_t;
+
+/* IDMA event register bit fields
+*/
+#define IDMA_EVENT_SC  ((unsigned char)0x08)   /* stop completed */
+#define IDMA_EVENT_OB  ((unsigned char)0x04)   /* out of buffers */
+#define IDMA_EVENT_EDN ((unsigned char)0x02)   /* external DONE asserted */
+#define IDMA_EVENT_BC  ((unsigned char)0x01)   /* buffer descriptor complete */
+
+/* RISC Controller Configuration Register (RCCR) bit fields
+*/
+#define RCCR_TIME      ((uint)0x80000000) /* timer enable */
+#define RCCR_TIMEP_MASK        ((uint)0x3f000000) /* mask for timer period bit field */
+#define RCCR_DR0M      ((uint)0x00800000) /* IDMA0 request mode */
+#define RCCR_DR1M      ((uint)0x00400000) /* IDMA1 request mode */
+#define RCCR_DR2M      ((uint)0x00000080) /* IDMA2 request mode */
+#define RCCR_DR3M      ((uint)0x00000040) /* IDMA3 request mode */
+#define RCCR_DR0QP_MASK        ((uint)0x00300000) /* mask for IDMA0 req priority */
+#define RCCR_DR0QP_HIGH ((uint)0x00000000) /* IDMA0 has high req priority */
+#define RCCR_DR0QP_MED ((uint)0x00100000) /* IDMA0 has medium req priority */
+#define RCCR_DR0QP_LOW ((uint)0x00200000) /* IDMA0 has low req priority */
+#define RCCR_DR1QP_MASK        ((uint)0x00030000) /* mask for IDMA1 req priority */
+#define RCCR_DR1QP_HIGH ((uint)0x00000000) /* IDMA1 has high req priority */
+#define RCCR_DR1QP_MED ((uint)0x00010000) /* IDMA1 has medium req priority */
+#define RCCR_DR1QP_LOW ((uint)0x00020000) /* IDMA1 has low req priority */
+#define RCCR_DR2QP_MASK        ((uint)0x00000030) /* mask for IDMA2 req priority */
+#define RCCR_DR2QP_HIGH ((uint)0x00000000) /* IDMA2 has high req priority */
+#define RCCR_DR2QP_MED ((uint)0x00000010) /* IDMA2 has medium req priority */
+#define RCCR_DR2QP_LOW ((uint)0x00000020) /* IDMA2 has low req priority */
+#define RCCR_DR3QP_MASK        ((uint)0x00000003) /* mask for IDMA3 req priority */
+#define RCCR_DR3QP_HIGH ((uint)0x00000000) /* IDMA3 has high req priority */
+#define RCCR_DR3QP_MED ((uint)0x00000001) /* IDMA3 has medium req priority */
+#define RCCR_DR3QP_LOW ((uint)0x00000002) /* IDMA3 has low req priority */
+#define RCCR_EIE       ((uint)0x00080000) /* external interrupt enable */
+#define RCCR_SCD       ((uint)0x00040000) /* scheduler configuration */
+#define RCCR_ERAM_MASK ((uint)0x0000e000) /* mask for enable RAM microcode */
+#define RCCR_ERAM_0KB  ((uint)0x00000000) /* use 0KB of dpram for microcode */
+#define RCCR_ERAM_2KB  ((uint)0x00002000) /* use 2KB of dpram for microcode */
+#define RCCR_ERAM_4KB  ((uint)0x00004000) /* use 4KB of dpram for microcode */
+#define RCCR_ERAM_6KB  ((uint)0x00006000) /* use 6KB of dpram for microcode */
+#define RCCR_ERAM_8KB  ((uint)0x00008000) /* use 8KB of dpram for microcode */
+#define RCCR_ERAM_10KB ((uint)0x0000a000) /* use 10KB of dpram for microcode */
+#define RCCR_ERAM_12KB ((uint)0x0000c000) /* use 12KB of dpram for microcode */
+#define RCCR_EDM0      ((uint)0x00000800) /* DREQ0 edge detect mode */
+#define RCCR_EDM1      ((uint)0x00000400) /* DREQ1 edge detect mode */
+#define RCCR_EDM2      ((uint)0x00000200) /* DREQ2 edge detect mode */
+#define RCCR_EDM3      ((uint)0x00000100) /* DREQ3 edge detect mode */
+#define RCCR_DEM01     ((uint)0x00000008) /* DONE0/DONE1 edge detect mode */
+#define RCCR_DEM23     ((uint)0x00000004) /* DONE2/DONE3 edge detect mode */
+
+/*-----------------------------------------------------------------------
+ * CMXFCR - CMX FCC Clock Route Register
+ */
+#define CMXFCR_FC1         0x40000000   /* FCC1 connection              */
+#define CMXFCR_RF1CS_MSK   0x38000000   /* Receive FCC1 Clock Source Mask */
+#define CMXFCR_TF1CS_MSK   0x07000000   /* Transmit FCC1 Clock Source Mask */
+#define CMXFCR_FC2         0x00400000   /* FCC2 connection              */
+#define CMXFCR_RF2CS_MSK   0x00380000   /* Receive FCC2 Clock Source Mask */
+#define CMXFCR_TF2CS_MSK   0x00070000   /* Transmit FCC2 Clock Source Mask */
+#define CMXFCR_FC3         0x00004000   /* FCC3 connection              */
+#define CMXFCR_RF3CS_MSK   0x00003800   /* Receive FCC3 Clock Source Mask */
+#define CMXFCR_TF3CS_MSK   0x00000700   /* Transmit FCC3 Clock Source Mask */
+
+#define CMXFCR_RF1CS_BRG5  0x00000000   /* Receive FCC1 Clock Source is BRG5 */
+#define CMXFCR_RF1CS_BRG6  0x08000000   /* Receive FCC1 Clock Source is BRG6 */
+#define CMXFCR_RF1CS_BRG7  0x10000000   /* Receive FCC1 Clock Source is BRG7 */
+#define CMXFCR_RF1CS_BRG8  0x18000000   /* Receive FCC1 Clock Source is BRG8 */
+#define CMXFCR_RF1CS_CLK9  0x20000000   /* Receive FCC1 Clock Source is CLK9 */
+#define CMXFCR_RF1CS_CLK10 0x28000000   /* Receive FCC1 Clock Source is CLK10 */
+#define CMXFCR_RF1CS_CLK11 0x30000000   /* Receive FCC1 Clock Source is CLK11 */
+#define CMXFCR_RF1CS_CLK12 0x38000000   /* Receive FCC1 Clock Source is CLK12 */
+
+#define CMXFCR_TF1CS_BRG5  0x00000000   /* Transmit FCC1 Clock Source is BRG5 */
+#define CMXFCR_TF1CS_BRG6  0x01000000   /* Transmit FCC1 Clock Source is BRG6 */
+#define CMXFCR_TF1CS_BRG7  0x02000000   /* Transmit FCC1 Clock Source is BRG7 */
+#define CMXFCR_TF1CS_BRG8  0x03000000   /* Transmit FCC1 Clock Source is BRG8 */
+#define CMXFCR_TF1CS_CLK9  0x04000000   /* Transmit FCC1 Clock Source is CLK9 */
+#define CMXFCR_TF1CS_CLK10 0x05000000   /* Transmit FCC1 Clock Source is CLK10 */
+#define CMXFCR_TF1CS_CLK11 0x06000000   /* Transmit FCC1 Clock Source is CLK11 */
+#define CMXFCR_TF1CS_CLK12 0x07000000   /* Transmit FCC1 Clock Source is CLK12 */
+
+#define CMXFCR_RF2CS_BRG5  0x00000000   /* Receive FCC2 Clock Source is BRG5 */
+#define CMXFCR_RF2CS_BRG6  0x00080000   /* Receive FCC2 Clock Source is BRG6 */
+#define CMXFCR_RF2CS_BRG7  0x00100000   /* Receive FCC2 Clock Source is BRG7 */
+#define CMXFCR_RF2CS_BRG8  0x00180000   /* Receive FCC2 Clock Source is BRG8 */
+#define CMXFCR_RF2CS_CLK13 0x00200000   /* Receive FCC2 Clock Source is CLK13 */
+#define CMXFCR_RF2CS_CLK14 0x00280000   /* Receive FCC2 Clock Source is CLK14 */
+#define CMXFCR_RF2CS_CLK15 0x00300000   /* Receive FCC2 Clock Source is CLK15 */
+#define CMXFCR_RF2CS_CLK16 0x00380000   /* Receive FCC2 Clock Source is CLK16 */
+
+#define CMXFCR_TF2CS_BRG5  0x00000000   /* Transmit FCC2 Clock Source is BRG5 */
+#define CMXFCR_TF2CS_BRG6  0x00010000   /* Transmit FCC2 Clock Source is BRG6 */
+#define CMXFCR_TF2CS_BRG7  0x00020000   /* Transmit FCC2 Clock Source is BRG7 */
+#define CMXFCR_TF2CS_BRG8  0x00030000   /* Transmit FCC2 Clock Source is BRG8 */
+#define CMXFCR_TF2CS_CLK13 0x00040000   /* Transmit FCC2 Clock Source is CLK13 */
+#define CMXFCR_TF2CS_CLK14 0x00050000   /* Transmit FCC2 Clock Source is CLK14 */
+#define CMXFCR_TF2CS_CLK15 0x00060000   /* Transmit FCC2 Clock Source is CLK15 */
+#define CMXFCR_TF2CS_CLK16 0x00070000   /* Transmit FCC2 Clock Source is CLK16 */
+
+#define CMXFCR_RF3CS_BRG5  0x00000000   /* Receive FCC3 Clock Source is BRG5 */
+#define CMXFCR_RF3CS_BRG6  0x00000800   /* Receive FCC3 Clock Source is BRG6 */
+#define CMXFCR_RF3CS_BRG7  0x00001000   /* Receive FCC3 Clock Source is BRG7 */
+#define CMXFCR_RF3CS_BRG8  0x00001800   /* Receive FCC3 Clock Source is BRG8 */
+#define CMXFCR_RF3CS_CLK13 0x00002000   /* Receive FCC3 Clock Source is CLK13 */
+#define CMXFCR_RF3CS_CLK14 0x00002800   /* Receive FCC3 Clock Source is CLK14 */
+#define CMXFCR_RF3CS_CLK15 0x00003000   /* Receive FCC3 Clock Source is CLK15 */
+#define CMXFCR_RF3CS_CLK16 0x00003800   /* Receive FCC3 Clock Source is CLK16 */
+
+#define CMXFCR_TF3CS_BRG5  0x00000000   /* Transmit FCC3 Clock Source is BRG5 */
+#define CMXFCR_TF3CS_BRG6  0x00000100   /* Transmit FCC3 Clock Source is BRG6 */
+#define CMXFCR_TF3CS_BRG7  0x00000200   /* Transmit FCC3 Clock Source is BRG7 */
+#define CMXFCR_TF3CS_BRG8  0x00000300   /* Transmit FCC3 Clock Source is BRG8 */
+#define CMXFCR_TF3CS_CLK13 0x00000400   /* Transmit FCC3 Clock Source is CLK13 */
+#define CMXFCR_TF3CS_CLK14 0x00000500   /* Transmit FCC3 Clock Source is CLK14 */
+#define CMXFCR_TF3CS_CLK15 0x00000600   /* Transmit FCC3 Clock Source is CLK15 */
+#define CMXFCR_TF3CS_CLK16 0x00000700   /* Transmit FCC3 Clock Source is CLK16 */
+
+/*-----------------------------------------------------------------------
+ * CMXSCR - CMX SCC Clock Route Register
+ */
+#define CMXSCR_GR1         0x80000000   /* Grant Support of SCC1        */
+#define CMXSCR_SC1         0x40000000   /* SCC1 connection              */
+#define CMXSCR_RS1CS_MSK   0x38000000   /* Receive SCC1 Clock Source Mask */
+#define CMXSCR_TS1CS_MSK   0x07000000   /* Transmit SCC1 Clock Source Mask */
+#define CMXSCR_GR2         0x00800000   /* Grant Support of SCC2        */
+#define CMXSCR_SC2         0x00400000   /* SCC2 connection              */
+#define CMXSCR_RS2CS_MSK   0x00380000   /* Receive SCC2 Clock Source Mask */
+#define CMXSCR_TS2CS_MSK   0x00070000   /* Transmit SCC2 Clock Source Mask */
+#define CMXSCR_GR3         0x00008000   /* Grant Support of SCC3        */
+#define CMXSCR_SC3         0x00004000   /* SCC3 connection              */
+#define CMXSCR_RS3CS_MSK   0x00003800   /* Receive SCC3 Clock Source Mask */
+#define CMXSCR_TS3CS_MSK   0x00000700   /* Transmit SCC3 Clock Source Mask */
+#define CMXSCR_GR4         0x00000080   /* Grant Support of SCC4        */
+#define CMXSCR_SC4         0x00000040   /* SCC4 connection              */
+#define CMXSCR_RS4CS_MSK   0x00000038   /* Receive SCC4 Clock Source Mask */
+#define CMXSCR_TS4CS_MSK   0x00000007   /* Transmit SCC4 Clock Source Mask */
+
+#define CMXSCR_RS1CS_BRG1  0x00000000   /* SCC1 Rx Clock Source is BRG1 */
+#define CMXSCR_RS1CS_BRG2  0x08000000   /* SCC1 Rx Clock Source is BRG2 */
+#define CMXSCR_RS1CS_BRG3  0x10000000   /* SCC1 Rx Clock Source is BRG3 */
+#define CMXSCR_RS1CS_BRG4  0x18000000   /* SCC1 Rx Clock Source is BRG4 */
+#define CMXSCR_RS1CS_CLK11 0x20000000   /* SCC1 Rx Clock Source is CLK11 */
+#define CMXSCR_RS1CS_CLK12 0x28000000   /* SCC1 Rx Clock Source is CLK12 */
+#define CMXSCR_RS1CS_CLK3  0x30000000   /* SCC1 Rx Clock Source is CLK3 */
+#define CMXSCR_RS1CS_CLK4  0x38000000   /* SCC1 Rx Clock Source is CLK4 */
+
+#define CMXSCR_TS1CS_BRG1  0x00000000   /* SCC1 Tx Clock Source is BRG1 */
+#define CMXSCR_TS1CS_BRG2  0x01000000   /* SCC1 Tx Clock Source is BRG2 */
+#define CMXSCR_TS1CS_BRG3  0x02000000   /* SCC1 Tx Clock Source is BRG3 */
+#define CMXSCR_TS1CS_BRG4  0x03000000   /* SCC1 Tx Clock Source is BRG4 */
+#define CMXSCR_TS1CS_CLK11 0x04000000   /* SCC1 Tx Clock Source is CLK11 */
+#define CMXSCR_TS1CS_CLK12 0x05000000   /* SCC1 Tx Clock Source is CLK12 */
+#define CMXSCR_TS1CS_CLK3  0x06000000   /* SCC1 Tx Clock Source is CLK3 */
+#define CMXSCR_TS1CS_CLK4  0x07000000   /* SCC1 Tx Clock Source is CLK4 */
+
+#define CMXSCR_RS2CS_BRG1  0x00000000   /* SCC2 Rx Clock Source is BRG1 */
+#define CMXSCR_RS2CS_BRG2  0x00080000   /* SCC2 Rx Clock Source is BRG2 */
+#define CMXSCR_RS2CS_BRG3  0x00100000   /* SCC2 Rx Clock Source is BRG3 */
+#define CMXSCR_RS2CS_BRG4  0x00180000   /* SCC2 Rx Clock Source is BRG4 */
+#define CMXSCR_RS2CS_CLK11 0x00200000   /* SCC2 Rx Clock Source is CLK11 */
+#define CMXSCR_RS2CS_CLK12 0x00280000   /* SCC2 Rx Clock Source is CLK12 */
+#define CMXSCR_RS2CS_CLK3  0x00300000   /* SCC2 Rx Clock Source is CLK3 */
+#define CMXSCR_RS2CS_CLK4  0x00380000   /* SCC2 Rx Clock Source is CLK4 */
+
+#define CMXSCR_TS2CS_BRG1  0x00000000   /* SCC2 Tx Clock Source is BRG1 */
+#define CMXSCR_TS2CS_BRG2  0x00010000   /* SCC2 Tx Clock Source is BRG2 */
+#define CMXSCR_TS2CS_BRG3  0x00020000   /* SCC2 Tx Clock Source is BRG3 */
+#define CMXSCR_TS2CS_BRG4  0x00030000   /* SCC2 Tx Clock Source is BRG4 */
+#define CMXSCR_TS2CS_CLK11 0x00040000   /* SCC2 Tx Clock Source is CLK11 */
+#define CMXSCR_TS2CS_CLK12 0x00050000   /* SCC2 Tx Clock Source is CLK12 */
+#define CMXSCR_TS2CS_CLK3  0x00060000   /* SCC2 Tx Clock Source is CLK3 */
+#define CMXSCR_TS2CS_CLK4  0x00070000   /* SCC2 Tx Clock Source is CLK4 */
+
+#define CMXSCR_RS3CS_BRG1  0x00000000   /* SCC3 Rx Clock Source is BRG1 */
+#define CMXSCR_RS3CS_BRG2  0x00000800   /* SCC3 Rx Clock Source is BRG2 */
+#define CMXSCR_RS3CS_BRG3  0x00001000   /* SCC3 Rx Clock Source is BRG3 */
+#define CMXSCR_RS3CS_BRG4  0x00001800   /* SCC3 Rx Clock Source is BRG4 */
+#define CMXSCR_RS3CS_CLK5  0x00002000   /* SCC3 Rx Clock Source is CLK5 */
+#define CMXSCR_RS3CS_CLK6  0x00002800   /* SCC3 Rx Clock Source is CLK6 */
+#define CMXSCR_RS3CS_CLK7  0x00003000   /* SCC3 Rx Clock Source is CLK7 */
+#define CMXSCR_RS3CS_CLK8  0x00003800   /* SCC3 Rx Clock Source is CLK8 */
+
+#define CMXSCR_TS3CS_BRG1  0x00000000   /* SCC3 Tx Clock Source is BRG1 */
+#define CMXSCR_TS3CS_BRG2  0x00000100   /* SCC3 Tx Clock Source is BRG2 */
+#define CMXSCR_TS3CS_BRG3  0x00000200   /* SCC3 Tx Clock Source is BRG3 */
+#define CMXSCR_TS3CS_BRG4  0x00000300   /* SCC3 Tx Clock Source is BRG4 */
+#define CMXSCR_TS3CS_CLK5  0x00000400   /* SCC3 Tx Clock Source is CLK5 */
+#define CMXSCR_TS3CS_CLK6  0x00000500   /* SCC3 Tx Clock Source is CLK6 */
+#define CMXSCR_TS3CS_CLK7  0x00000600   /* SCC3 Tx Clock Source is CLK7 */
+#define CMXSCR_TS3CS_CLK8  0x00000700   /* SCC3 Tx Clock Source is CLK8 */
+
+#define CMXSCR_RS4CS_BRG1  0x00000000   /* SCC4 Rx Clock Source is BRG1 */
+#define CMXSCR_RS4CS_BRG2  0x00000008   /* SCC4 Rx Clock Source is BRG2 */
+#define CMXSCR_RS4CS_BRG3  0x00000010   /* SCC4 Rx Clock Source is BRG3 */
+#define CMXSCR_RS4CS_BRG4  0x00000018   /* SCC4 Rx Clock Source is BRG4 */
+#define CMXSCR_RS4CS_CLK5  0x00000020   /* SCC4 Rx Clock Source is CLK5 */
+#define CMXSCR_RS4CS_CLK6  0x00000028   /* SCC4 Rx Clock Source is CLK6 */
+#define CMXSCR_RS4CS_CLK7  0x00000030   /* SCC4 Rx Clock Source is CLK7 */
+#define CMXSCR_RS4CS_CLK8  0x00000038   /* SCC4 Rx Clock Source is CLK8 */
+
+#define CMXSCR_TS4CS_BRG1  0x00000000   /* SCC4 Tx Clock Source is BRG1 */
+#define CMXSCR_TS4CS_BRG2  0x00000001   /* SCC4 Tx Clock Source is BRG2 */
+#define CMXSCR_TS4CS_BRG3  0x00000002   /* SCC4 Tx Clock Source is BRG3 */
+#define CMXSCR_TS4CS_BRG4  0x00000003   /* SCC4 Tx Clock Source is BRG4 */
+#define CMXSCR_TS4CS_CLK5  0x00000004   /* SCC4 Tx Clock Source is CLK5 */
+#define CMXSCR_TS4CS_CLK6  0x00000005   /* SCC4 Tx Clock Source is CLK6 */
+#define CMXSCR_TS4CS_CLK7  0x00000006   /* SCC4 Tx Clock Source is CLK7 */
+#define CMXSCR_TS4CS_CLK8  0x00000007   /* SCC4 Tx Clock Source is CLK8 */
+
+#endif /* __CPM2__ */
+#endif /* __KERNEL__ */
+
+
diff --git a/include/asm-ppc/immap_cpm2.h b/include/asm-ppc/immap_cpm2.h
new file mode 100644 (file)
index 0000000..4d56515
--- /dev/null
@@ -0,0 +1,648 @@
+/*
+ * CPM2 Internal Memory Map
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ *
+ * The Internal Memory Map for devices with CPM2 on them.  This
+ * is the superset of all CPM2 devices (8260, 8266, 8280, 8272,
+ * 8560). 
+ */
+#ifdef __KERNEL__
+#ifndef __IMMAP_CPM2__
+#define __IMMAP_CPM2__
+
+/* System configuration registers.
+*/
+typedef        struct sys_82xx_conf {
+       u32     sc_siumcr;
+       u32     sc_sypcr;
+       u8      res1[6];
+       u16     sc_swsr;
+       u8      res2[20];
+       u32     sc_bcr;
+       u8      sc_ppc_acr;
+       u8      res3[3];
+       u32     sc_ppc_alrh;
+       u32     sc_ppc_alrl;
+       u8      sc_lcl_acr;
+       u8      res4[3];
+       u32     sc_lcl_alrh;
+       u32     sc_lcl_alrl;
+       u32     sc_tescr1;
+       u32     sc_tescr2;
+       u32     sc_ltescr1;
+       u32     sc_ltescr2;
+       u32     sc_pdtea;
+       u8      sc_pdtem;
+       u8      res5[3];
+       u32     sc_ldtea;
+       u8      sc_ldtem;
+       u8      res6[163];
+} sysconf_82xx_cpm2_t;
+
+typedef        struct sys_85xx_conf {
+       u32     sc_cear;
+       u16     sc_ceer;
+       u16     sc_cemr;
+       u8      res1[70];
+       u32     sc_smaer;
+       u8      res2[4];
+       u32     sc_smevr;
+       u32     sc_smctr;
+       u32     sc_lmaer;
+       u8      res3[4];
+       u32     sc_lmevr;
+       u32     sc_lmctr;
+       u8      res4[144];
+} sysconf_85xx_cpm2_t;
+
+typedef union sys_conf {
+       sysconf_82xx_cpm2_t     siu_82xx;
+       sysconf_85xx_cpm2_t     siu_85xx;
+} sysconf_cpm2_t;
+
+
+
+/* Memory controller registers.
+*/
+typedef struct mem_ctlr {
+       u32     memc_br0;
+       u32     memc_or0;
+       u32     memc_br1;
+       u32     memc_or1;
+       u32     memc_br2;
+       u32     memc_or2;
+       u32     memc_br3;
+       u32     memc_or3;
+       u32     memc_br4;
+       u32     memc_or4;
+       u32     memc_br5;
+       u32     memc_or5;
+       u32     memc_br6;
+       u32     memc_or6;
+       u32     memc_br7;
+       u32     memc_or7;
+       u32     memc_br8;
+       u32     memc_or8;
+       u32     memc_br9;
+       u32     memc_or9;
+       u32     memc_br10;
+       u32     memc_or10;
+       u32     memc_br11;
+       u32     memc_or11;
+       u8      res1[8];
+       u32     memc_mar;
+       u8      res2[4];
+       u32     memc_mamr;
+       u32     memc_mbmr;
+       u32     memc_mcmr;
+       u8      res3[8];
+       u16     memc_mptpr;
+       u8      res4[2];
+       u32     memc_mdr;
+       u8      res5[4];
+       u32     memc_psdmr;
+       u32     memc_lsdmr;
+       u8      memc_purt;
+       u8      res6[3];
+       u8      memc_psrt;
+       u8      res7[3];
+       u8      memc_lurt;
+       u8      res8[3];
+       u8      memc_lsrt;
+       u8      res9[3];
+       u32     memc_immr;
+       u32     memc_pcibr0;
+       u32     memc_pcibr1;
+       u8      res10[16];
+       u32     memc_pcimsk0;
+       u32     memc_pcimsk1;
+       u8      res11[52];
+} memctl_cpm2_t;
+
+/* System Integration Timers.
+*/
+typedef struct sys_int_timers {
+       u8      res1[32];
+       u16     sit_tmcntsc;
+       u8      res2[2];
+       u32     sit_tmcnt;
+       u8      res3[4];
+       u32     sit_tmcntal;
+       u8      res4[16];
+       u16     sit_piscr;
+       u8      res5[2];
+       u32     sit_pitc;
+       u32     sit_pitr;
+       u8      res6[92];
+       u8      res7[390];
+} sit_cpm2_t;
+
+#define PISCR_PIRQ_MASK                ((u16)0xff00)
+#define PISCR_PS               ((u16)0x0080)
+#define PISCR_PIE              ((u16)0x0004)
+#define PISCR_PTF              ((u16)0x0002)
+#define PISCR_PTE              ((u16)0x0001)
+
+/* PCI Controller.
+*/
+typedef struct pci_ctlr {
+       u32     pci_omisr;
+       u32     pci_omimr;
+       u8      res1[8];
+       u32     pci_ifqpr;
+       u32     pci_ofqpr;
+       u8      res2[8];
+       u32     pci_imr0;
+       u32     pci_imr1;
+       u32     pci_omr0;
+       u32     pci_omr1;
+       u32     pci_odr;
+       u8      res3[4];
+       u32     pci_idr;
+       u8      res4[20];
+       u32     pci_imisr;
+       u32     pci_imimr;
+       u8      res5[24];
+       u32     pci_ifhpr;
+       u8      res6[4];
+       u32     pci_iftpr;
+       u8      res7[4];
+       u32     pci_iphpr;
+       u8      res8[4];
+       u32     pci_iptpr;
+       u8      res9[4];
+       u32     pci_ofhpr;
+       u8      res10[4];
+       u32     pci_oftpr;
+       u8      res11[4];
+       u32     pci_ophpr;
+       u8      res12[4];
+       u32     pci_optpr;
+       u8      res13[8];
+       u32     pci_mucr;
+       u8      res14[8];
+       u32     pci_qbar;
+       u8      res15[12];
+       u32     pci_dmamr0;
+       u32     pci_dmasr0;
+       u32     pci_dmacdar0;
+       u8      res16[4];
+       u32     pci_dmasar0;
+       u8      res17[4];
+       u32     pci_dmadar0;
+       u8      res18[4];
+       u32     pci_dmabcr0;
+       u32     pci_dmandar0;
+       u8      res19[86];
+       u32     pci_dmamr1;
+       u32     pci_dmasr1;
+       u32     pci_dmacdar1;
+       u8      res20[4];
+       u32     pci_dmasar1;
+       u8      res21[4];
+       u32     pci_dmadar1;
+       u8      res22[4];
+       u32     pci_dmabcr1;
+       u32     pci_dmandar1;
+       u8      res23[88];
+       u32     pci_dmamr2;
+       u32     pci_dmasr2;
+       u32     pci_dmacdar2;
+       u8      res24[4];
+       u32     pci_dmasar2;
+       u8      res25[4];
+       u32     pci_dmadar2;
+       u8      res26[4];
+       u32     pci_dmabcr2;
+       u32     pci_dmandar2;
+       u8      res27[88];
+       u32     pci_dmamr3;
+       u32     pci_dmasr3;
+       u32     pci_dmacdar3;
+       u8      res28[4];
+       u32     pci_dmasar3;
+       u8      res29[4];
+       u32     pci_dmadar3;
+       u8      res30[4];
+       u32     pci_dmabcr3;
+       u32     pci_dmandar3;
+       u8      res31[344];
+       u32     pci_potar0;
+       u8      res32[4];
+       u32     pci_pobar0;
+       u8      res33[4];
+       u32     pci_pocmr0;
+       u8      res34[4];
+       u32     pci_potar1;
+       u8      res35[4];
+       u32     pci_pobar1;
+       u8      res36[4];
+       u32     pci_pocmr1;
+       u8      res37[4];
+       u32     pci_potar2;
+       u8      res38[4];
+       u32     pci_pobar2;
+       u8      res39[4];
+       u32     pci_pocmr2;
+       u8      res40[50];
+       u32     pci_ptcr;
+       u32     pci_gpcr;
+       u32     pci_gcr;
+       u32     pci_esr;
+       u32     pci_emr;
+       u32     pci_ecr;
+       u32     pci_eacr;
+       u8      res41[4];
+       u32     pci_edcr;
+       u8      res42[4];
+       u32     pci_eccr;
+       u8      res43[44];
+       u32     pci_pitar1;
+       u8      res44[4];
+       u32     pci_pibar1;
+       u8      res45[4];
+       u32     pci_picmr1;
+       u8      res46[4];
+       u32     pci_pitar0;
+       u8      res47[4];
+       u32     pci_pibar0;
+       u8      res48[4];
+       u32     pci_picmr0;
+       u8      res49[4];
+       u32     pci_cfg_addr;
+       u32     pci_cfg_data;
+       u32     pci_int_ack;
+       u8      res50[756];
+} pci_cpm2_t;
+
+/* Interrupt Controller.
+*/
+typedef struct interrupt_controller {
+       u16     ic_sicr;
+       u8      res1[2];
+       u32     ic_sivec;
+       u32     ic_sipnrh;
+       u32     ic_sipnrl;
+       u32     ic_siprr;
+       u32     ic_scprrh;
+       u32     ic_scprrl;
+       u32     ic_simrh;
+       u32     ic_simrl;
+       u32     ic_siexr;
+       u8      res2[88];
+} intctl_cpm2_t;
+
+/* Clocks and Reset.
+*/
+typedef struct clk_and_reset {
+       u32     car_sccr;
+       u8      res1[4];
+       u32     car_scmr;
+       u8      res2[4];
+       u32     car_rsr;
+       u32     car_rmr;
+       u8      res[104];
+} car_cpm2_t;
+
+/* Input/Output Port control/status registers.
+ * Names consistent with processor manual, although they are different
+ * from the original 8xx names.......
+ */
+typedef struct io_port {
+       u32     iop_pdira;
+       u32     iop_ppara;
+       u32     iop_psora;
+       u32     iop_podra;
+       u32     iop_pdata;
+       u8      res1[12];
+       u32     iop_pdirb;
+       u32     iop_pparb;
+       u32     iop_psorb;
+       u32     iop_podrb;
+       u32     iop_pdatb;
+       u8      res2[12];
+       u32     iop_pdirc;
+       u32     iop_pparc;
+       u32     iop_psorc;
+       u32     iop_podrc;
+       u32     iop_pdatc;
+       u8      res3[12];
+       u32     iop_pdird;
+       u32     iop_ppard;
+       u32     iop_psord;
+       u32     iop_podrd;
+       u32     iop_pdatd;
+       u8      res4[12];
+} iop_cpm2_t;
+
+/* Communication Processor Module Timers
+*/
+typedef struct cpm_timers {
+       u8      cpmt_tgcr1;
+       u8      res1[3];
+       u8      cpmt_tgcr2;
+       u8      res2[11];
+       u16     cpmt_tmr1;
+       u16     cpmt_tmr2;
+       u16     cpmt_trr1;
+       u16     cpmt_trr2;
+       u16     cpmt_tcr1;
+       u16     cpmt_tcr2;
+       u16     cpmt_tcn1;
+       u16     cpmt_tcn2;
+       u16     cpmt_tmr3;
+       u16     cpmt_tmr4;
+       u16     cpmt_trr3;
+       u16     cpmt_trr4;
+       u16     cpmt_tcr3;
+       u16     cpmt_tcr4;
+       u16     cpmt_tcn3;
+       u16     cpmt_tcn4;
+       u16     cpmt_ter1;
+       u16     cpmt_ter2;
+       u16     cpmt_ter3;
+       u16     cpmt_ter4;
+       u8      res3[584];
+} cpmtimer_cpm2_t;
+
+/* DMA control/status registers.
+*/
+typedef struct sdma_csr {
+       u8      res0[24];
+       u8      sdma_sdsr;
+       u8      res1[3];
+       u8      sdma_sdmr;
+       u8      res2[3];
+       u8      sdma_idsr1;
+       u8      res3[3];
+       u8      sdma_idmr1;
+       u8      res4[3];
+       u8      sdma_idsr2;
+       u8      res5[3];
+       u8      sdma_idmr2;
+       u8      res6[3];
+       u8      sdma_idsr3;
+       u8      res7[3];
+       u8      sdma_idmr3;
+       u8      res8[3];
+       u8      sdma_idsr4;
+       u8      res9[3];
+       u8      sdma_idmr4;
+       u8      res10[707];
+} sdma_cpm2_t;
+
+/* Fast controllers
+*/
+typedef struct fcc {
+       u32     fcc_gfmr;
+       u32     fcc_fpsmr;
+       u16     fcc_ftodr;
+       u8      res1[2];
+       u16     fcc_fdsr;
+       u8      res2[2];
+       u16     fcc_fcce;
+       u8      res3[2];
+       u16     fcc_fccm;
+       u8      res4[2];
+       u8      fcc_fccs;
+       u8      res5[3];
+       u8      fcc_ftirr_phy[4];
+} fcc_t;
+
+/* Fast controllers continued
+ */
+typedef struct fcc_c {
+       u32     fcc_firper;
+       u32     fcc_firer;
+       u32     fcc_firsr_hi;
+       u32     fcc_firsr_lo;
+       u8      fcc_gfemr;
+       u8      res1[15];
+} fcc_c_t;
+
+/* TC Layer
+ */
+typedef struct tclayer {
+       u16     tc_tcmode;
+       u16     tc_cdsmr;
+       u16     tc_tcer;
+       u16     tc_rcc;
+       u16     tc_tcmr;
+       u16     tc_fcc;
+       u16     tc_ccc;
+       u16     tc_icc;
+       u16     tc_tcc;
+       u16     tc_ecc;
+       u8      res1[12];
+} tclayer_t;
+
+
+/* I2C
+*/
+typedef struct i2c {
+       u8      i2c_i2mod;
+       u8      res1[3];
+       u8      i2c_i2add;
+       u8      res2[3];
+       u8      i2c_i2brg;
+       u8      res3[3];
+       u8      i2c_i2com;
+       u8      res4[3];
+       u8      i2c_i2cer;
+       u8      res5[3];
+       u8      i2c_i2cmr;
+       u8      res6[331];
+} i2c_cpm2_t;
+
+typedef struct scc {           /* Serial communication channels */
+       u32     scc_gsmrl;
+       u32     scc_gsmrh;
+       u16     scc_psmr;
+       u8      res1[2];
+       u16     scc_todr;
+       u16     scc_dsr;
+       u16     scc_scce;
+       u8      res2[2];
+       u16     scc_sccm;
+       u8      res3;
+       u8      scc_sccs;
+       u8      res4[8];
+} scc_t;
+
+typedef struct smc {           /* Serial management channels */
+       u8      res1[2];
+       u16     smc_smcmr;
+       u8      res2[2];
+       u8      smc_smce;
+       u8      res3[3];
+       u8      smc_smcm;
+       u8      res4[5];
+} smc_t;
+
+/* Serial Peripheral Interface.
+*/
+typedef struct spi_ctrl {
+       u16     spi_spmode;
+       u8      res1[4];
+       u8      spi_spie;
+       u8      res2[3];
+       u8      spi_spim;
+       u8      res3[2];
+       u8      spi_spcom;
+       u8      res4[82];
+} spictl_cpm2_t;
+
+/* CPM Mux.
+*/
+typedef struct cpmux {
+       u8      cmx_si1cr;
+       u8      res1;
+       u8      cmx_si2cr;
+       u8      res2;
+       u32     cmx_fcr;
+       u32     cmx_scr;
+       u8      cmx_smr;
+       u8      res3;
+       u16     cmx_uar;
+       u8      res4[16];
+} cpmux_t;
+
+/* SIRAM control
+*/
+typedef struct siram {
+       u16     si_amr;
+       u16     si_bmr;
+       u16     si_cmr;
+       u16     si_dmr;
+       u8      si_gmr;
+       u8      res1;
+       u8      si_cmdr;
+       u8      res2;
+       u8      si_str;
+       u8      res3;
+       u16     si_rsr;
+} siramctl_t;
+
+typedef struct mcc {
+       u16     mcc_mcce;
+       u8      res1[2];
+       u16     mcc_mccm;
+       u8      res2[2];
+       u8      mcc_mccf;
+       u8      res3[7];
+} mcc_t;
+
+typedef struct comm_proc {
+       u32     cp_cpcr;
+       u32     cp_rccr;
+       u8      res1[14];
+       u16     cp_rter;
+       u8      res2[2];
+       u16     cp_rtmr;
+       u16     cp_rtscr;
+       u8      res3[2];
+       u32     cp_rtsr;
+       u8      res4[12];
+} cpm_cpm2_t;
+
+/* USB Controller.
+*/
+typedef struct usb_ctlr {
+       u8      usb_usmod;
+       u8      usb_usadr;
+       u8      usb_uscom;
+       u8      res1[1];
+       u16     usb_usep1;
+       u16     usb_usep2;
+       u16     usb_usep3;
+       u16     usb_usep4;
+       u8      res2[4];
+       u16     usb_usber;
+       u8      res3[2];
+       u16     usb_usbmr;
+       u8      usb_usbs;
+       u8      res4[7];
+} usb_cpm2_t;
+
+/* ...and the whole thing wrapped up....
+*/
+
+typedef struct immap {
+       /* Some references are into the unique and known dpram spaces,
+        * others are from the generic base.
+        */
+#define im_dprambase   im_dpram1
+       u8              im_dpram1[16*1024];
+       u8              res1[16*1024];
+       u8              im_dpram2[4*1024];
+       u8              res2[8*1024];
+       u8              im_dpram3[4*1024];
+       u8              res3[16*1024];
+
+       sysconf_cpm2_t  im_siu_conf;    /* SIU Configuration */
+       memctl_cpm2_t   im_memctl;      /* Memory Controller */
+       sit_cpm2_t      im_sit;         /* System Integration Timers */
+       pci_cpm2_t      im_pci;         /* PCI Controller */
+       intctl_cpm2_t   im_intctl;      /* Interrupt Controller */
+       car_cpm2_t      im_clkrst;      /* Clocks and reset */
+       iop_cpm2_t      im_ioport;      /* IO Port control/status */
+       cpmtimer_cpm2_t im_cpmtimer;    /* CPM timers */
+       sdma_cpm2_t     im_sdma;        /* SDMA control/status */
+
+       fcc_t           im_fcc[3];      /* Three FCCs */
+       u8              res4z[32];
+       fcc_c_t         im_fcc_c[3];    /* Continued FCCs */
+
+       u8              res4[32];
+
+       tclayer_t       im_tclayer[8];  /* Eight TCLayers */
+       u16             tc_tcgsr;
+       u16             tc_tcger;
+       
+       /* First set of baud rate generators.
+       */
+       u8              res[236];
+       u32             im_brgc5;
+       u32             im_brgc6;
+       u32             im_brgc7;
+       u32             im_brgc8;
+
+       u8              res5[608];
+
+       i2c_cpm2_t      im_i2c;         /* I2C control/status */
+       cpm_cpm2_t      im_cpm;         /* Communication processor */
+
+       /* Second set of baud rate generators.
+       */
+       u32             im_brgc1;
+       u32             im_brgc2;
+       u32             im_brgc3;
+       u32             im_brgc4;
+
+       scc_t           im_scc[4];      /* Four SCCs */
+       smc_t           im_smc[2];      /* Couple of SMCs */
+       spictl_cpm2_t   im_spi;         /* A SPI */
+       cpmux_t         im_cpmux;       /* CPM clock route mux */
+       siramctl_t      im_siramctl1;   /* First SI RAM Control */
+       mcc_t           im_mcc1;        /* First MCC */
+       siramctl_t      im_siramctl2;   /* Second SI RAM Control */
+       mcc_t           im_mcc2;        /* Second MCC */
+       usb_cpm2_t      im_usb;         /* USB Controller */
+
+       u8              res6[1153];
+
+       u16             im_si1txram[256];
+       u8              res7[512];
+       u16             im_si1rxram[256];
+       u8              res8[512];
+       u16             im_si2txram[256];
+       u8              res9[512];
+       u16             im_si2rxram[256];
+       u8              res10[512];
+       u8              res11[4096];
+} cpm2_map_t;
+
+extern cpm2_map_t      *cpm2_immr;
+
+#endif /* __IMMAP_CPM2__ */
+#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/m8260_pci.h b/include/asm-ppc/m8260_pci.h
new file mode 100644 (file)
index 0000000..163a6b9
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * include/asm-ppc/m8260_pci.h
+ *
+ * Definitions for the MPC8250/MPC8265/MPC8266 integrated PCI host bridge.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifdef __KERNEL__
+#ifndef __M8260_PCI_H
+#define __M8260_PCI_H
+
+#include <linux/pci_ids.h>
+
+/*
+ * Define the vendor/device ID for the MPC8265.
+ */
+#define        PCI_DEVICE_ID_MPC8265   ((0x18C0 << 16) | PCI_VENDOR_ID_MOTOROLA)
+
+#define M8265_PCIBR0   0x101ac
+#define M8265_PCIBR1   0x101b0
+#define M8265_PCIMSK0  0x101c4
+#define M8265_PCIMSK1  0x101c8
+
+/* Bit definitions for PCIBR registers */
+
+#define PCIBR_ENABLE        0x00000001
+
+/* Bit definitions for PCIMSK registers */
+
+#define PCIMSK_32KiB         0xFFFF8000  /* Size of window, smallest */
+#define PCIMSK_64KiB         0xFFFF0000
+#define PCIMSK_128KiB        0xFFFE0000
+#define PCIMSK_256KiB        0xFFFC0000
+#define PCIMSK_512KiB        0xFFF80000
+#define PCIMSK_1MiB          0xFFF00000
+#define PCIMSK_2MiB          0xFFE00000
+#define PCIMSK_4MiB          0xFFC00000
+#define PCIMSK_8MiB          0xFF800000
+#define PCIMSK_16MiB         0xFF000000
+#define PCIMSK_32MiB         0xFE000000
+#define PCIMSK_64MiB         0xFC000000
+#define PCIMSK_128MiB        0xF8000000
+#define PCIMSK_256MiB        0xF0000000
+#define PCIMSK_512MiB        0xE0000000
+#define PCIMSK_1GiB          0xC0000000  /* Size of window, largest */
+
+
+#define M826X_SCCR_PCI_MODE_EN 0x100
+
+
+/*
+ * Outbound ATU registers (3 sets). These registers control how 60x bus (local) 
+ * addresses are translated to PCI addresses when the MPC826x is a PCI bus 
+ * master (initiator).
+ */
+
+#define POTAR_REG0          0x10800     /* PCI Outbound Translation Addr registers */
+#define POTAR_REG1          0x10818
+#define POTAR_REG2          0x10830
+
+#define POBAR_REG0          0x10808     /* PCI Outbound Base Addr registers */
+#define POBAR_REG1          0x10820
+#define POBAR_REG2          0x10838
+
+#define POCMR_REG0          0x10810     /* PCI Outbound Comparison Mask registers */
+#define POCMR_REG1          0x10828
+#define POCMR_REG2          0x10840
+
+/* Bit definitions for POMCR registers */
+
+#define POCMR_MASK_4KiB      0x000FFFFF
+#define POCMR_MASK_8KiB      0x000FFFFE
+#define POCMR_MASK_16KiB     0x000FFFFC
+#define POCMR_MASK_32KiB     0x000FFFF8
+#define POCMR_MASK_64KiB     0x000FFFF0
+#define POCMR_MASK_128KiB    0x000FFFE0
+#define POCMR_MASK_256KiB    0x000FFFC0
+#define POCMR_MASK_512KiB    0x000FFF80
+#define POCMR_MASK_1MiB      0x000FFF00
+#define POCMR_MASK_2MiB      0x000FFE00
+#define POCMR_MASK_4MiB      0x000FFC00
+#define POCMR_MASK_8MiB      0x000FF800
+#define POCMR_MASK_16MiB     0x000FF000
+#define POCMR_MASK_32MiB     0x000FE000
+#define POCMR_MASK_64MiB     0x000FC000
+#define POCMR_MASK_128MiB    0x000F8000
+#define POCMR_MASK_256MiB    0x000F0000
+#define POCMR_MASK_512MiB    0x000E0000
+#define POCMR_MASK_1GiB      0x000C0000
+
+#define POCMR_ENABLE        0x80000000
+#define POCMR_PCI_IO        0x40000000
+#define POCMR_PREFETCH_EN   0x20000000
+
+/* Soft PCI reset */
+
+#define PCI_GCR_REG         0x10880
+
+/* Bit definitions for PCI_GCR registers */
+
+#define PCIGCR_PCI_BUS_EN   0x1
+
+#define PCI_EMR_REG        0x10888
+/*
+ * Inbound ATU registers (2 sets). These registers control how PCI addresses 
+ * are translated to 60x bus (local) addresses when the MPC826x is a PCI bus target.
+ */
+
+#define PITAR_REG1          0x108D0
+#define PIBAR_REG1          0x108D8
+#define PICMR_REG1          0x108E0
+#define PITAR_REG0          0x108E8
+#define PIBAR_REG0          0x108F0
+#define PICMR_REG0          0x108F8
+
+/* Bit definitions for PCI Inbound Comparison Mask registers */
+
+#define PICMR_MASK_4KiB       0x000FFFFF
+#define PICMR_MASK_8KiB       0x000FFFFE
+#define PICMR_MASK_16KiB      0x000FFFFC
+#define PICMR_MASK_32KiB      0x000FFFF8
+#define PICMR_MASK_64KiB      0x000FFFF0
+#define PICMR_MASK_128KiB     0x000FFFE0
+#define PICMR_MASK_256KiB     0x000FFFC0
+#define PICMR_MASK_512KiB     0x000FFF80
+#define PICMR_MASK_1MiB       0x000FFF00
+#define PICMR_MASK_2MiB       0x000FFE00
+#define PICMR_MASK_4MiB       0x000FFC00
+#define PICMR_MASK_8MiB       0x000FF800
+#define PICMR_MASK_16MiB      0x000FF000
+#define PICMR_MASK_32MiB      0x000FE000
+#define PICMR_MASK_64MiB      0x000FC000
+#define PICMR_MASK_128MiB     0x000F8000
+#define PICMR_MASK_256MiB     0x000F0000
+#define PICMR_MASK_512MiB     0x000E0000
+#define PICMR_MASK_1GiB       0x000C0000
+
+#define PICMR_ENABLE         0x80000000
+#define PICMR_NO_SNOOP_EN    0x40000000
+#define PICMR_PREFETCH_EN    0x20000000
+
+/* PCI error Registers */
+
+#define        PCI_ERROR_STATUS_REG            0x10884
+#define        PCI_ERROR_MASK_REG              0x10888
+#define        PCI_ERROR_CONTROL_REG           0x1088C
+#define PCI_ERROR_ADRS_CAPTURE_REG      0x10890
+#define PCI_ERROR_DATA_CAPTURE_REG      0x10898
+#define PCI_ERROR_CTRL_CAPTURE_REG      0x108A0
+
+/* PCI error Register bit defines */
+
+#define        PCI_ERROR_PCI_ADDR_PAR                  0x00000001
+#define        PCI_ERROR_PCI_DATA_PAR_WR               0x00000002
+#define        PCI_ERROR_PCI_DATA_PAR_RD               0x00000004
+#define        PCI_ERROR_PCI_NO_RSP                    0x00000008
+#define        PCI_ERROR_PCI_TAR_ABT                   0x00000010
+#define        PCI_ERROR_PCI_SERR                      0x00000020
+#define        PCI_ERROR_PCI_PERR_RD                   0x00000040
+#define        PCI_ERROR_PCI_PERR_WR                   0x00000080
+#define        PCI_ERROR_I2O_OFQO                      0x00000100
+#define        PCI_ERROR_I2O_IPQO                      0x00000200
+#define        PCI_ERROR_IRA                           0x00000400
+#define        PCI_ERROR_NMI                           0x00000800
+#define        PCI_ERROR_I2O_DBMC                      0x00001000
+
+/*
+ * Register pair used to generate configuration cycles on the PCI bus
+ * and access the MPC826x's own PCI configuration registers.
+ */
+
+#define PCI_CFG_ADDR_REG     0x10900
+#define PCI_CFG_DATA_REG     0x10904
+
+/* Bus parking decides where the bus control sits when idle */
+/* If modifying memory controllers for PCI park on the core */
+
+#define PPC_ACR_BUS_PARK_CORE 0x6
+#define PPC_ACR_BUS_PARK_PCI  0x3
+
+#endif /* __M8260_PCI_H */
+#endif /* __KERNEL__ */
diff --git a/include/asm-ppc64/netdump.h b/include/asm-ppc64/netdump.h
new file mode 100644 (file)
index 0000000..8b9fef2
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_PPC64_NETDUMP_H_
+#define _ASM_PPC64_NETDUMP_H_
+
+#include <asm-generic/netdump.h>
+
+#endif /* _ASM_PPC64_NETDUMP_H_ */
diff --git a/include/asm-s390/netdump.h b/include/asm-s390/netdump.h
new file mode 100644 (file)
index 0000000..0ad1104
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_S390_NETDUMP_H_
+#define _ASM_S390_NETDUMP_H_
+
+#include <asm-generic/netdump.h>
+
+#endif /* _ASM_S390_NETDUMP_H_ */
diff --git a/include/asm-sh/adc.h b/include/asm-sh/adc.h
new file mode 100644 (file)
index 0000000..64747dc
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __ASM_ADC_H
+#define __ASM_ADC_H
+
+/*
+ * Copyright (C) 2004  Andriy Skulysh
+ */
+
+#include <asm/cpu/adc.h>
+
+int adc_single(unsigned int channel);
+
+#endif /* __ASM_ADC_H */
diff --git a/include/asm-sh/cpu-sh3/adc.h b/include/asm-sh/cpu-sh3/adc.h
new file mode 100644 (file)
index 0000000..b289e3c
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __ASM_CPU_SH3_ADC_H
+#define __ASM_CPU_SH3_ADC_H
+
+/*
+ * Copyright (C) 2004  Andriy Skulysh
+ */
+
+
+#define ADDRAH 0xa4000080
+#define ADDRAL 0xa4000082
+#define ADDRBH 0xa4000084
+#define ADDRBL 0xa4000086
+#define ADDRCH 0xa4000088
+#define ADDRCL 0xa400008a
+#define ADDRDH 0xa400008c
+#define ADDRDL 0xa400008e
+#define ADCSR  0xa4000090
+
+#define ADCSR_ADF      0x80
+#define ADCSR_ADIE     0x40
+#define ADCSR_ADST     0x20
+#define ADCSR_MULTI    0x10
+#define ADCSR_CKS      0x08
+#define ADCSR_CH_MASK  0x07
+
+#define ADCR   0xa4000092
+
+#endif /* __ASM_CPU_SH3_ADC_H */
diff --git a/include/asm-sh64/a.out.h b/include/asm-sh64/a.out.h
new file mode 100644 (file)
index 0000000..e1995e8
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef __ASM_SH64_A_OUT_H
+#define __ASM_SH64_A_OUT_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/a.out.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+
+struct exec
+{
+  unsigned long a_info;                /* Use macros N_MAGIC, etc for access */
+  unsigned a_text;             /* length of text, in bytes */
+  unsigned a_data;             /* length of data, in bytes */
+  unsigned a_bss;              /* length of uninitialized data area for file, in bytes */
+  unsigned a_syms;             /* length of symbol table data in file, in bytes */
+  unsigned a_entry;            /* start address */
+  unsigned a_trsize;           /* length of relocation info for text, in bytes */
+  unsigned a_drsize;           /* length of relocation info for data, in bytes */
+};
+
+#define N_TRSIZE(a)    ((a).a_trsize)
+#define N_DRSIZE(a)    ((a).a_drsize)
+#define N_SYMSIZE(a)   ((a).a_syms)
+
+#ifdef __KERNEL__
+
+#define STACK_TOP      TASK_SIZE
+
+#endif
+
+#endif /* __ASM_SH64_A_OUT_H */
diff --git a/include/asm-sh64/atomic.h b/include/asm-sh64/atomic.h
new file mode 100644 (file)
index 0000000..8c3872d
--- /dev/null
@@ -0,0 +1,126 @@
+#ifndef __ASM_SH64_ATOMIC_H
+#define __ASM_SH64_ATOMIC_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/atomic.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003  Paul Mundt
+ *
+ */
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ *
+ */
+
+typedef struct { volatile int counter; } atomic_t;
+
+#define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
+
+#define atomic_read(v)         ((v)->counter)
+#define atomic_set(v,i)                ((v)->counter = (i))
+
+#include <asm/system.h>
+
+/*
+ * To get proper branch prediction for the main line, we must branch
+ * forward to code at the end of this object's .text section, then
+ * branch back to restart the operation.
+ */
+
+static __inline__ void atomic_add(int i, atomic_t * v)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       *(long *)v += i;
+       local_irq_restore(flags);
+}
+
+static __inline__ void atomic_sub(int i, atomic_t *v)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       *(long *)v -= i;
+       local_irq_restore(flags);
+}
+
+static __inline__ int atomic_add_return(int i, atomic_t * v)
+{
+       unsigned long temp, flags;
+
+       local_irq_save(flags);
+       temp = *(long *)v;
+       temp += i;
+       *(long *)v = temp;
+       local_irq_restore(flags);
+
+       return temp;
+}
+
+#define atomic_add_negative(a, v)      (atomic_add_return((a), (v)) < 0)
+
+static __inline__ int atomic_sub_return(int i, atomic_t * v)
+{
+       unsigned long temp, flags;
+
+       local_irq_save(flags);
+       temp = *(long *)v;
+       temp -= i;
+       *(long *)v = temp;
+       local_irq_restore(flags);
+
+       return temp;
+}
+
+#define atomic_dec_return(v) atomic_sub_return(1,(v))
+#define atomic_inc_return(v) atomic_add_return(1,(v))
+
+/*
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
+
+#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
+#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+
+#define atomic_inc(v) atomic_add(1,(v))
+#define atomic_dec(v) atomic_sub(1,(v))
+
+static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       *(long *)v &= ~mask;
+       local_irq_restore(flags);
+}
+
+static __inline__ void atomic_set_mask(unsigned int mask, atomic_t *v)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       *(long *)v |= mask;
+       local_irq_restore(flags);
+}
+
+/* Atomic operations are already serializing on SH */
+#define smp_mb__before_atomic_dec()    barrier()
+#define smp_mb__after_atomic_dec()     barrier()
+#define smp_mb__before_atomic_inc()    barrier()
+#define smp_mb__after_atomic_inc()     barrier()
+
+#endif /* __ASM_SH64_ATOMIC_H */
diff --git a/include/asm-sh64/bugs.h b/include/asm-sh64/bugs.h
new file mode 100644 (file)
index 0000000..05554aa
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef __ASM_SH64_BUGS_H
+#define __ASM_SH64_BUGS_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/bugs.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003  Paul Mundt
+ *
+ */
+
+/*
+ * This is included by init/main.c to check for architecture-dependent bugs.
+ *
+ * Needs:
+ *     void check_bugs(void);
+ */
+
+/*
+ * I don't know of any Super-H bugs yet.
+ */
+
+#include <asm/processor.h>
+
+static void __init check_bugs(void)
+{
+       extern char *get_cpu_subtype(void);
+       extern unsigned long loops_per_jiffy;
+
+       cpu_data->loops_per_jiffy = loops_per_jiffy;
+
+       printk("CPU: %s\n", get_cpu_subtype());
+}
+#endif /* __ASM_SH64_BUGS_H */
diff --git a/include/asm-sh64/cache.h b/include/asm-sh64/cache.h
new file mode 100644 (file)
index 0000000..f54e85e
--- /dev/null
@@ -0,0 +1,141 @@
+#ifndef __ASM_SH64_CACHE_H
+#define __ASM_SH64_CACHE_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/cache.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003, 2004  Paul Mundt
+ *
+ */
+#include <asm/cacheflush.h>
+
+#define L1_CACHE_SHIFT         5
+/* bytes per L1 cache line */
+#define L1_CACHE_BYTES         (1 << L1_CACHE_SHIFT)
+#define L1_CACHE_ALIGN_MASK    (~(L1_CACHE_BYTES - 1))
+#define L1_CACHE_ALIGN(x)      (((x)+(L1_CACHE_BYTES - 1)) & L1_CACHE_ALIGN_MASK)
+#define L1_CACHE_SIZE_BYTES    (L1_CACHE_BYTES << 10)
+/* Largest L1 which this arch supports */
+#define L1_CACHE_SHIFT_MAX     5
+
+#ifdef MODULE
+#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES)))
+#else
+#define __cacheline_aligned                                    \
+  __attribute__((__aligned__(L1_CACHE_BYTES),                  \
+                __section__(".data.cacheline_aligned")))
+#endif
+
+/*
+ * Control Registers.
+ */
+#define ICCR_BASE      0x01600000      /* Instruction Cache Control Register */
+#define ICCR_REG0      0               /* Register 0 offset */
+#define ICCR_REG1      1               /* Register 1 offset */
+#define ICCR0          ICCR_BASE+ICCR_REG0
+#define ICCR1          ICCR_BASE+ICCR_REG1
+
+#define ICCR0_OFF      0x0             /* Set ICACHE off */
+#define ICCR0_ON       0x1             /* Set ICACHE on */
+#define ICCR0_ICI      0x2             /* Invalidate all in IC */
+
+#define ICCR1_NOLOCK   0x0             /* Set No Locking */
+
+#define OCCR_BASE      0x01E00000      /* Operand Cache Control Register */
+#define OCCR_REG0      0               /* Register 0 offset */
+#define OCCR_REG1      1               /* Register 1 offset */
+#define OCCR0          OCCR_BASE+OCCR_REG0
+#define OCCR1          OCCR_BASE+OCCR_REG1
+
+#define OCCR0_OFF      0x0             /* Set OCACHE off */
+#define OCCR0_ON       0x1             /* Set OCACHE on */
+#define OCCR0_OCI      0x2             /* Invalidate all in OC */
+#define OCCR0_WT       0x4             /* Set OCACHE in WT Mode */
+#define OCCR0_WB       0x0             /* Set OCACHE in WB Mode */
+
+#define OCCR1_NOLOCK   0x0             /* Set No Locking */
+
+
+/*
+ * SH-5
+ * A bit of description here, for neff=32.
+ *
+ *                               |<--- tag  (19 bits) --->|
+ * +-----------------------------+-----------------+------+----------+------+
+ * |                             |                 | ways |set index |offset|
+ * +-----------------------------+-----------------+------+----------+------+
+ *                                ^                 2 bits   8 bits   5 bits
+ *                                +- Bit 31
+ *
+ * Cacheline size is based on offset: 5 bits = 32 bytes per line
+ * A cache line is identified by a tag + set but OCACHETAG/ICACHETAG
+ * have a broader space for registers. These are outlined by
+ * CACHE_?C_*_STEP below.
+ *
+ */
+
+/* Valid and Dirty bits */
+#define SH_CACHE_VALID         (1LL<<0)
+#define SH_CACHE_UPDATED       (1LL<<57)
+
+/* Cache flags */
+#define SH_CACHE_MODE_WT       (1LL<<0)
+#define SH_CACHE_MODE_WB       (1LL<<1)
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Cache information structure.
+ *
+ * Defined for both I and D cache, per-processor.
+ */
+struct cache_info {
+       unsigned int ways;
+       unsigned int sets;
+       unsigned int linesz;
+
+       unsigned int way_shift;
+       unsigned int entry_shift;
+       unsigned int set_shift;
+       unsigned int way_step_shift;
+       unsigned int asid_shift;
+
+       unsigned int way_ofs;
+
+       unsigned int asid_mask;
+       unsigned int idx_mask;
+       unsigned int epn_mask;
+
+       unsigned long flags;
+};
+
+#endif /* __ASSEMBLY__ */
+
+/* Instruction cache */
+#define CACHE_IC_ADDRESS_ARRAY 0x01000000
+
+/* Operand Cache */
+#define CACHE_OC_ADDRESS_ARRAY 0x01800000
+
+/* These declarations relate to cache 'synonyms' in the operand cache.  A
+   'synonym' occurs where effective address bits overlap between those used for
+   indexing the cache sets and those passed to the MMU for translation.  In the
+   case of SH5-101 & SH5-103, only bit 12 is affected for 4k pages. */
+
+#define CACHE_OC_N_SYNBITS  1               /* Number of synonym bits */
+#define CACHE_OC_SYN_SHIFT  12
+/* Mask to select synonym bit(s) */
+#define CACHE_OC_SYN_MASK   (((1UL<<CACHE_OC_N_SYNBITS)-1)<<CACHE_OC_SYN_SHIFT)
+
+
+/*
+ * Instruction cache can't be invalidated based on physical addresses.
+ * No Instruction Cache defines required, then.
+ */
+
+#endif /* __ASM_SH64_CACHE_H */
diff --git a/include/asm-sh64/cayman.h b/include/asm-sh64/cayman.h
new file mode 100644 (file)
index 0000000..7b6b968
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/cayman.h
+ *
+ * Cayman definitions
+ *
+ * Global defintions for the SH5 Cayman board
+ *
+ * Copyright (C) 2002 Stuart Menefy
+ */
+
+
+/* Setup for the SMSC FDC37C935 / LAN91C100FD */
+#define SMSC_IRQ         IRQ_IRL1
+
+/* Setup for PCI Bus 2, which transmits interrupts via the EPLD */
+#define PCI2_IRQ         IRQ_IRL3
diff --git a/include/asm-sh64/cpumask.h b/include/asm-sh64/cpumask.h
new file mode 100644 (file)
index 0000000..b7b105d
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH64_CPUMASK_H
+#define __ASM_SH64_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* __ASM_SH64_CPUMASK_H */
diff --git a/include/asm-sh64/current.h b/include/asm-sh64/current.h
new file mode 100644 (file)
index 0000000..2612243
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __ASM_SH64_CURRENT_H
+#define __ASM_SH64_CURRENT_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/current.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003  Paul Mundt
+ *
+ */
+
+#include <linux/thread_info.h>
+
+struct task_struct;
+
+static __inline__ struct task_struct * get_current(void)
+{
+       return current_thread_info()->task;
+}
+
+#define current get_current()
+
+#endif /* __ASM_SH64_CURRENT_H */
+
diff --git a/include/asm-sh64/delay.h b/include/asm-sh64/delay.h
new file mode 100644 (file)
index 0000000..6ae3130
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __ASM_SH64_DELAY_H
+#define __ASM_SH64_DELAY_H
+
+extern void __delay(int loops);
+extern void __udelay(unsigned long long usecs, unsigned long lpj);
+extern void __ndelay(unsigned long long nsecs, unsigned long lpj);
+extern void udelay(unsigned long usecs);
+extern void ndelay(unsigned long nsecs);
+
+#endif /* __ASM_SH64_DELAY_H */
+
diff --git a/include/asm-sh64/div64.h b/include/asm-sh64/div64.h
new file mode 100644 (file)
index 0000000..f758695
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH64_DIV64_H
+#define __ASM_SH64_DIV64_H
+
+#include <asm-generic/div64.h>
+
+#endif /* __ASM_SH64_DIV64_H */
diff --git a/include/asm-sh64/dma.h b/include/asm-sh64/dma.h
new file mode 100644 (file)
index 0000000..e701f39
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __ASM_SH64_DMA_H
+#define __ASM_SH64_DMA_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/dma.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003  Paul Mundt
+ *
+ */
+
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+
+#define MAX_DMA_CHANNELS       4
+
+/*
+ * SH5 can DMA in any memory area.
+ *
+ * The static definition is dodgy because it should limit
+ * the highest DMA-able address based on the actual
+ * Physical memory available. This is actually performed
+ * at run time in defining the memory allowed to DMA_ZONE.
+ */
+#define MAX_DMA_ADDRESS                ~(NPHYS_MASK)
+
+#define DMA_MODE_READ          0
+#define DMA_MODE_WRITE         1
+
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy   (0)
+#endif
+
+#endif /* __ASM_SH64_DMA_H */
diff --git a/include/asm-sh64/elf.h b/include/asm-sh64/elf.h
new file mode 100644 (file)
index 0000000..bc48366
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef __ASM_SH64_ELF_H
+#define __ASM_SH64_ELF_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/elf.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+#include <asm/user.h>
+#include <asm/byteorder.h>
+
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct user_fpu_struct elf_fpregset_t;
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ( (x)->e_machine == EM_SH )
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS      ELFCLASS32
+#ifdef __LITTLE_ENDIAN__
+#define ELF_DATA       ELFDATA2LSB
+#else
+#define ELF_DATA       ELFDATA2MSB
+#endif
+#define ELF_ARCH       EM_SH
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE      4096
+
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+   use of this is to invoke "./ld.so someprog" to test out a new version of
+   the loader.  We need to make sure that it is out of the way of the program
+   that it will "exec", and that there is sufficient room for the brk.  */
+
+#define ELF_ET_DYN_BASE         (2 * TASK_SIZE / 3)
+
+
+#define ELF_CORE_COPY_REGS(_dest,_regs)                                \
+       memcpy((char *) &_dest, (char *) _regs,                 \
+              sizeof(struct pt_regs));
+
+/* This yields a mask that user programs can use to figure out what
+   instruction set this CPU supports.  This could be done in user space,
+   but it's not easy, and we've already done it here.  */
+
+#define ELF_HWCAP      (0)
+
+/* This yields a string that ld.so will use to load implementation
+   specific libraries for optimization.  This is more specific in
+   intent than poking at uname or /proc/cpuinfo.
+
+   For the moment, we have only optimizations for the Intel generations,
+   but that could change... */
+
+#define ELF_PLATFORM  (NULL)
+
+#define ELF_PLAT_INIT(_r, load_addr) \
+  do { _r->regs[0]=0; _r->regs[1]=0; _r->regs[2]=0; _r->regs[3]=0; \
+       _r->regs[4]=0; _r->regs[5]=0; _r->regs[6]=0; _r->regs[7]=0; \
+       _r->regs[8]=0; _r->regs[9]=0; _r->regs[10]=0; _r->regs[11]=0; \
+       _r->regs[12]=0; _r->regs[13]=0; _r->regs[14]=0; _r->regs[15]=0; \
+       _r->regs[16]=0; _r->regs[17]=0; _r->regs[18]=0; _r->regs[19]=0; \
+       _r->regs[20]=0; _r->regs[21]=0; _r->regs[22]=0; _r->regs[23]=0; \
+       _r->regs[24]=0; _r->regs[25]=0; _r->regs[26]=0; _r->regs[27]=0; \
+       _r->regs[28]=0; _r->regs[29]=0; _r->regs[30]=0; _r->regs[31]=0; \
+       _r->regs[32]=0; _r->regs[33]=0; _r->regs[34]=0; _r->regs[35]=0; \
+       _r->regs[36]=0; _r->regs[37]=0; _r->regs[38]=0; _r->regs[39]=0; \
+       _r->regs[40]=0; _r->regs[41]=0; _r->regs[42]=0; _r->regs[43]=0; \
+       _r->regs[44]=0; _r->regs[45]=0; _r->regs[46]=0; _r->regs[47]=0; \
+       _r->regs[48]=0; _r->regs[49]=0; _r->regs[50]=0; _r->regs[51]=0; \
+       _r->regs[52]=0; _r->regs[53]=0; _r->regs[54]=0; _r->regs[55]=0; \
+       _r->regs[56]=0; _r->regs[57]=0; _r->regs[58]=0; _r->regs[59]=0; \
+       _r->regs[60]=0; _r->regs[61]=0; _r->regs[62]=0; \
+       _r->tregs[0]=0; _r->tregs[1]=0; _r->tregs[2]=0; _r->tregs[3]=0; \
+       _r->tregs[4]=0; _r->tregs[5]=0; _r->tregs[6]=0; _r->tregs[7]=0; \
+       _r->sr = SR_FD | SR_MMU; } while (0)
+
+#ifdef __KERNEL__
+#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
+#endif
+
+#endif /* __ASM_SH64_ELF_H */
diff --git a/include/asm-sh64/errno.h b/include/asm-sh64/errno.h
new file mode 100644 (file)
index 0000000..57b46d4
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH64_ERRNO_H
+#define __ASM_SH64_ERRNO_H
+
+#include <asm-generic/errno.h>
+
+#endif /* __ASM_SH64_ERRNO_H */
diff --git a/include/asm-sh64/fcntl.h b/include/asm-sh64/fcntl.h
new file mode 100644 (file)
index 0000000..ffcc36c
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __ASM_SH64_FCNTL_H
+#define __ASM_SH64_FCNTL_H
+
+#include <asm-sh/fcntl.h>
+
+#endif /* __ASM_SH64_FCNTL_H */
+
diff --git a/include/asm-sh64/hardware.h b/include/asm-sh64/hardware.h
new file mode 100644 (file)
index 0000000..a2e6112
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __ASM_SH64_HARDWARE_H
+#define __ASM_SH64_HARDWARE_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/hardware.h
+ *
+ * Copyright (C) 2002 Stuart Menefy
+ * Copyright (C) 2003 Paul Mundt
+ *
+ * Defitions of the locations of registers in the physical address space.
+ */
+
+#define        PHYS_PERIPHERAL_BLOCK   0x09000000
+#define PHYS_DMAC_BLOCK                0x0e000000
+#define PHYS_PCI_BLOCK         0x60000000
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+#include <asm/io.h>
+
+struct vcr_info {
+       u8      perr_flags;     /* P-port Error flags */
+       u8      merr_flags;     /* Module Error flags */
+       u16     mod_vers;       /* Module Version */
+       u16     mod_id;         /* Module ID */
+       u8      bot_mb;         /* Bottom Memory block */
+       u8      top_mb;         /* Top Memory block */
+};
+
+static inline struct vcr_info sh64_get_vcr_info(unsigned long base)
+{
+       unsigned long long tmp;
+
+       tmp = sh64_in64(base);
+
+       return *((struct vcr_info *)&tmp);
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_SH64_HARDWARE_H */
diff --git a/include/asm-sh64/ioctl.h b/include/asm-sh64/ioctl.h
new file mode 100644 (file)
index 0000000..c089a6f
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef __ASM_SH64_IOCTL_H
+#define __ASM_SH64_IOCTL_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/ioctl.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ * linux/ioctl.h for Linux by H.H. Bergman.
+ *
+ */
+
+/* ioctl command encoding: 32 bits total, command in lower 16 bits,
+ * size of the parameter structure in the lower 14 bits of the
+ * upper 16 bits.
+ * Encoding the size of the parameter structure in the ioctl request
+ * is useful for catching programs compiled with old versions
+ * and to avoid overwriting user space outside the user buffer area.
+ * The highest 2 bits are reserved for indicating the ``access mode''.
+ * NOTE: This limits the max parameter size to 16kB -1 !
+ */
+
+/*
+ * The following is for compatibility across the various Linux
+ * platforms.  The i386 ioctl numbering scheme doesn't really enforce
+ * a type field.  De facto, however, the top 8 bits of the lower 16
+ * bits are indeed used as a type field, so we might just as well make
+ * this explicit here.  Please be sure to use the decoding macros
+ * below from now on.
+ */
+#define _IOC_NRBITS    8
+#define _IOC_TYPEBITS  8
+#define _IOC_SIZEBITS  14
+#define _IOC_DIRBITS   2
+
+#define _IOC_NRMASK    ((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK  ((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK  ((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK   ((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT   0
+#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT  (_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * Direction bits.
+ */
+#define _IOC_NONE      0U
+#define _IOC_WRITE     1U
+#define _IOC_READ      2U
+
+#define _IOC(dir,type,nr,size) \
+       (((dir)  << _IOC_DIRSHIFT) | \
+        ((type) << _IOC_TYPESHIFT) | \
+        ((nr)   << _IOC_NRSHIFT) | \
+        ((size) << _IOC_SIZESHIFT))
+
+/* used to create numbers */
+#define _IO(type,nr)           _IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size)     _IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW(type,nr,size)     _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR(type,nr,size)    _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+/* used to decode ioctl numbers.. */
+#define _IOC_DIR(nr)           (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_TYPE(nr)          (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
+#define _IOC_NR(nr)            (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr)          (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+
+/* ...and for the drivers/sound files... */
+
+#define IOC_IN         (_IOC_WRITE << _IOC_DIRSHIFT)
+#define IOC_OUT                (_IOC_READ << _IOC_DIRSHIFT)
+#define IOC_INOUT      ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
+#define IOCSIZE_MASK   (_IOC_SIZEMASK << _IOC_SIZESHIFT)
+#define IOCSIZE_SHIFT  (_IOC_SIZESHIFT)
+
+#endif /* __ASM_SH64_IOCTL_H */
diff --git a/include/asm-sh64/ioctls.h b/include/asm-sh64/ioctls.h
new file mode 100644 (file)
index 0000000..e5d5562
--- /dev/null
@@ -0,0 +1,111 @@
+#ifndef __ASM_SH64_IOCTLS_H
+#define __ASM_SH64_IOCTLS_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/ioctls.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+
+#include <asm/ioctl.h>
+
+#define FIOCLEX                _IO('f', 1)
+#define FIONCLEX       _IO('f', 2)
+#define FIOASYNC       _IOW('f', 125, int)
+#define FIONBIO                _IOW('f', 126, int)
+#define FIONREAD       _IOR('f', 127, int)
+#define TIOCINQ                FIONREAD
+#define FIOQSIZE       _IOR('f', 128, loff_t)
+
+#define TCGETS         0x5401
+#define TCSETS         0x5402
+#define TCSETSW                0x5403
+#define TCSETSF                0x5404
+
+#define TCGETA         _IOR('t', 23, struct termio)
+#define TCSETA         _IOW('t', 24, struct termio)
+#define TCSETAW                _IOW('t', 25, struct termio)
+#define TCSETAF                _IOW('t', 28, struct termio)
+
+#define TCSBRK         _IO('t', 29)
+#define TCXONC         _IO('t', 30)
+#define TCFLSH         _IO('t', 31)
+
+#define TIOCSWINSZ     _IOW('t', 103, struct winsize)
+#define TIOCGWINSZ     _IOR('t', 104, struct winsize)
+#define        TIOCSTART       _IO('t', 110)           /* start output, like ^Q */
+#define        TIOCSTOP        _IO('t', 111)           /* stop output, like ^S */
+#define TIOCOUTQ        _IOR('t', 115, int)     /* output queue size */
+
+#define TIOCSPGRP      _IOW('t', 118, int)
+#define TIOCGPGRP      _IOR('t', 119, int)
+
+#define TIOCEXCL       _IO('T', 12) /* 0x540C */
+#define TIOCNXCL       _IO('T', 13) /* 0x540D */
+#define TIOCSCTTY      _IO('T', 14) /* 0x540E */
+
+#define TIOCSTI                _IOW('T', 18, char) /* 0x5412 */
+#define TIOCMGET       _IOR('T', 21, unsigned int) /* 0x5415 */
+#define TIOCMBIS       _IOW('T', 22, unsigned int) /* 0x5416 */
+#define TIOCMBIC       _IOW('T', 23, unsigned int) /* 0x5417 */
+#define TIOCMSET       _IOW('T', 24, unsigned int) /* 0x5418 */
+# define TIOCM_LE      0x001
+# define TIOCM_DTR     0x002
+# define TIOCM_RTS     0x004
+# define TIOCM_ST      0x008
+# define TIOCM_SR      0x010
+# define TIOCM_CTS     0x020
+# define TIOCM_CAR     0x040
+# define TIOCM_RNG     0x080
+# define TIOCM_DSR     0x100
+# define TIOCM_CD      TIOCM_CAR
+# define TIOCM_RI      TIOCM_RNG
+
+#define TIOCGSOFTCAR   _IOR('T', 25, unsigned int) /* 0x5419 */
+#define TIOCSSOFTCAR   _IOW('T', 26, unsigned int) /* 0x541A */
+#define TIOCLINUX      _IOW('T', 28, char) /* 0x541C */
+#define TIOCCONS       _IO('T', 29) /* 0x541D */
+#define TIOCGSERIAL    _IOR('T', 30, struct serial_struct) /* 0x541E */
+#define TIOCSSERIAL    _IOW('T', 31, struct serial_struct) /* 0x541F */
+#define TIOCPKT                _IOW('T', 32, int) /* 0x5420 */
+# define TIOCPKT_DATA           0
+# define TIOCPKT_FLUSHREAD      1
+# define TIOCPKT_FLUSHWRITE     2
+# define TIOCPKT_STOP           4
+# define TIOCPKT_START          8
+# define TIOCPKT_NOSTOP                16
+# define TIOCPKT_DOSTOP                32
+
+
+#define TIOCNOTTY      _IO('T', 34) /* 0x5422 */
+#define TIOCSETD       _IOW('T', 35, int) /* 0x5423 */
+#define TIOCGETD       _IOR('T', 36, int) /* 0x5424 */
+#define TCSBRKP                _IOW('T', 37, int) /* 0x5425 */ /* Needed for POSIX tcsendbreak() */
+#define TIOCTTYGSTRUCT _IOR('T', 38, struct tty_struct) /* 0x5426 */ /* For debugging only */
+#define TIOCSBRK       _IO('T', 39) /* 0x5427 */ /* BSD compatibility */
+#define TIOCCBRK       _IO('T', 40) /* 0x5428 */ /* BSD compatibility */
+#define TIOCGSID       _IOR('T', 41, pid_t) /* 0x5429 */ /* Return the session ID of FD */
+#define TIOCGPTN       _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK     _IOW('T',0x31, int)  /* Lock/unlock Pty */
+
+#define TIOCSERCONFIG  _IO('T', 83) /* 0x5453 */
+#define TIOCSERGWILD   _IOR('T', 84,  int) /* 0x5454 */
+#define TIOCSERSWILD   _IOW('T', 85,  int) /* 0x5455 */
+#define TIOCGLCKTRMIOS 0x5456
+#define TIOCSLCKTRMIOS 0x5457
+#define TIOCSERGSTRUCT _IOR('T', 88, struct async_struct) /* 0x5458 */ /* For debugging only */
+#define TIOCSERGETLSR   _IOR('T', 89, unsigned int) /* 0x5459 */ /* Get line status register */
+  /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+# define TIOCSER_TEMT    0x01  /* Transmitter physically empty */
+#define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* 0x545A */ /* Get multiport config  */
+#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* 0x545B */ /* Set multiport config */
+
+#define TIOCMIWAIT     _IO('T', 92) /* 0x545C */       /* wait for a change on serial input line(s) */
+#define TIOCGICOUNT    _IOR('T', 93, struct async_icount) /* 0x545D */ /* read serial port inline interrupt counts */
+
+#endif /* __ASM_SH64_IOCTLS_H */
diff --git a/include/asm-sh64/ipc.h b/include/asm-sh64/ipc.h
new file mode 100644 (file)
index 0000000..d8d9389
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH64_IPC_H
+#define __ASM_SH64_IPC_H
+
+#include <asm-sh/ipc.h>
+
+#endif /* __ASM_SH64_IPC_H */
diff --git a/include/asm-sh64/ipcbuf.h b/include/asm-sh64/ipcbuf.h
new file mode 100644 (file)
index 0000000..c441e35
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef __ASM_SH64_IPCBUF_H__
+#define __ASM_SH64_IPCBUF_H__
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/ipcbuf.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+
+/*
+ * The ipc64_perm structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit mode_t and seq
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct ipc64_perm
+{
+       __kernel_key_t          key;
+       __kernel_uid32_t        uid;
+       __kernel_gid32_t        gid;
+       __kernel_uid32_t        cuid;
+       __kernel_gid32_t        cgid;
+       __kernel_mode_t         mode;
+       unsigned short          __pad1;
+       unsigned short          seq;
+       unsigned short          __pad2;
+       unsigned long           __unused1;
+       unsigned long           __unused2;
+};
+
+#endif /* __ASM_SH64_IPCBUF_H__ */
diff --git a/include/asm-sh64/kmap_types.h b/include/asm-sh64/kmap_types.h
new file mode 100644 (file)
index 0000000..2ae7c75
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __ASM_SH64_KMAP_TYPES_H
+#define __ASM_SH64_KMAP_TYPES_H
+
+#include <asm-sh/kmap_types.h>
+
+#endif /* __ASM_SH64_KMAP_TYPES_H */
+
diff --git a/include/asm-sh64/linkage.h b/include/asm-sh64/linkage.h
new file mode 100644 (file)
index 0000000..1dd0e84
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __ASM_SH64_LINKAGE_H
+#define __ASM_SH64_LINKAGE_H
+
+#include <asm-sh/linkage.h>
+
+#endif /* __ASM_SH64_LINKAGE_H */
+
diff --git a/include/asm-sh64/local.h b/include/asm-sh64/local.h
new file mode 100644 (file)
index 0000000..d9bd95d
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __ASM_SH64_LOCAL_H
+#define __ASM_SH64_LOCAL_H
+
+#include <asm-generic/local.h>
+
+#endif /* __ASM_SH64_LOCAL_H */
+
diff --git a/include/asm-sh64/mc146818rtc.h b/include/asm-sh64/mc146818rtc.h
new file mode 100644 (file)
index 0000000..6cd3aec
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * linux/include/asm-sh64/mc146818rtc.h
+ *
+*/
+
+/* For now, an empty place-holder to get IDE to compile. */
+
diff --git a/include/asm-sh64/mman.h b/include/asm-sh64/mman.h
new file mode 100644 (file)
index 0000000..a9be6d8
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH64_MMAN_H
+#define __ASM_SH64_MMAN_H
+
+#include <asm-sh/mman.h>
+
+#endif /* __ASM_SH64_MMAN_H */
diff --git a/include/asm-sh64/mmu.h b/include/asm-sh64/mmu.h
new file mode 100644 (file)
index 0000000..ccd36d2
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __MMU_H
+#define __MMU_H
+
+/* Default "unsigned long" context */
+typedef unsigned long mm_context_t;
+
+#endif
diff --git a/include/asm-sh64/module.h b/include/asm-sh64/module.h
new file mode 100644 (file)
index 0000000..bf382bc
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __ASM_SH64_MODULE_H
+#define __ASM_SH64_MODULE_H
+/*
+ * This file contains the SH architecture specific module code.
+ */
+
+#define module_map(x)          vmalloc(x)
+#define module_unmap(x)                vfree(x)
+#define module_arch_init(x)    (0)
+#define arch_init_modules(x)   do { } while (0)
+
+#endif /* __ASM_SH64_MODULE_H */
diff --git a/include/asm-sh64/msgbuf.h b/include/asm-sh64/msgbuf.h
new file mode 100644 (file)
index 0000000..cf0494c
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef __ASM_SH64_MSGBUF_H
+#define __ASM_SH64_MSGBUF_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/msgbuf.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+
+/*
+ * The msqid64_ds structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct msqid64_ds {
+       struct ipc64_perm msg_perm;
+       __kernel_time_t msg_stime;      /* last msgsnd time */
+       unsigned long   __unused1;
+       __kernel_time_t msg_rtime;      /* last msgrcv time */
+       unsigned long   __unused2;
+       __kernel_time_t msg_ctime;      /* last change time */
+       unsigned long   __unused3;
+       unsigned long  msg_cbytes;      /* current number of bytes on queue */
+       unsigned long  msg_qnum;        /* number of messages in queue */
+       unsigned long  msg_qbytes;      /* max number of bytes on queue */
+       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
+       __kernel_pid_t msg_lrpid;       /* last receive pid */
+       unsigned long  __unused4;
+       unsigned long  __unused5;
+};
+
+#endif /* __ASM_SH64_MSGBUF_H */
diff --git a/include/asm-sh64/namei.h b/include/asm-sh64/namei.h
new file mode 100644 (file)
index 0000000..99d759a
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __ASM_SH64_NAMEI_H
+#define __ASM_SH64_NAMEI_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/namei.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ * Included from linux/fs/namei.c
+ *
+ */
+
+/* This dummy routine maybe changed to something useful
+ * for /usr/gnemul/ emulation stuff.
+ * Look at asm-sparc/namei.h for details.
+ */
+
+#define __emul_prefix() NULL
+
+#endif /* __ASM_SH64_NAMEI_H */
diff --git a/include/asm-sh64/pci.h b/include/asm-sh64/pci.h
new file mode 100644 (file)
index 0000000..8cc14e1
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef __ASM_SH64_PCI_H
+#define __ASM_SH64_PCI_H
+
+#ifdef __KERNEL__
+
+#include <linux/dma-mapping.h>
+
+/* Can be used to override the logic in pci_scan_bus for skipping
+   already-configured bus numbers - to be used for buggy BIOSes
+   or architectures with incomplete PCI setup by the loader */
+
+#define pcibios_assign_all_busses()     1
+
+/*
+ * 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 defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
+#define PCIBIOS_MIN_IO          0x2000
+#define PCIBIOS_MIN_MEM         0x40000000
+#endif
+
+extern void pcibios_set_master(struct pci_dev *dev);
+
+/*
+ * Set penalize isa irq function
+ */
+static inline void pcibios_penalize_isa_irq(int irq)
+{
+       /* We don't do dynamic PCI IRQ allocation */
+}
+
+/* Dynamic DMA mapping stuff.
+ * SuperH has everything mapped statically like x86.
+ */
+
+/* The PCI address space does equal the physical memory
+ * address space.  The networking and block device layers use
+ * this boolean for bounce buffer decisions.
+ */
+#define PCI_DMA_BUS_IS_PHYS    (1)
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/scatterlist.h>
+#include <linux/string.h>
+#include <asm/io.h>
+
+/* pci_unmap_{single,page} being a nop depends upon the
+ * configuration.
+ */
+#ifdef CONFIG_SH_PCIDMA_NONCOHERENT
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)      \
+       dma_addr_t ADDR_NAME;
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)                \
+       __u32 LEN_NAME;
+#define pci_unmap_addr(PTR, ADDR_NAME)                 \
+       ((PTR)->ADDR_NAME)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)                \
+       (((PTR)->ADDR_NAME) = (VAL))
+#define pci_unmap_len(PTR, LEN_NAME)                   \
+       ((PTR)->LEN_NAME)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)          \
+       (((PTR)->LEN_NAME) = (VAL))
+#else
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
+#define pci_unmap_addr(PTR, ADDR_NAME)         (0)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)        do { } while (0)
+#define pci_unmap_len(PTR, LEN_NAME)           (0)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)  do { } while (0)
+#endif
+
+/* Not supporting more than 32-bit PCI bus addresses now, but
+ * must satisfy references to this function.  Change if needed.
+ */
+#define pci_dac_dma_supported(pci_dev, mask) (0)
+
+/* These macros should be used after a pci_map_sg call has been done
+ * to get bus addresses of each of the SG entries and their lengths.
+ * You should only work with the number of sg entries pci_map_sg
+ * returns, or alternatively stop on the first sg_dma_len(sg) which
+ * is 0.
+ */
+#define sg_dma_address(sg)     ((sg)->dma_address)
+#define sg_dma_len(sg)         ((sg)->length)
+
+/* Board-specific fixup routines. */
+extern void pcibios_fixup(void);
+extern void pcibios_fixup_irqs(void);
+
+#ifdef CONFIG_PCI_AUTO
+extern int pciauto_assign_resources(int busno, struct pci_channel *hose);
+#endif
+
+static inline void pcibios_add_platform_entries(struct pci_dev *dev)
+{
+}
+
+#endif /* __KERNEL__ */
+
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
+/* generic DMA-mapping stuff */
+#include <asm-generic/pci-dma-compat.h>
+
+#endif /* __ASM_SH64_PCI_H */
+
diff --git a/include/asm-sh64/percpu.h b/include/asm-sh64/percpu.h
new file mode 100644 (file)
index 0000000..a01d16c
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH64_PERCPU
+#define __ASM_SH64_PERCPU
+
+#include <asm-generic/percpu.h>
+
+#endif /* __ASM_SH64_PERCPU */
diff --git a/include/asm-sh64/posix_types.h b/include/asm-sh64/posix_types.h
new file mode 100644 (file)
index 0000000..0620317
--- /dev/null
@@ -0,0 +1,131 @@
+#ifndef __ASM_SH64_POSIX_TYPES_H
+#define __ASM_SH64_POSIX_TYPES_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/posix_types.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003  Paul Mundt
+ *
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned long  __kernel_ino_t;
+typedef unsigned short __kernel_mode_t;
+typedef unsigned short __kernel_nlink_t;
+typedef long           __kernel_off_t;
+typedef int            __kernel_pid_t;
+typedef unsigned short __kernel_ipc_pid_t;
+typedef unsigned short __kernel_uid_t;
+typedef unsigned short __kernel_gid_t;
+typedef long unsigned int      __kernel_size_t;
+typedef int            __kernel_ssize_t;
+typedef int            __kernel_ptrdiff_t;
+typedef long           __kernel_time_t;
+typedef long           __kernel_suseconds_t;
+typedef long           __kernel_clock_t;
+typedef int            __kernel_timer_t;
+typedef int            __kernel_clockid_t;
+typedef int            __kernel_daddr_t;
+typedef char *         __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int   __kernel_uid32_t;
+typedef unsigned int   __kernel_gid32_t;
+
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+typedef unsigned short __kernel_old_dev_t;
+
+#ifdef __GNUC__
+typedef long long      __kernel_loff_t;
+#endif
+
+typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
+       int     val[2];
+#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+       int     __val[2];
+#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+} __kernel_fsid_t;
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#undef __FD_SET
+static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
+{
+       unsigned long __tmp = __fd / __NFDBITS;
+       unsigned long __rem = __fd % __NFDBITS;
+       __fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
+}
+
+#undef __FD_CLR
+static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp)
+{
+       unsigned long __tmp = __fd / __NFDBITS;
+       unsigned long __rem = __fd % __NFDBITS;
+       __fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem);
+}
+
+
+#undef __FD_ISSET
+static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p)
+{
+       unsigned long __tmp = __fd / __NFDBITS;
+       unsigned long __rem = __fd % __NFDBITS;
+       return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0;
+}
+
+/*
+ * This will unroll the loop for the normal constant case (8 ints,
+ * for a 256-bit fd_set)
+ */
+#undef __FD_ZERO
+static __inline__ void __FD_ZERO(__kernel_fd_set *__p)
+{
+       unsigned long *__tmp = __p->fds_bits;
+       int __i;
+
+       if (__builtin_constant_p(__FDSET_LONGS)) {
+               switch (__FDSET_LONGS) {
+               case 16:
+                       __tmp[ 0] = 0; __tmp[ 1] = 0;
+                       __tmp[ 2] = 0; __tmp[ 3] = 0;
+                       __tmp[ 4] = 0; __tmp[ 5] = 0;
+                       __tmp[ 6] = 0; __tmp[ 7] = 0;
+                       __tmp[ 8] = 0; __tmp[ 9] = 0;
+                       __tmp[10] = 0; __tmp[11] = 0;
+                       __tmp[12] = 0; __tmp[13] = 0;
+                       __tmp[14] = 0; __tmp[15] = 0;
+                       return;
+
+               case 8:
+                       __tmp[ 0] = 0; __tmp[ 1] = 0;
+                       __tmp[ 2] = 0; __tmp[ 3] = 0;
+                       __tmp[ 4] = 0; __tmp[ 5] = 0;
+                       __tmp[ 6] = 0; __tmp[ 7] = 0;
+                       return;
+
+               case 4:
+                       __tmp[ 0] = 0; __tmp[ 1] = 0;
+                       __tmp[ 2] = 0; __tmp[ 3] = 0;
+                       return;
+               }
+       }
+       __i = __FDSET_LONGS;
+       while (__i) {
+               __i--;
+               *__tmp = 0;
+               __tmp++;
+       }
+}
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+
+#endif /* __ASM_SH64_POSIX_TYPES_H */
diff --git a/include/asm-sh64/registers.h b/include/asm-sh64/registers.h
new file mode 100644 (file)
index 0000000..7eec666
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef __ASM_SH64_REGISTERS_H
+#define __ASM_SH64_REGISTERS_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/registers.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2004  Richard Curnow
+ */
+
+#ifdef __ASSEMBLY__
+/* =====================================================================
+**
+** Section 1: acts on assembly sources pre-processed by GPP ( <source.S>).
+**           Assigns symbolic names to control & target registers.
+*/
+
+/*
+ * Define some useful aliases for control registers.
+ */
+#define SR     cr0
+#define SSR    cr1
+#define PSSR   cr2
+                       /* cr3 UNDEFINED */
+#define INTEVT cr4
+#define EXPEVT cr5
+#define PEXPEVT        cr6
+#define TRA    cr7
+#define SPC    cr8
+#define PSPC   cr9
+#define RESVEC cr10
+#define VBR    cr11
+                       /* cr12 UNDEFINED */
+#define TEA    cr13
+                       /* cr14-cr15 UNDEFINED */
+#define DCR    cr16
+#define KCR0   cr17
+#define KCR1   cr18
+                       /* cr19-cr31 UNDEFINED */
+                       /* cr32-cr61 RESERVED */
+#define CTC    cr62
+#define USR    cr63
+
+/*
+ * ABI dependent registers (general purpose set)
+ */
+#define RET    r2
+#define ARG1   r2
+#define ARG2   r3
+#define ARG3   r4
+#define ARG4   r5
+#define ARG5   r6
+#define ARG6   r7
+#define SP     r15
+#define LINK   r18
+#define ZERO   r63
+
+/*
+ * Status register defines: used only by assembly sources (and
+ *                         syntax independednt)
+ */
+#define SR_RESET_VAL   0x0000000050008000
+#define SR_HARMLESS    0x00000000500080f0      /* Write ignores for most */
+#define SR_ENABLE_FPU  0xffffffffffff7fff      /* AND with this */
+
+#if defined (CONFIG_SH64_SR_WATCH)
+#define SR_ENABLE_MMU  0x0000000084000000      /* OR with this */
+#else
+#define SR_ENABLE_MMU  0x0000000080000000      /* OR with this */
+#endif
+
+#define SR_UNBLOCK_EXC 0xffffffffefffffff      /* AND with this */
+#define SR_BLOCK_EXC   0x0000000010000000      /* OR with this */
+
+#else  /* Not __ASSEMBLY__ syntax */
+
+/*
+** Stringify reg. name
+*/
+#define __str(x)  #x
+
+/* Stringify control register names for use in inline assembly */
+#define __SR __str(SR)
+#define __SSR __str(SSR)
+#define __PSSR __str(PSSR)
+#define __INTEVT __str(INTEVT)
+#define __EXPEVT __str(EXPEVT)
+#define __PEXPEVT __str(PEXPEVT)
+#define __TRA __str(TRA)
+#define __SPC __str(SPC)
+#define __PSPC __str(PSPC)
+#define __RESVEC __str(RESVEC)
+#define __VBR __str(VBR)
+#define __TEA __str(TEA)
+#define __DCR __str(DCR)
+#define __KCR0 __str(KCR0)
+#define __KCR1 __str(KCR1)
+#define __CTC __str(CTC)
+#define __USR __str(USR)
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_SH64_REGISTERS_H */
diff --git a/include/asm-sh64/resource.h b/include/asm-sh64/resource.h
new file mode 100644 (file)
index 0000000..8ff9394
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH64_RESOURCE_H
+#define __ASM_SH64_RESOURCE_H
+
+#include <asm-sh/resource.h>
+
+#endif /* __ASM_SH64_RESOURCE_H */
diff --git a/include/asm-sh64/scatterlist.h b/include/asm-sh64/scatterlist.h
new file mode 100644 (file)
index 0000000..5d8fa32
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/scatterlist.h
+ *
+ * Copyright (C) 2003  Paul Mundt
+ *
+ */
+#ifndef __ASM_SH64_SCATTERLIST_H
+#define __ASM_SH64_SCATTERLIST_H
+
+struct scatterlist {
+    struct page * page; /* Location for highmem page, if any */
+    unsigned int offset;/* for highmem, page offset */
+    dma_addr_t dma_address;
+    unsigned int length;
+};
+
+#define ISA_DMA_THRESHOLD (0xffffffff)
+
+#endif /* !__ASM_SH64_SCATTERLIST_H */
diff --git a/include/asm-sh64/sections.h b/include/asm-sh64/sections.h
new file mode 100644 (file)
index 0000000..897f36b
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __ASM_SH64_SECTIONS_H
+#define __ASM_SH64_SECTIONS_H
+
+#include <asm-sh/sections.h>
+
+#endif /* __ASM_SH64_SECTIONS_H */
+
diff --git a/include/asm-sh64/segment.h b/include/asm-sh64/segment.h
new file mode 100644 (file)
index 0000000..92ac001
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_SEGMENT_H
+#define _ASM_SEGMENT_H
+
+/* Only here because we have some old header files that expect it.. */
+
+#endif /* _ASM_SEGMENT_H */
diff --git a/include/asm-sh64/semaphore-helper.h b/include/asm-sh64/semaphore-helper.h
new file mode 100644 (file)
index 0000000..fcfafe2
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef __ASM_SH64_SEMAPHORE_HELPER_H
+#define __ASM_SH64_SEMAPHORE_HELPER_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/semaphore-helper.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+#include <asm/errno.h>
+
+/*
+ * SMP- and interrupt-safe semaphores helper functions.
+ *
+ * (C) Copyright 1996 Linus Torvalds
+ * (C) Copyright 1999 Andrea Arcangeli
+ */
+
+/*
+ * These two _must_ execute atomically wrt each other.
+ *
+ * This is trivially done with load_locked/store_cond,
+ * which we have.  Let the rest of the losers suck eggs.
+ */
+static __inline__ void wake_one_more(struct semaphore * sem)
+{
+       atomic_inc((atomic_t *)&sem->sleepers);
+}
+
+static __inline__ int waking_non_zero(struct semaphore *sem)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(&semaphore_wake_lock, flags);
+       if (sem->sleepers > 0) {
+               sem->sleepers--;
+               ret = 1;
+       }
+       spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+       return ret;
+}
+
+/*
+ * waking_non_zero_interruptible:
+ *     1       got the lock
+ *     0       go to sleep
+ *     -EINTR  interrupted
+ *
+ * We must undo the sem->count down_interruptible() increment while we are
+ * protected by the spinlock in order to make atomic this atomic_inc() with the
+ * atomic_read() in wake_one_more(), otherwise we can race. -arca
+ */
+static __inline__ int waking_non_zero_interruptible(struct semaphore *sem,
+                                               struct task_struct *tsk)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(&semaphore_wake_lock, flags);
+       if (sem->sleepers > 0) {
+               sem->sleepers--;
+               ret = 1;
+       } else if (signal_pending(tsk)) {
+               atomic_inc(&sem->count);
+               ret = -EINTR;
+       }
+       spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+       return ret;
+}
+
+/*
+ * waking_non_zero_trylock:
+ *     1       failed to lock
+ *     0       got the lock
+ *
+ * We must undo the sem->count down_trylock() increment while we are
+ * protected by the spinlock in order to make atomic this atomic_inc() with the
+ * atomic_read() in wake_one_more(), otherwise we can race. -arca
+ */
+static __inline__ int waking_non_zero_trylock(struct semaphore *sem)
+{
+       unsigned long flags;
+       int ret = 1;
+
+       spin_lock_irqsave(&semaphore_wake_lock, flags);
+       if (sem->sleepers <= 0)
+               atomic_inc(&sem->count);
+       else {
+               sem->sleepers--;
+               ret = 0;
+       }
+       spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+       return ret;
+}
+
+#endif /* __ASM_SH64_SEMAPHORE_HELPER_H */
diff --git a/include/asm-sh64/semaphore.h b/include/asm-sh64/semaphore.h
new file mode 100644 (file)
index 0000000..3e97ead
--- /dev/null
@@ -0,0 +1,146 @@
+#ifndef __ASM_SH64_SEMAPHORE_H
+#define __ASM_SH64_SEMAPHORE_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/semaphore.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ * SMP- and interrupt-safe semaphores.
+ *
+ * (C) Copyright 1996 Linus Torvalds
+ *
+ * SuperH verison by Niibe Yutaka
+ *  (Currently no asm implementation but generic C code...)
+ *
+ */
+
+#include <linux/linkage.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/rwsem.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+
+struct semaphore {
+       atomic_t count;
+       int sleepers;
+       wait_queue_head_t wait;
+#ifdef WAITQUEUE_DEBUG
+       long __magic;
+#endif
+};
+
+#ifdef WAITQUEUE_DEBUG
+# define __SEM_DEBUG_INIT(name) \
+               , (int)&(name).__magic
+#else
+# define __SEM_DEBUG_INIT(name)
+#endif
+
+#define __SEMAPHORE_INITIALIZER(name,count) \
+{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+       __SEM_DEBUG_INIT(name) }
+
+#define __MUTEX_INITIALIZER(name) \
+       __SEMAPHORE_INITIALIZER(name,1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+       struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+static inline void sema_init (struct semaphore *sem, int val)
+{
+/*
+ *     *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+ *
+ * i'd rather use the more flexible initialization above, but sadly
+ * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
+ */
+       atomic_set(&sem->count, val);
+       sem->sleepers = 0;
+       init_waitqueue_head(&sem->wait);
+#ifdef WAITQUEUE_DEBUG
+       sem->__magic = (int)&sem->__magic;
+#endif
+}
+
+static inline void init_MUTEX (struct semaphore *sem)
+{
+       sema_init(sem, 1);
+}
+
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+{
+       sema_init(sem, 0);
+}
+
+#if 0
+asmlinkage void __down_failed(void /* special register calling convention */);
+asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
+asmlinkage int  __down_failed_trylock(void  /* params in registers */);
+asmlinkage void __up_wakeup(void /* special register calling convention */);
+#endif
+
+asmlinkage void __down(struct semaphore * sem);
+asmlinkage int  __down_interruptible(struct semaphore * sem);
+asmlinkage int  __down_trylock(struct semaphore * sem);
+asmlinkage void __up(struct semaphore * sem);
+
+extern spinlock_t semaphore_wake_lock;
+
+static inline void down(struct semaphore * sem)
+{
+#ifdef WAITQUEUE_DEBUG
+       CHECK_MAGIC(sem->__magic);
+#endif
+
+       if (atomic_dec_return(&sem->count) < 0)
+               __down(sem);
+}
+
+static inline int down_interruptible(struct semaphore * sem)
+{
+       int ret = 0;
+#ifdef WAITQUEUE_DEBUG
+       CHECK_MAGIC(sem->__magic);
+#endif
+
+       if (atomic_dec_return(&sem->count) < 0)
+               ret = __down_interruptible(sem);
+       return ret;
+}
+
+static inline int down_trylock(struct semaphore * sem)
+{
+       int ret = 0;
+#ifdef WAITQUEUE_DEBUG
+       CHECK_MAGIC(sem->__magic);
+#endif
+
+       if (atomic_dec_return(&sem->count) < 0)
+               ret = __down_trylock(sem);
+       return ret;
+}
+
+/*
+ * Note! This is subtle. We jump to wake people up only if
+ * the semaphore was negative (== somebody was waiting on it).
+ */
+static inline void up(struct semaphore * sem)
+{
+#ifdef WAITQUEUE_DEBUG
+       CHECK_MAGIC(sem->__magic);
+#endif
+       if (atomic_inc_return(&sem->count) <= 0)
+               __up(sem);
+}
+
+#endif /* __ASM_SH64_SEMAPHORE_H */
diff --git a/include/asm-sh64/sembuf.h b/include/asm-sh64/sembuf.h
new file mode 100644 (file)
index 0000000..ec4d9f1
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef __ASM_SH64_SEMBUF_H
+#define __ASM_SH64_SEMBUF_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/sembuf.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+
+/*
+ * The semid64_ds structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct semid64_ds {
+       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
+       __kernel_time_t sem_otime;              /* last semop time */
+       unsigned long   __unused1;
+       __kernel_time_t sem_ctime;              /* last change time */
+       unsigned long   __unused2;
+       unsigned long   sem_nsems;              /* no. of semaphores in array */
+       unsigned long   __unused3;
+       unsigned long   __unused4;
+};
+
+#endif /* __ASM_SH64_SEMBUF_H */
diff --git a/include/asm-sh64/shmbuf.h b/include/asm-sh64/shmbuf.h
new file mode 100644 (file)
index 0000000..022f349
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef __ASM_SH64_SHMBUF_H
+#define __ASM_SH64_SHMBUF_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/shmbuf.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+
+/*
+ * The shmid64_ds structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct shmid64_ds {
+       struct ipc64_perm       shm_perm;       /* operation perms */
+       size_t                  shm_segsz;      /* size of segment (bytes) */
+       __kernel_time_t         shm_atime;      /* last attach time */
+       unsigned long           __unused1;
+       __kernel_time_t         shm_dtime;      /* last detach time */
+       unsigned long           __unused2;
+       __kernel_time_t         shm_ctime;      /* last change time */
+       unsigned long           __unused3;
+       __kernel_pid_t          shm_cpid;       /* pid of creator */
+       __kernel_pid_t          shm_lpid;       /* pid of last operator */
+       unsigned long           shm_nattch;     /* no. of current attaches */
+       unsigned long           __unused4;
+       unsigned long           __unused5;
+};
+
+struct shminfo64 {
+       unsigned long   shmmax;
+       unsigned long   shmmin;
+       unsigned long   shmmni;
+       unsigned long   shmseg;
+       unsigned long   shmall;
+       unsigned long   __unused1;
+       unsigned long   __unused2;
+       unsigned long   __unused3;
+       unsigned long   __unused4;
+};
+
+#endif /* __ASM_SH64_SHMBUF_H */
diff --git a/include/asm-sh64/sigcontext.h b/include/asm-sh64/sigcontext.h
new file mode 100644 (file)
index 0000000..6293509
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef __ASM_SH64_SIGCONTEXT_H
+#define __ASM_SH64_SIGCONTEXT_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/sigcontext.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+
+struct sigcontext {
+       unsigned long   oldmask;
+
+       /* CPU registers */
+       unsigned long long sc_regs[63];
+       unsigned long long sc_tregs[8];
+       unsigned long long sc_pc;
+       unsigned long long sc_sr;
+
+       /* FPU registers */
+       unsigned long long sc_fpregs[32];
+       unsigned int sc_fpscr;
+       unsigned int sc_fpvalid;
+};
+
+#endif /* __ASM_SH64_SIGCONTEXT_H */
diff --git a/include/asm-sh64/siginfo.h b/include/asm-sh64/siginfo.h
new file mode 100644 (file)
index 0000000..56ef1da
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH64_SIGINFO_H
+#define __ASM_SH64_SIGINFO_H
+
+#include <asm-generic/siginfo.h>
+
+#endif /* __ASM_SH64_SIGINFO_H */
diff --git a/include/asm-sh64/smp.h b/include/asm-sh64/smp.h
new file mode 100644 (file)
index 0000000..4a4d0da
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __ASM_SH64_SMP_H
+#define __ASM_SH64_SMP_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/smp.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+
+#endif /* __ASM_SH64_SMP_H */
diff --git a/include/asm-sh64/socket.h b/include/asm-sh64/socket.h
new file mode 100644 (file)
index 0000000..1853f72
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH64_SOCKET_H
+#define __ASM_SH64_SOCKET_H
+
+#include <asm-sh/socket.h>
+
+#endif /* __ASM_SH64_SOCKET_H */
diff --git a/include/asm-sh64/sockios.h b/include/asm-sh64/sockios.h
new file mode 100644 (file)
index 0000000..1ae23ae
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __ASM_SH64_SOCKIOS_H
+#define __ASM_SH64_SOCKIOS_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/sockios.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+
+/* Socket-level I/O control calls. */
+#define FIOGETOWN      _IOR('f', 123, int)
+#define FIOSETOWN      _IOW('f', 124, int)
+
+#define SIOCATMARK     _IOR('s', 7, int)
+#define SIOCSPGRP      _IOW('s', 8, pid_t)
+#define SIOCGPGRP      _IOR('s', 9, pid_t)
+
+#define SIOCGSTAMP     _IOR('s', 100, struct timeval) /* Get stamp - linux-specific */
+#endif /* __ASM_SH64_SOCKIOS_H */
diff --git a/include/asm-sh64/spinlock.h b/include/asm-sh64/spinlock.h
new file mode 100644 (file)
index 0000000..296b0c9
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __ASM_SH64_SPINLOCK_H
+#define __ASM_SH64_SPINLOCK_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/spinlock.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+
+#error "No SMP on SH64"
+
+#endif /* __ASM_SH64_SPINLOCK_H */
diff --git a/include/asm-sh64/stat.h b/include/asm-sh64/stat.h
new file mode 100644 (file)
index 0000000..86f551b
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef __ASM_SH64_STAT_H
+#define __ASM_SH64_STAT_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/stat.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+
+struct __old_kernel_stat {
+       unsigned short st_dev;
+       unsigned short st_ino;
+       unsigned short st_mode;
+       unsigned short st_nlink;
+       unsigned short st_uid;
+       unsigned short st_gid;
+       unsigned short st_rdev;
+       unsigned long  st_size;
+       unsigned long  st_atime;
+       unsigned long  st_mtime;
+       unsigned long  st_ctime;
+};
+
+struct stat {
+       unsigned short st_dev;
+       unsigned short __pad1;
+       unsigned long st_ino;
+       unsigned short st_mode;
+       unsigned short st_nlink;
+       unsigned short st_uid;
+       unsigned short st_gid;
+       unsigned short st_rdev;
+       unsigned short __pad2;
+       unsigned long  st_size;
+       unsigned long  st_blksize;
+       unsigned long  st_blocks;
+       unsigned long  st_atime;
+       unsigned long  st_atime_nsec;
+       unsigned long  st_mtime;
+       unsigned long  st_mtime_nsec;
+       unsigned long  st_ctime;
+       unsigned long  st_ctime_nsec;
+       unsigned long  __unused4;
+       unsigned long  __unused5;
+};
+
+/* This matches struct stat64 in glibc2.1, hence the absolutely
+ * insane amounts of padding around dev_t's.
+ */
+struct stat64 {
+       unsigned short  st_dev;
+       unsigned char   __pad0[10];
+
+       unsigned long   st_ino;
+       unsigned int    st_mode;
+       unsigned int    st_nlink;
+
+       unsigned long   st_uid;
+       unsigned long   st_gid;
+
+       unsigned short  st_rdev;
+       unsigned char   __pad3[10];
+
+       long long       st_size;
+       unsigned long   st_blksize;
+
+       unsigned long   st_blocks;      /* Number 512-byte blocks allocated. */
+       unsigned long   __pad4;         /* future possible st_blocks high bits */
+
+       unsigned long   st_atime;
+       unsigned long   st_atime_nsec;
+
+       unsigned long   st_mtime;
+       unsigned long   st_mtime_nsec;
+
+       unsigned long   st_ctime;
+       unsigned long   st_ctime_nsec;  /* will be high 32 bits of ctime someday */
+
+       unsigned long   __unused1;
+       unsigned long   __unused2;
+};
+
+#endif /* __ASM_SH64_STAT_H */
diff --git a/include/asm-sh64/statfs.h b/include/asm-sh64/statfs.h
new file mode 100644 (file)
index 0000000..083fd79
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH64_STATFS_H
+#define __ASM_SH64_STATFS_H
+
+#include <asm-generic/statfs.h>
+
+#endif /* __ASM_SH64_STATFS_H */
diff --git a/include/asm-sh64/string.h b/include/asm-sh64/string.h
new file mode 100644 (file)
index 0000000..8a73573
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __ASM_SH64_STRING_H
+#define __ASM_SH64_STRING_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/string.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ * Empty on purpose. ARCH SH64 ASM libs are out of the current project scope.
+ *
+ */
+
+#define __HAVE_ARCH_MEMCPY
+
+extern void *memcpy(void *dest, const void *src, size_t count);
+
+#endif
diff --git a/include/asm-sh64/termbits.h b/include/asm-sh64/termbits.h
new file mode 100644 (file)
index 0000000..86bde5e
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH64_TERMBITS_H
+#define __ASM_SH64_TERMBITS_H
+
+#include <asm-sh/termbits.h>
+
+#endif /* __ASM_SH64_TERMBITS_H */
diff --git a/include/asm-sh64/termios.h b/include/asm-sh64/termios.h
new file mode 100644 (file)
index 0000000..4a9c7fb
--- /dev/null
@@ -0,0 +1,117 @@
+#ifndef __ASM_SH64_TERMIOS_H
+#define __ASM_SH64_TERMIOS_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/termios.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+       unsigned short ws_row;
+       unsigned short ws_col;
+       unsigned short ws_xpixel;
+       unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+       unsigned short c_iflag;         /* input mode flags */
+       unsigned short c_oflag;         /* output mode flags */
+       unsigned short c_cflag;         /* control mode flags */
+       unsigned short c_lflag;         /* local mode flags */
+       unsigned char c_line;           /* line discipline */
+       unsigned char c_cc[NCC];        /* control characters */
+};
+
+/* modem lines */
+#define TIOCM_LE       0x001
+#define TIOCM_DTR      0x002
+#define TIOCM_RTS      0x004
+#define TIOCM_ST       0x008
+#define TIOCM_SR       0x010
+#define TIOCM_CTS      0x020
+#define TIOCM_CAR      0x040
+#define TIOCM_RNG      0x080
+#define TIOCM_DSR      0x100
+#define TIOCM_CD       TIOCM_CAR
+#define TIOCM_RI       TIOCM_RNG
+#define TIOCM_OUT1     0x2000
+#define TIOCM_OUT2     0x4000
+#define TIOCM_LOOP     0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+/* line disciplines */
+#define N_TTY          0
+#define N_SLIP         1
+#define N_MOUSE                2
+#define N_PPP          3
+#define N_STRIP                4
+#define N_AX25         5
+#define N_X25          6       /* X.25 async */
+#define N_6PACK                7
+#define N_MASC         8       /* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964                9       /* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL 10      /* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA         11      /* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_SMSBLOCK     12      /* SMS block mode - for talking to GSM data cards about SMS messages */
+#define N_HDLC         13      /* synchronous HDLC */
+#define N_SYNC_PPP     14
+#define N_HCI          15      /* Bluetooth HCI UART */
+
+#ifdef __KERNEL__
+
+/*     intr=^C         quit=^\         erase=del       kill=^U
+       eof=^D          vtime=\0        vmin=\1         sxtc=\0
+       start=^Q        stop=^S         susp=^Z         eol=\0
+       reprint=^R      discard=^U      werase=^W       lnext=^V
+       eol2=\0
+*/
+#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
+       unsigned short __tmp; \
+       get_user(__tmp,&(termio)->x); \
+       *(unsigned short *) &(termios)->x = __tmp; \
+}
+
+#define user_termio_to_kernel_termios(termios, termio) \
+({ \
+       SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
+       SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
+       SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
+       SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
+       copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
+})
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ */
+#define kernel_termios_to_user_termio(termio, termios) \
+({ \
+       put_user((termios)->c_iflag, &(termio)->c_iflag); \
+       put_user((termios)->c_oflag, &(termio)->c_oflag); \
+       put_user((termios)->c_cflag, &(termio)->c_cflag); \
+       put_user((termios)->c_lflag, &(termio)->c_lflag); \
+       put_user((termios)->c_line,  &(termio)->c_line); \
+       copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
+})
+
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_SH64_TERMIOS_H */
diff --git a/include/asm-sh64/thread_info.h b/include/asm-sh64/thread_info.h
new file mode 100644 (file)
index 0000000..f9d2a22
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef __ASM_SH64_THREAD_INFO_H
+#define __ASM_SH64_THREAD_INFO_H
+
+/*
+ * SuperH 5 version
+ * Copyright (C) 2003  Paul Mundt
+ */
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+#include <asm/registers.h>
+
+/*
+ * low level task data that entry.S needs immediate access to
+ * - this struct should fit entirely inside of one cache line
+ * - this struct shares the supervisor stack pages
+ * - if the contents of this structure are changed, the assembly constants must also be changed
+ */
+struct thread_info {
+       struct task_struct      *task;          /* main task structure */
+       struct exec_domain      *exec_domain;   /* execution domain */
+       unsigned long           flags;          /* low level flags */
+       /* Put the 4 32-bit fields together to make asm offsetting easier. */
+       __s32                   preempt_count; /* 0 => preemptable, <0 => BUG */
+       __u16                   cpu;
+
+       mm_segment_t            addr_limit;
+       struct restart_block    restart_block;
+
+       __u8                    supervisor_stack[0];
+};
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ */
+#define INIT_THREAD_INFO(tsk)                  \
+{                                              \
+       .task           = &tsk,                 \
+       .exec_domain    = &default_exec_domain, \
+       .flags          = 0,                    \
+       .cpu            = 0,                    \
+       .preempt_count  = 1,                    \
+       .addr_limit     = KERNEL_DS,            \
+       .restart_block  = {                     \
+               .fn = do_no_restart_syscall,    \
+       },                                      \
+}
+
+#define init_thread_info       (init_thread_union.thread_info)
+#define init_stack             (init_thread_union.stack)
+
+/* how to get the thread information struct from C */
+static inline struct thread_info *current_thread_info(void)
+{
+       struct thread_info *ti;
+
+       __asm__ __volatile__ ("getcon " __KCR0 ", %0\n\t" : "=r" (ti));
+
+       return ti;
+}
+
+/* thread information allocation */
+#define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,2))
+#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
+#define get_thread_info(ti) get_task_struct((ti)->task)
+#define put_thread_info(ti) put_task_struct((ti)->task)
+
+#endif /* __ASSEMBLY__ */
+
+#define PREEMPT_ACTIVE         0x4000000
+
+/* thread information flags */
+#define TIF_SYSCALL_TRACE      0       /* syscall trace active */
+#define TIF_SIGPENDING         2       /* signal pending */
+#define TIF_NEED_RESCHED       3       /* rescheduling necessary */
+
+#define THREAD_SIZE    16384
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_SH64_THREAD_INFO_H */
diff --git a/include/asm-sh64/tlb.h b/include/asm-sh64/tlb.h
new file mode 100644 (file)
index 0000000..4979408
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * include/asm-sh64/tlb.h
+ *
+ * Copyright (C) 2003  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+#ifndef __ASM_SH64_TLB_H
+#define __ASM_SH64_TLB_H
+
+/*
+ * Note! These are mostly unused, we just need the xTLB_LAST_VAR_UNRESTRICTED
+ * for head.S! Once this limitation is gone, we can clean the rest of this up.
+ */
+
+/* ITLB defines */
+#define ITLB_FIXED     0x00000000      /* First fixed ITLB, see head.S */
+#define ITLB_LAST_VAR_UNRESTRICTED     0x000003F0      /* Last ITLB */
+
+/* DTLB defines */
+#define DTLB_FIXED     0x00800000      /* First fixed DTLB, see head.S */
+#define DTLB_LAST_VAR_UNRESTRICTED     0x008003F0      /* Last DTLB */
+
+#ifndef __ASSEMBLY__
+
+/**
+ * for_each_dtlb_entry
+ *
+ * @tlb:       TLB entry
+ *
+ * Iterate over free (non-wired) DTLB entries
+ */
+#define for_each_dtlb_entry(tlb)               \
+       for (tlb  = cpu_data->dtlb.first;       \
+            tlb <= cpu_data->dtlb.last;        \
+            tlb += cpu_data->dtlb.step)
+
+/**
+ * for_each_itlb_entry
+ *
+ * @tlb:       TLB entry
+ *
+ * Iterate over free (non-wired) ITLB entries
+ */
+#define for_each_itlb_entry(tlb)               \
+       for (tlb  = cpu_data->itlb.first;       \
+            tlb <= cpu_data->itlb.last;        \
+            tlb += cpu_data->itlb.step)
+
+/**
+ * __flush_tlb_slot
+ *
+ * @slot:      Address of TLB slot.
+ *
+ * Flushes TLB slot @slot.
+ */
+static inline void __flush_tlb_slot(unsigned long long slot)
+{
+       __asm__ __volatile__ ("putcfg %0, 0, r63\n" : : "r" (slot));
+}
+
+/* arch/sh64/mm/tlb.c */
+extern int sh64_tlb_init(void);
+extern unsigned long long sh64_next_free_dtlb_entry(void);
+extern unsigned long long sh64_get_wired_dtlb_entry(void);
+extern int sh64_put_wired_dtlb_entry(unsigned long long entry);
+
+extern void sh64_setup_tlb_slot(unsigned long long config_addr, unsigned long eaddr, unsigned long asid, unsigned long paddr);
+extern void sh64_teardown_tlb_slot(unsigned long long config_addr);
+
+#define tlb_start_vma(tlb, vma) \
+       flush_cache_range(vma, vma->vm_start, vma->vm_end)
+
+#define tlb_end_vma(tlb, vma)  \
+       flush_tlb_range(vma, vma->vm_start, vma->vm_end)
+
+#define __tlb_remove_tlb_entry(tlb, pte, address)      do { } while (0)
+
+/*
+ * Flush whole TLBs for MM
+ */
+#define tlb_flush(tlb)         flush_tlb_mm((tlb)->mm)
+
+#include <asm-generic/tlb.h>
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_SH64_TLB_H */
+
diff --git a/include/asm-sh64/tlbflush.h b/include/asm-sh64/tlbflush.h
new file mode 100644 (file)
index 0000000..15c0719
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef __ASM_SH64_TLBFLUSH_H
+#define __ASM_SH64_TLBFLUSH_H
+
+#include <asm/pgalloc.h>
+
+/*
+ * TLB flushing:
+ *
+ *  - flush_tlb() flushes the current mm struct TLBs
+ *  - flush_tlb_all() flushes all processes TLBs
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - flush_tlb_range(mm, start, end) flushes a range of pages
+ *
+ */
+
+extern void flush_tlb(void);
+extern void flush_tlb_all(void);
+extern void flush_tlb_mm(struct mm_struct *mm);
+extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+                           unsigned long end);
+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
+extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+                                     unsigned long start, unsigned long end)
+{
+}
+
+extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+
+#endif /* __ASM_SH64_TLBFLUSH_H */
+
diff --git a/include/asm-sh64/topology.h b/include/asm-sh64/topology.h
new file mode 100644 (file)
index 0000000..3421178
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH64_TOPOLOGY_H
+#define __ASM_SH64_TOPOLOGY_H
+
+#include <asm-generic/topology.h>
+
+#endif /* __ASM_SH64_TOPOLOGY_H */
diff --git a/include/asm-sh64/types.h b/include/asm-sh64/types.h
new file mode 100644 (file)
index 0000000..41d4d2f
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef __ASM_SH64_TYPES_H
+#define __ASM_SH64_TYPES_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/types.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+typedef __signed__ char s8;
+typedef unsigned char u8;
+
+typedef __signed__ short s16;
+typedef unsigned short u16;
+
+typedef __signed__ int s32;
+typedef unsigned int u32;
+
+typedef __signed__ long long s64;
+typedef unsigned long long u64;
+
+/* DMA addresses come in generic and 64-bit flavours.  */
+
+#ifdef CONFIG_HIGHMEM64G
+typedef u64 dma_addr_t;
+#else
+typedef u32 dma_addr_t;
+#endif
+typedef u64 dma64_addr_t;
+
+typedef unsigned int kmem_bufctl_t;
+
+#endif /* __ASSEMBLY__ */
+
+#define BITS_PER_LONG 32
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_SH64_TYPES_H */
diff --git a/include/asm-sh64/uaccess.h b/include/asm-sh64/uaccess.h
new file mode 100644 (file)
index 0000000..588065c
--- /dev/null
@@ -0,0 +1,320 @@
+#ifndef __ASM_SH64_UACCESS_H
+#define __ASM_SH64_UACCESS_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/uaccess.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003, 2004  Paul Mundt
+ *
+ * User space memory access functions
+ *
+ * Copyright (C) 1999  Niibe Yutaka
+ *
+ *  Based on:
+ *     MIPS implementation version 1.15 by
+ *              Copyright (C) 1996, 1997, 1998 by Ralf Baechle
+ *     and i386 version.
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+
+#define VERIFY_READ    0
+#define VERIFY_WRITE   1
+
+/*
+ * The fs value determines whether argument validity checking should be
+ * performed or not.  If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons (Data Segment Register?), these macros are misnamed.
+ */
+
+#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
+
+#define KERNEL_DS      MAKE_MM_SEG(0xFFFFFFFF)
+#define USER_DS                MAKE_MM_SEG(0x80000000)
+
+#define get_ds()       (KERNEL_DS)
+#define get_fs()        (current_thread_info()->addr_limit)
+#define set_fs(x)       (current_thread_info()->addr_limit=(x))
+
+#define segment_eq(a,b)        ((a).seg == (b).seg)
+
+#define __addr_ok(addr) ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg))
+
+/*
+ * Uhhuh, this needs 33-bit arithmetic. We have a carry..
+ *
+ * sum := addr + size;  carry? --> flag = true;
+ * if (sum >= addr_limit) flag = true;
+ */
+#define __range_ok(addr,size) (((unsigned long) (addr) + (size) < (current_thread_info()->addr_limit.seg)) ? 0 : 1)
+
+#define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
+#define __access_ok(addr,size) (__range_ok(addr,size) == 0)
+
+extern inline int verify_area(int type, const void __user * addr, unsigned long size)
+{
+       return access_ok(type,addr,size) ? 0 : -EFAULT;
+}
+
+/*
+ * Uh, these should become the main single-value transfer routines ...
+ * They automatically use the right size if we just have the right
+ * pointer type ...
+ *
+ * As MIPS uses the same address space for kernel and user data, we
+ * can just do these as direct assignments.
+ *
+ * Careful to not
+ * (a) re-use the arguments for side effects (sizeof is ok)
+ * (b) require any knowledge of processes at this stage
+ */
+#define put_user(x,ptr)        __put_user_check((x),(ptr),sizeof(*(ptr)))
+#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)))
+
+/*
+ * The "__xxx" versions do not do address space checking, useful when
+ * doing multiple accesses to the same area (the user has to do the
+ * checks by hand with "access_ok()")
+ */
+#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
+#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+
+/*
+ * The "xxx_ret" versions return constant specified in third argument, if
+ * something bad happens. These macros can be optimized for the
+ * case of just returning from the function xxx_ret is used.
+ */
+
+#define put_user_ret(x,ptr,ret) ({ \
+if (put_user(x,ptr)) return ret; })
+
+#define get_user_ret(x,ptr,ret) ({ \
+if (get_user(x,ptr)) return ret; })
+
+#define __put_user_ret(x,ptr,ret) ({ \
+if (__put_user(x,ptr)) return ret; })
+
+#define __get_user_ret(x,ptr,ret) ({ \
+if (__get_user(x,ptr)) return ret; })
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) (*(struct __large_struct *)(x))
+
+#define __get_user_size(x,ptr,size,retval)                     \
+do {                                                           \
+       retval = 0;                                             \
+       switch (size) {                                         \
+       case 1:                                                 \
+               retval = __get_user_asm_b(x, ptr);              \
+               break;                                          \
+       case 2:                                                 \
+               retval = __get_user_asm_w(x, ptr);              \
+               break;                                          \
+       case 4:                                                 \
+               retval = __get_user_asm_l(x, ptr);              \
+               break;                                          \
+       case 8:                                                 \
+               retval = __get_user_asm_q(x, ptr);              \
+               break;                                          \
+       default:                                                \
+               __get_user_unknown();                           \
+               break;                                          \
+       }                                                       \
+} while (0)
+
+#define __get_user_nocheck(x,ptr,size)                         \
+({                                                             \
+       long __gu_addr = (long)(ptr);                           \
+       long __gu_err;                                          \
+       __typeof(*(ptr)) __gu_val;                              \
+       __asm__ ("":"=r" (__gu_val));                           \
+       __asm__ ("":"=r" (__gu_err));                           \
+       __get_user_size((void *)&__gu_val, __gu_addr, (size), __gu_err); \
+       (x) = (__typeof__(*(ptr))) __gu_val;                    \
+       __gu_err;                                               \
+})
+
+#define __get_user_check(x,ptr,size)                           \
+({                                                             \
+       long __gu_addr = (long)(ptr);                           \
+       long __gu_err = -EFAULT;                                \
+       __typeof(*(ptr)) __gu_val;                              \
+       __asm__ ("":"=r" (__gu_val));                           \
+       __asm__ ("":"=r" (__gu_err));                           \
+       if (__access_ok(__gu_addr, (size)))                     \
+               __get_user_size((void *)&__gu_val, __gu_addr, (size), __gu_err); \
+       (x) = (__typeof__(*(ptr))) __gu_val;                    \
+       __gu_err;                                               \
+})
+
+extern long __get_user_asm_b(void *, long);
+extern long __get_user_asm_w(void *, long);
+extern long __get_user_asm_l(void *, long);
+extern long __get_user_asm_q(void *, long);
+extern void __get_user_unknown(void);
+
+#define __put_user_size(x,ptr,size,retval)                     \
+do {                                                           \
+       retval = 0;                                             \
+       switch (size) {                                         \
+       case 1:                                                 \
+               retval = __put_user_asm_b(x, ptr);              \
+               break;                                          \
+       case 2:                                                 \
+               retval = __put_user_asm_w(x, ptr);              \
+               break;                                          \
+       case 4:                                                 \
+               retval = __put_user_asm_l(x, ptr);              \
+               break;                                          \
+       case 8:                                                 \
+               retval = __put_user_asm_q(x, ptr);              \
+               break;                                          \
+       default:                                                \
+               __put_user_unknown();                           \
+       }                                                       \
+} while (0)
+
+#define __put_user_nocheck(x,ptr,size)                         \
+({                                                             \
+       long __pu_err;                                          \
+       __typeof__(*(ptr)) __pu_val = (x);                      \
+       __put_user_size((void *)&__pu_val, (long)(ptr), (size), __pu_err); \
+       __pu_err;                                               \
+})
+
+#define __put_user_check(x,ptr,size)                           \
+({                                                             \
+       long __pu_err = -EFAULT;                                \
+       long __pu_addr = (long)(ptr);                           \
+       __typeof__(*(ptr)) __pu_val = (x);                      \
+                                                               \
+       if (__access_ok(__pu_addr, (size)))                     \
+               __put_user_size((void *)&__pu_val, __pu_addr, (size), __pu_err);\
+       __pu_err;                                               \
+})
+
+extern long __put_user_asm_b(void *, long);
+extern long __put_user_asm_w(void *, long);
+extern long __put_user_asm_l(void *, long);
+extern long __put_user_asm_q(void *, long);
+extern void __put_user_unknown(void);
+
+\f
+/* Generic arbitrary sized copy.  */
+/* Return the number of bytes NOT copied */
+/* XXX: should be such that: 4byte and the rest. */
+extern __kernel_size_t __copy_user(void *__to, const void *__from, __kernel_size_t __n);
+
+#define copy_to_user(to,from,n) ({ \
+void *__copy_to = (void *) (to); \
+__kernel_size_t __copy_size = (__kernel_size_t) (n); \
+__kernel_size_t __copy_res; \
+if(__copy_size && __access_ok((unsigned long)__copy_to, __copy_size)) { \
+__copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); \
+} else __copy_res = __copy_size; \
+__copy_res; })
+
+#define copy_to_user_ret(to,from,n,retval) ({ \
+if (copy_to_user(to,from,n)) \
+       return retval; \
+})
+
+#define __copy_to_user(to,from,n)              \
+       __copy_user((void *)(to),               \
+                   (void *)(from), n)
+
+#define __copy_to_user_ret(to,from,n,retval) ({ \
+if (__copy_to_user(to,from,n)) \
+       return retval; \
+})
+
+#define copy_from_user(to,from,n) ({ \
+void *__copy_to = (void *) (to); \
+void *__copy_from = (void *) (from); \
+__kernel_size_t __copy_size = (__kernel_size_t) (n); \
+__kernel_size_t __copy_res; \
+if(__copy_size && __access_ok((unsigned long)__copy_from, __copy_size)) { \
+__copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \
+} else __copy_res = __copy_size; \
+__copy_res; })
+
+#define copy_from_user_ret(to,from,n,retval) ({ \
+if (copy_from_user(to,from,n)) \
+       return retval; \
+})
+
+#define __copy_from_user(to,from,n)            \
+       __copy_user((void *)(to),               \
+                   (void *)(from), n)
+
+#define __copy_from_user_ret(to,from,n,retval) ({ \
+if (__copy_from_user(to,from,n)) \
+       return retval; \
+})
+
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
+/* XXX: Not sure it works well..
+   should be such that: 4byte clear and the rest. */
+extern __kernel_size_t __clear_user(void *addr, __kernel_size_t size);
+
+#define clear_user(addr,n) ({ \
+void * __cl_addr = (addr); \
+unsigned long __cl_size = (n); \
+if (__cl_size && __access_ok(((unsigned long)(__cl_addr)), __cl_size)) \
+__cl_size = __clear_user(__cl_addr, __cl_size); \
+__cl_size; })
+
+extern int __strncpy_from_user(unsigned long __dest, unsigned long __src, int __count);
+
+#define strncpy_from_user(dest,src,count) ({ \
+unsigned long __sfu_src = (unsigned long) (src); \
+int __sfu_count = (int) (count); \
+long __sfu_res = -EFAULT; \
+if(__access_ok(__sfu_src, __sfu_count)) { \
+__sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); \
+} __sfu_res; })
+
+#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
+
+/*
+ * Return the size of a string (including the ending 0!)
+ */
+extern long __strnlen_user(const char *__s, long __n);
+
+extern __inline__ long strnlen_user(const char *s, long n)
+{
+       if (!__addr_ok(s))
+               return 0;
+       else
+               return __strnlen_user(s, n);
+}
+
+struct exception_table_entry
+{
+       unsigned long insn, fixup;
+};
+
+#define ARCH_HAS_SEARCH_EXTABLE
+
+/* If gcc inlines memset, it will use st.q instructions.  Therefore, we need
+   kmalloc allocations to be 8-byte aligned.  Without this, the alignment
+   becomes BYTE_PER_WORD i.e. only 4 (since sizeof(long)==sizeof(void*)==4 on
+   sh64 at the moment). */
+#define ARCH_KMALLOC_MINALIGN 8
+
+/* Returns 0 if exception not found and fixup.unit otherwise.  */
+extern unsigned long search_exception_table(unsigned long addr);
+extern const struct exception_table_entry *search_exception_tables (unsigned long addr);
+
+#endif /* __ASM_SH64_UACCESS_H */
diff --git a/include/asm-sh64/ucontext.h b/include/asm-sh64/ucontext.h
new file mode 100644 (file)
index 0000000..cf77a08
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef __ASM_SH64_UCONTEXT_H
+#define __ASM_SH64_UCONTEXT_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/ucontext.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+
+struct ucontext {
+       unsigned long     uc_flags;
+       struct ucontext  *uc_link;
+       stack_t           uc_stack;
+       struct sigcontext uc_mcontext;
+       sigset_t          uc_sigmask;   /* mask last for extensibility */
+};
+
+#endif /* __ASM_SH64_UCONTEXT_H */
diff --git a/include/asm-sh64/unaligned.h b/include/asm-sh64/unaligned.h
new file mode 100644 (file)
index 0000000..ad22487
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __ASM_SH64_UNALIGNED_H
+#define __ASM_SH64_UNALIGNED_H
+
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * include/asm-sh64/unaligned.h
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ *
+ */
+
+#include <linux/string.h>
+
+
+/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
+
+#define get_unaligned(ptr) \
+  ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
+
+#define put_unaligned(val, ptr)                                \
+  ({ __typeof__(*(ptr)) __tmp = (val);                 \
+     memmove((ptr), &__tmp, sizeof(*(ptr)));           \
+     (void)0; })
+
+#endif /* __ASM_SH64_UNALIGNED_H */
diff --git a/include/asm-sparc64/cmt.h b/include/asm-sparc64/cmt.h
new file mode 100644 (file)
index 0000000..870db59
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef _SPARC64_CMT_H
+#define _SPARC64_CMT_H
+
+/* cmt.h: Chip Multi-Threading register definitions
+ *
+ * Copyright (C) 2004 David S. Miller (davem@redhat.com)
+ */
+
+/* ASI_CORE_ID - private */
+#define LP_ID          0x0000000000000010UL
+#define  LP_ID_MAX     0x00000000003f0000UL
+#define  LP_ID_ID      0x000000000000003fUL
+
+/* ASI_INTR_ID - private */
+#define LP_INTR_ID     0x0000000000000000UL
+#define  LP_INTR_ID_ID 0x00000000000003ffUL
+
+/* ASI_CESR_ID - private */
+#define CESR_ID                0x0000000000000040UL
+#define  CESR_ID_ID    0x00000000000000ffUL
+
+/* ASI_CORE_AVAILABLE - shared */
+#define LP_AVAIL       0x0000000000000000UL
+#define  LP_AVAIL_1    0x0000000000000002UL
+#define  LP_AVAIL_0    0x0000000000000001UL
+
+/* ASI_CORE_ENABLE_STATUS - shared */
+#define LP_ENAB_STAT   0x0000000000000010UL
+#define  LP_ENAB_STAT_1        0x0000000000000002UL
+#define  LP_ENAB_STAT_0        0x0000000000000001UL
+
+/* ASI_CORE_ENABLE - shared */
+#define LP_ENAB                0x0000000000000020UL
+#define  LP_ENAB_1     0x0000000000000002UL
+#define  LP_ENAB_0     0x0000000000000001UL
+
+/* ASI_CORE_RUNNING - shared */
+#define LP_RUNNING_RW  0x0000000000000050UL
+#define LP_RUNNING_W1S 0x0000000000000060UL
+#define LP_RUNNING_W1C 0x0000000000000068UL
+#define  LP_RUNNING_1  0x0000000000000002UL
+#define  LP_RUNNING_0  0x0000000000000001UL
+
+/* ASI_CORE_RUNNING_STAT - shared */
+#define LP_RUN_STAT    0x0000000000000058UL
+#define  LP_RUN_STAT_1 0x0000000000000002UL
+#define  LP_RUN_STAT_0 0x0000000000000001UL
+
+/* ASI_XIR_STEERING - shared */
+#define LP_XIR_STEER   0x0000000000000030UL
+#define  LP_XIR_STEER_1        0x0000000000000002UL
+#define  LP_XIR_STEER_0        0x0000000000000001UL
+
+/* ASI_CMT_ERROR_STEERING - shared */
+#define CMT_ER_STEER   0x0000000000000040UL
+#define  CMT_ER_STEER_1        0x0000000000000002UL
+#define  CMT_ER_STEER_0        0x0000000000000001UL
+
+#endif /* _SPARC64_CMT_H */
diff --git a/include/asm-um/setup.h b/include/asm-um/setup.h
new file mode 100644 (file)
index 0000000..e5787bb
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef SETUP_H_INCLUDED
+#define SETUP_H_INCLUDED
+
+#define COMMAND_LINE_SIZE 512
+
+#endif         /* SETUP_H_INCLUDED */
diff --git a/include/asm-v850/setup.h b/include/asm-v850/setup.h
new file mode 100644 (file)
index 0000000..c48a9b9
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _V850_SETUP_H
+#define _V850_SETUP_H
+
+#define COMMAND_LINE_SIZE      512
+
+#endif /* __SETUP_H */
diff --git a/include/asm-x86_64/netdump.h b/include/asm-x86_64/netdump.h
new file mode 100644 (file)
index 0000000..3be9bad
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_64_NETDUMP_H_
+#define _ASM_X86_64_NETDUMP_H_
+
+#include <asm-generic/netdump.h>
+
+#endif /* _ASM_X86_64_NETDUMP_H_ */
diff --git a/include/linux/crc-ccitt.h b/include/linux/crc-ccitt.h
new file mode 100644 (file)
index 0000000..f52696a
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _LINUX_CRC_CCITT_H
+#define _LINUX_CRC_CCITT_H
+
+#include <linux/types.h>
+
+extern u16 const crc_ccitt_table[256];
+
+extern u16 crc_ccitt(u16 crc, const u8 *buffer, size_t len);
+
+static inline u16 crc_ccitt_byte(u16 crc, const u8 c)
+{
+       return (crc >> 8) ^ crc_ccitt_table[(crc ^ c) & 0xff];
+}
+
+#endif /* _LINUX_CRC_CCITT_H */
diff --git a/include/linux/crypto/ksign.h b/include/linux/crypto/ksign.h
new file mode 100644 (file)
index 0000000..5569cd3
--- /dev/null
@@ -0,0 +1,22 @@
+/* ksign.h: in-kernel signature checker
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_CRYPTO_KSIGN_H
+#define _LINUX_CRYPTO_KSIGN_H
+
+#include <linux/types.h>
+
+#ifdef CONFIG_CRYPTO_SIGNATURE
+extern int ksign_verify_signature(const char *sig, unsigned sig_size,
+                                 struct crypto_tfm *sha1);
+#endif
+
+#endif /* _LINUX_CRYPTO_KSIGN_H */
diff --git a/include/linux/crypto/mpi.h b/include/linux/crypto/mpi.h
new file mode 100644 (file)
index 0000000..4de3ba0
--- /dev/null
@@ -0,0 +1,147 @@
+/* mpi.h  -  Multi Precision Integers
+ *     Copyright (C) 1994, 1996, 1998, 1999,
+ *                    2000, 2001 Free Software Foundation, Inc.
+ *
+ * This file is part of GNUPG.
+ *
+ * GNUPG 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.
+ *
+ * GNUPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * Note: This code is heavily based on the GNU MP Library.
+ *      Actually it's the same code with only minor changes in the
+ *      way the data is stored; this is to support the abstraction
+ *      of an optional secure memory allocation which may be used
+ *      to avoid revealing of sensitive data due to paging etc.
+ *      The GNU MP Library itself is published under the LGPL;
+ *      however I decided to publish this code under the plain GPL.
+ */
+
+#ifndef G10_MPI_H
+#define G10_MPI_H
+
+#include <linux/types.h>
+
+/* DSI defines */
+
+#define SHA1_DIGEST_LENGTH   20
+
+/*end of DSI defines */
+
+#define BYTES_PER_MPI_LIMB     (BITS_PER_LONG / 8)
+#define BITS_PER_MPI_LIMB      BITS_PER_LONG
+
+typedef unsigned long int mpi_limb_t;
+typedef   signed long int mpi_limb_signed_t;
+
+struct gcry_mpi {
+       int     alloced;    /* array size (# of allocated limbs) */
+       int     nlimbs;     /* number of valid limbs */
+       int     nbits;      /* the real number of valid bits (info only) */
+       int     sign;       /* indicates a negative number */
+       unsigned flags; /* bit 0: array must be allocated in secure memory space */
+       /* bit 1: not used */
+       /* bit 2: the limb is a pointer to some m_alloced data */
+       mpi_limb_t *d;  /* array with the limbs */
+};
+
+typedef struct gcry_mpi *MPI;
+
+#define MPI_NULL NULL
+
+#define mpi_get_nlimbs(a)     ((a)->nlimbs)
+#define mpi_is_neg(a)        ((a)->sign)
+
+/*-- mpiutil.c --*/
+MPI mpi_alloc( unsigned nlimbs );
+MPI mpi_alloc_secure( unsigned nlimbs );
+MPI mpi_alloc_like( MPI a );
+void mpi_free( MPI a );
+int mpi_resize( MPI a, unsigned nlimbs );
+int  mpi_copy( MPI *copy, const MPI a );
+void mpi_clear( MPI a );
+int mpi_set( MPI w, MPI u);
+int mpi_set_ui( MPI w, ulong u);
+MPI  mpi_alloc_set_ui( unsigned long u);
+void mpi_m_check( MPI a );
+void mpi_swap( MPI a, MPI b);
+
+/*-- mpicoder.c --*/
+MPI do_encode_md(const void *sha_buffer, unsigned nbits);
+MPI mpi_read_from_buffer(const void *buffer, unsigned *ret_nread);
+int mpi_fromstr(MPI val, const char *str);
+u32 mpi_get_keyid( MPI a, u32 *keyid );
+void *mpi_get_buffer( MPI a, unsigned *nbytes, int *sign );
+void *mpi_get_secure_buffer( MPI a, unsigned *nbytes, int *sign );
+int  mpi_set_buffer( MPI a, const void *buffer, unsigned nbytes, int sign );
+
+#define log_mpidump g10_log_mpidump
+
+/*-- mpi-add.c --*/
+int mpi_add_ui(MPI w, MPI u, ulong v );
+int mpi_add(MPI w, MPI u, MPI v);
+int mpi_addm(MPI w, MPI u, MPI v, MPI m);
+int mpi_sub_ui(MPI w, MPI u, ulong v );
+int mpi_sub( MPI w, MPI u, MPI v);
+int mpi_subm( MPI w, MPI u, MPI v, MPI m);
+
+/*-- mpi-mul.c --*/
+int mpi_mul_ui(MPI w, MPI u, ulong v );
+int mpi_mul_2exp( MPI w, MPI u, ulong cnt);
+int mpi_mul( MPI w, MPI u, MPI v);
+int mpi_mulm( MPI w, MPI u, MPI v, MPI m);
+
+/*-- mpi-div.c --*/
+ulong mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor );
+int mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor );
+int mpi_fdiv_q( MPI quot, MPI dividend, MPI divisor );
+int mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor );
+int mpi_tdiv_r( MPI rem, MPI num, MPI den);
+int mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den);
+int mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count );
+int   mpi_divisible_ui(const MPI dividend, ulong divisor );
+
+/*-- mpi-gcd.c --*/
+int mpi_gcd( MPI g, const MPI a, const MPI b );
+
+/*-- mpi-pow.c --*/
+int mpi_pow( MPI w, MPI u, MPI v);
+int mpi_powm( MPI res, MPI base, MPI exp, MPI mod);
+
+/*-- mpi-mpow.c --*/
+int mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI mod);
+
+/*-- mpi-cmp.c --*/
+int mpi_cmp_ui( MPI u, ulong v );
+int mpi_cmp( MPI u, MPI v );
+
+/*-- mpi-scan.c --*/
+int mpi_getbyte( MPI a, unsigned idx );
+void mpi_putbyte( MPI a, unsigned idx, int value );
+unsigned mpi_trailing_zeros( MPI a );
+
+/*-- mpi-bit.c --*/
+void mpi_normalize( MPI a );
+unsigned mpi_get_nbits( MPI a );
+int  mpi_test_bit( MPI a, unsigned n );
+int mpi_set_bit( MPI a, unsigned n );
+int mpi_set_highbit( MPI a, unsigned n );
+void mpi_clear_highbit( MPI a, unsigned n );
+void mpi_clear_bit( MPI a, unsigned n );
+int mpi_rshift( MPI x, MPI a, unsigned n );
+
+/*-- mpi-inv.c --*/
+int mpi_invm( MPI x, MPI u, MPI v );
+
+
+#endif /*G10_MPI_H*/
diff --git a/include/linux/ds1286.h b/include/linux/ds1286.h
new file mode 100644 (file)
index 0000000..d898986
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 1998, 1999, 2003 Ralf Baechle
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __LINUX_DS1286_H
+#define __LINUX_DS1286_H
+
+#include <asm/ds1286.h>
+
+/**********************************************************************
+ * register summary
+ **********************************************************************/
+#define RTC_HUNDREDTH_SECOND   0
+#define RTC_SECONDS            1
+#define RTC_MINUTES            2
+#define RTC_MINUTES_ALARM      3
+#define RTC_HOURS              4
+#define RTC_HOURS_ALARM                5
+#define RTC_DAY                        6
+#define RTC_DAY_ALARM          7
+#define RTC_DATE               8
+#define RTC_MONTH              9
+#define RTC_YEAR               10
+#define RTC_CMD                        11
+#define RTC_WHSEC              12
+#define RTC_WSEC               13
+#define RTC_UNUSED             14
+
+/* RTC_*_alarm is always true if 2 MSBs are set */
+# define RTC_ALARM_DONT_CARE   0xC0
+
+
+/*
+ * Bits in the month register
+ */
+#define RTC_EOSC               0x80
+#define RTC_ESQW               0x40
+
+/*
+ * Bits in the Command register
+ */
+#define RTC_TDF                        0x01
+#define RTC_WAF                        0x02
+#define RTC_TDM                        0x04
+#define RTC_WAM                        0x08
+#define RTC_PU_LVL             0x10
+#define RTC_IBH_LO             0x20
+#define RTC_IPSW               0x40
+#define RTC_TE                 0x80
+
+#endif /* __LINUX_DS1286_H */
diff --git a/include/linux/netfilter_ipv4/ipt_addrtype.h b/include/linux/netfilter_ipv4/ipt_addrtype.h
new file mode 100644 (file)
index 0000000..166ed01
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _IPT_ADDRTYPE_H
+#define _IPT_ADDRTYPE_H
+
+struct ipt_addrtype_info {
+       u_int16_t       source;         /* source-type mask */
+       u_int16_t       dest;           /* dest-type mask */
+       u_int32_t       invert_source;
+       u_int32_t       invert_dest;
+};
+
+#endif
diff --git a/include/linux/netfilter_ipv4/ipt_realm.h b/include/linux/netfilter_ipv4/ipt_realm.h
new file mode 100644 (file)
index 0000000..a4d6698
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _IPT_REALM_H
+#define _IPT_REALM_H
+
+struct ipt_realm_info {
+       u_int32_t id;
+       u_int32_t mask;
+       u_int8_t invert;
+};
+
+#endif /* _IPT_REALM_H */
diff --git a/kernel/module-verify.c b/kernel/module-verify.c
new file mode 100644 (file)
index 0000000..9dacc53
--- /dev/null
@@ -0,0 +1,127 @@
+/* module-verify.c: description
+ *
+ * Written by David Howells (dhowells@redhat.com)
+ * - Derived from GregKH's RSA module signer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/elf.h>
+#include <linux/crypto.h>
+#include <linux/crypto/ksign.h>
+#include <asm/scatterlist.h>
+#include "module-verify.h"
+
+#if 0
+#define _debug(FMT, ...) printk(KERN_DEBUG FMT, ##__VA_ARGS__)
+#else
+#define _debug(FMT, ...) do { ; } while (0)
+#endif
+
+static int signedonly;
+
+/*****************************************************************************/
+/*
+ * verify the signature attached to a module
+ */
+int module_verify_sig(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, const char *secstrings, struct module *mod)
+{
+       struct crypto_tfm *sha1_tfm;
+       unsigned sig_index, sig_size;
+       char *sig;
+       int i;
+
+       /* pull the signature out of the file */
+       sig_index = 0;
+       for (i = 1; i < hdr->e_shnum; i++) {
+               if (strcmp(secstrings + sechdrs[i].sh_name,
+                          "module_sig") == 0) {
+                       sig_index = i;
+                       break;
+               }
+       }
+
+       if (sig_index <= 0)
+               goto no_signature;
+
+       _debug("sig in section %d (size %d)\n",
+              sig_index, sechdrs[sig_index].sh_size);
+
+       sig = (char *) sechdrs[sig_index].sh_addr;
+       sig_size = sechdrs[sig_index].sh_size;
+
+       _debug("");
+
+
+
+
+       /* grab an SHA1 transformation context
+        * - !!! if this tries to load the sha1.ko module, we will deadlock!!!
+        */
+       sha1_tfm = crypto_alloc_tfm2("sha1", 0, 1);
+       if (!sha1_tfm) {
+               printk("Couldn't load module - SHA1 transform unavailable\n");
+               return -EPERM;
+       }
+
+       crypto_digest_init(sha1_tfm);
+
+       for (i = 1; i < hdr->e_shnum; i++) {
+               uint8_t *data;
+               int size;
+               const char *name = secstrings + sechdrs[i].sh_name;
+
+               /* We only care about sections with "text" or "data" in their names */
+               if ((strstr(name, "text") == NULL) &&
+                   (strstr(name, "data") == NULL))
+                       continue;
+
+               /* avoid the ".rel.*" sections too. */
+               if (strstr(name, ".rel.") != NULL)
+                       continue;
+
+               /* avoid the ".rel.*" sections too. */
+               if (strstr(name, ".rela.") != NULL)
+                       continue;
+
+               data = (uint8_t *) sechdrs[i].sh_addr;
+               size = sechdrs[i].sh_size;
+
+               _debug("SHA1ing the %s section, size %d\n", name, size);
+               _debug("idata [ %02x%02x%02x%02x ]\n",
+                      data[0], data[1], data[2], data[3]);
+
+               crypto_digest_update_kernel(sha1_tfm, data, size);
+       }
+
+       /* do the actual signature verification */
+       i = ksign_verify_signature(sig, sig_size, sha1_tfm);
+       if (!i)
+                mod->gpgsig_ok = 1;
+       
+       return i;
+
+       /* deal with the case of an unsigned module */
+ no_signature:
+       if (!signedonly)
+               return 0;
+       printk("An attempt to load unsigned module was rejected\n");
+       return -EPERM;
+} /* end module_verify_sig() */
+
+static int __init sign_setup(char *str)
+{
+       signedonly = 1;
+       return 0;
+}
+__setup("enforcemodulesig", sign_setup);
+                        
diff --git a/kernel/module-verify.h b/kernel/module-verify.h
new file mode 100644 (file)
index 0000000..10efab8
--- /dev/null
@@ -0,0 +1,15 @@
+/* module-verify.h: module verification definitions
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifdef CONFIG_MODULE_SIG
+extern int module_verify_sig(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
+                            const char *secstrings, struct module *mod);
+#endif
diff --git a/net/bluetooth/hidp/Makefile b/net/bluetooth/hidp/Makefile
new file mode 100644 (file)
index 0000000..a9ee115
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the Linux Bluetooth HIDP layer
+#
+
+obj-$(CONFIG_BT_HIDP) += hidp.o
+
+hidp-objs := core.o sock.o
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
new file mode 100644 (file)
index 0000000..7e8e7ba
--- /dev/null
@@ -0,0 +1,649 @@
+/* 
+   HIDP implementation for Linux Bluetooth stack (BlueZ).
+   Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 as
+   published by the Free Software Foundation;
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   SOFTWARE IS DISCLAIMED.
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/fcntl.h>
+#include <linux/skbuff.h>
+#include <linux/socket.h>
+#include <linux/ioctl.h>
+#include <linux/file.h>
+#include <linux/init.h>
+#include <net/sock.h>
+
+#include <linux/input.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/l2cap.h>
+
+#include "hidp.h"
+
+#ifndef CONFIG_BT_HIDP_DEBUG
+#undef  BT_DBG
+#define BT_DBG(D...)
+#endif
+
+#define VERSION "1.0"
+
+static DECLARE_RWSEM(hidp_session_sem);
+static LIST_HEAD(hidp_session_list);
+
+static unsigned char hidp_keycode[256] = {
+         0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
+        50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
+         4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
+        27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
+        65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
+       105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
+        72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
+       191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
+       115,114,  0,  0,  0,121,  0, 89, 93,124, 92, 94, 95,  0,  0,  0,
+       122,123, 90, 91, 85,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+        29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
+       150,158,159,128,136,177,178,176,142,152,173,140
+};
+
+static struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr)
+{
+       struct hidp_session *session;
+       struct list_head *p;
+
+       BT_DBG("");
+
+       list_for_each(p, &hidp_session_list) {
+               session = list_entry(p, struct hidp_session, list);
+               if (!bacmp(bdaddr, &session->bdaddr))
+                       return session;
+       }
+       return NULL;
+}
+
+static void __hidp_link_session(struct hidp_session *session)
+{
+       __module_get(THIS_MODULE);
+       list_add(&session->list, &hidp_session_list);
+}
+
+static void __hidp_unlink_session(struct hidp_session *session)
+{
+       list_del(&session->list);
+       module_put(THIS_MODULE);
+}
+
+static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
+{
+       bacpy(&ci->bdaddr, &session->bdaddr);
+
+       ci->flags = session->flags;
+       ci->state = session->state;
+
+       ci->vendor  = 0x0000;
+       ci->product = 0x0000;
+       ci->version = 0x0000;
+       memset(ci->name, 0, 128);
+
+       if (session->input) {
+               ci->vendor  = session->input->id.vendor;
+               ci->product = session->input->id.product;
+               ci->version = session->input->id.version;
+               if (session->input->name)
+                       strncpy(ci->name, session->input->name, 128);
+               else
+                       strncpy(ci->name, "HID Boot Device", 128);
+       }
+}
+
+static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+       struct hidp_session *session = dev->private;
+       struct sk_buff *skb;
+       unsigned char newleds;
+
+       BT_DBG("session %p hid %p data %p size %d", session, device, data, size);
+
+       if (type != EV_LED)
+               return -1;
+
+       newleds = (!!test_bit(LED_KANA,    dev->led) << 3) |
+                 (!!test_bit(LED_COMPOSE, dev->led) << 3) |
+                 (!!test_bit(LED_SCROLLL, dev->led) << 2) |
+                 (!!test_bit(LED_CAPSL,   dev->led) << 1) |
+                 (!!test_bit(LED_NUML,    dev->led));
+
+       if (session->leds == newleds)
+               return 0;
+
+       session->leds = newleds;
+
+       if (!(skb = alloc_skb(3, GFP_ATOMIC))) {
+               BT_ERR("Can't allocate memory for new frame");
+               return -ENOMEM;
+       }
+
+       *skb_put(skb, 1) = 0xa2;
+       *skb_put(skb, 1) = 0x01;
+       *skb_put(skb, 1) = newleds;
+
+       skb_queue_tail(&session->intr_transmit, skb);
+
+       hidp_schedule(session);
+
+       return 0;
+}
+
+static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
+{
+       struct input_dev *dev = session->input;
+       unsigned char *keys = session->keys;
+       unsigned char *udata = skb->data + 1;
+       signed char *sdata = skb->data + 1;
+       int i, size = skb->len - 1;
+
+       switch (skb->data[0]) {
+       case 0x01:      /* Keyboard report */
+               for (i = 0; i < 8; i++)
+                       input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
+
+               for (i = 2; i < 8; i++) {
+                       if (keys[i] > 3 && memscan(udata + 2, keys[i], 6) == udata + 8) {
+                               if (hidp_keycode[keys[i]])
+                                       input_report_key(dev, hidp_keycode[keys[i]], 0);
+                               else
+                                       BT_ERR("Unknown key (scancode %#x) released.", keys[i]);
+                       }
+
+                       if (udata[i] > 3 && memscan(keys + 2, udata[i], 6) == keys + 8) {
+                               if (hidp_keycode[udata[i]])
+                                       input_report_key(dev, hidp_keycode[udata[i]], 1);
+                               else
+                                       BT_ERR("Unknown key (scancode %#x) pressed.", udata[i]);
+                       }
+               }
+
+               memcpy(keys, udata, 8);
+               break;
+
+       case 0x02:      /* Mouse report */
+               input_report_key(dev, BTN_LEFT,   sdata[0] & 0x01);
+               input_report_key(dev, BTN_RIGHT,  sdata[0] & 0x02);
+               input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
+               input_report_key(dev, BTN_SIDE,   sdata[0] & 0x08);
+               input_report_key(dev, BTN_EXTRA,  sdata[0] & 0x10);
+
+               input_report_rel(dev, REL_X, sdata[1]);
+               input_report_rel(dev, REL_Y, sdata[2]);
+
+               if (size > 3)
+                       input_report_rel(dev, REL_WHEEL, sdata[3]);
+               break;
+       }
+
+       input_sync(dev);
+}
+
+static void hidp_idle_timeout(unsigned long arg)
+{
+       struct hidp_session *session = (struct hidp_session *) arg;
+
+       atomic_inc(&session->terminate);
+       hidp_schedule(session);
+}
+
+static inline void hidp_set_timer(struct hidp_session *session)
+{
+       if (session->idle_to > 0)
+               mod_timer(&session->timer, jiffies + HZ * session->idle_to);
+}
+
+static inline void hidp_del_timer(struct hidp_session *session)
+{
+       if (session->idle_to > 0)
+               del_timer(&session->timer);
+}
+
+static inline void hidp_send_message(struct hidp_session *session, unsigned char hdr)
+{
+       struct sk_buff *skb;
+
+       BT_DBG("session %p", session);
+
+       if (!(skb = alloc_skb(1, GFP_ATOMIC))) {
+               BT_ERR("Can't allocate memory for message");
+               return;
+       }
+
+       *skb_put(skb, 1) = hdr;
+
+       skb_queue_tail(&session->ctrl_transmit, skb);
+
+       hidp_schedule(session);
+}
+
+static inline int hidp_recv_frame(struct hidp_session *session, struct sk_buff *skb)
+{
+       __u8 hdr;
+
+       BT_DBG("session %p skb %p len %d", session, skb, skb->len);
+
+       hdr = skb->data[0];
+       skb_pull(skb, 1);
+
+       if (hdr == 0xa1) {
+               hidp_set_timer(session);
+
+               if (session->input)
+                       hidp_input_report(session, skb);
+       } else {
+               BT_DBG("Unsupported protocol header 0x%02x", hdr);
+       }
+
+       kfree_skb(skb);
+       return 0;
+}
+
+static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
+{
+       struct iovec iv = { data, len };
+       struct msghdr msg;
+
+       BT_DBG("sock %p data %p len %d", sock, data, len);
+
+       if (!len)
+               return 0;
+
+       memset(&msg, 0, sizeof(msg));
+       msg.msg_iovlen = 1;
+       msg.msg_iov = &iv;
+
+       return sock_sendmsg(sock, &msg, len);
+}
+
+static int hidp_process_transmit(struct hidp_session *session)
+{
+       struct sk_buff *skb;
+
+       BT_DBG("session %p", session);
+
+       while ((skb = skb_dequeue(&session->ctrl_transmit))) {
+               if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
+                       skb_queue_head(&session->ctrl_transmit, skb);
+                       break;
+               }
+
+               hidp_set_timer(session);
+               kfree_skb(skb);
+       }
+
+       while ((skb = skb_dequeue(&session->intr_transmit))) {
+               if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
+                       skb_queue_head(&session->intr_transmit, skb);
+                       break;
+               }
+
+               hidp_set_timer(session);
+               kfree_skb(skb);
+       }
+
+       return skb_queue_len(&session->ctrl_transmit) +
+                               skb_queue_len(&session->intr_transmit);
+}
+
+static int hidp_session(void *arg)
+{
+       struct hidp_session *session = arg;
+       struct sock *ctrl_sk = session->ctrl_sock->sk;
+       struct sock *intr_sk = session->intr_sock->sk;
+       struct sk_buff *skb;
+       int vendor = 0x0000, product = 0x0000;
+       wait_queue_t ctrl_wait, intr_wait;
+       unsigned long timeo = HZ;
+
+       BT_DBG("session %p", session);
+
+       if (session->input) {
+               vendor  = session->input->id.vendor;
+               product = session->input->id.product;
+       }
+
+       daemonize("khidpd_%04x%04x", vendor, product);
+       set_user_nice(current, -15);
+       current->flags |= PF_NOFREEZE;
+
+       set_fs(KERNEL_DS);
+
+       init_waitqueue_entry(&ctrl_wait, current);
+       init_waitqueue_entry(&intr_wait, current);
+       add_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait);
+       add_wait_queue(intr_sk->sk_sleep, &intr_wait);
+       while (!atomic_read(&session->terminate)) {
+               set_current_state(TASK_INTERRUPTIBLE);
+
+               if (ctrl_sk->sk_state != BT_CONNECTED || intr_sk->sk_state != BT_CONNECTED)
+                       break;
+
+               while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
+                       skb_orphan(skb);
+                       hidp_recv_frame(session, skb);
+               }
+
+               while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
+                       skb_orphan(skb);
+                       hidp_recv_frame(session, skb);
+               }
+
+               hidp_process_transmit(session);
+
+               schedule();
+       }
+       set_current_state(TASK_RUNNING);
+       remove_wait_queue(intr_sk->sk_sleep, &intr_wait);
+       remove_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait);
+
+       down_write(&hidp_session_sem);
+
+       hidp_del_timer(session);
+
+       if (intr_sk->sk_state != BT_CONNECTED) {
+               init_waitqueue_entry(&ctrl_wait, current);
+               add_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait);
+               while (timeo && ctrl_sk->sk_state != BT_CLOSED) {
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       timeo = schedule_timeout(timeo);
+               }
+               set_current_state(TASK_RUNNING);
+               remove_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait);
+               timeo = HZ;
+       }
+
+       fput(session->ctrl_sock->file);
+
+       init_waitqueue_entry(&intr_wait, current);
+       add_wait_queue(intr_sk->sk_sleep, &intr_wait);
+       while (timeo && intr_sk->sk_state != BT_CLOSED) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               timeo = schedule_timeout(timeo);
+       }
+       set_current_state(TASK_RUNNING);
+       remove_wait_queue(intr_sk->sk_sleep, &intr_wait);
+
+       fput(session->intr_sock->file);
+
+       __hidp_unlink_session(session);
+
+       if (session->input) {
+               input_unregister_device(session->input);
+               kfree(session->input);
+       }
+
+       up_write(&hidp_session_sem);
+
+       kfree(session);
+       return 0;
+}
+
+static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
+{
+       struct input_dev *input = session->input;
+       int i;
+
+       input->private = session;
+
+       input->id.bustype = BUS_BLUETOOTH;
+       input->id.vendor  = req->vendor;
+       input->id.product = req->product;
+       input->id.version = req->version;
+
+       if (req->subclass & 0x40) {
+               set_bit(EV_KEY, input->evbit);
+               set_bit(EV_LED, input->evbit);
+               set_bit(EV_REP, input->evbit);
+
+               set_bit(LED_NUML,    input->ledbit);
+               set_bit(LED_CAPSL,   input->ledbit);
+               set_bit(LED_SCROLLL, input->ledbit);
+               set_bit(LED_COMPOSE, input->ledbit);
+               set_bit(LED_KANA,    input->ledbit);
+
+               for (i = 0; i < sizeof(hidp_keycode); i++)
+                       set_bit(hidp_keycode[i], input->keybit);
+               clear_bit(0, input->keybit);
+       }
+
+       if (req->subclass & 0x80) {
+               input->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+               input->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+               input->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+               input->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
+               input->relbit[0] |= BIT(REL_WHEEL);
+       }
+
+       input->event = hidp_input_event;
+
+       input_register_device(input);
+}
+
+int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
+{
+       struct hidp_session *session, *s;
+       int err;
+
+       BT_DBG("");
+
+       if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||
+                       bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
+               return -ENOTUNIQ;
+
+       session = kmalloc(sizeof(struct hidp_session), GFP_KERNEL);
+       if (!session) 
+               return -ENOMEM;
+       memset(session, 0, sizeof(struct hidp_session));
+
+       session->input = kmalloc(sizeof(struct input_dev), GFP_KERNEL);
+       if (!session->input) {
+               kfree(session);
+               return -ENOMEM;
+       }
+       memset(session->input, 0, sizeof(struct input_dev));
+
+       down_write(&hidp_session_sem);
+
+       s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
+       if (s && s->state == BT_CONNECTED) {
+               err = -EEXIST;
+               goto failed;
+       }
+
+       bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
+
+       session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->omtu, l2cap_pi(ctrl_sock->sk)->imtu);
+       session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->omtu, l2cap_pi(intr_sock->sk)->imtu);
+
+       BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
+
+       session->ctrl_sock = ctrl_sock;
+       session->intr_sock = intr_sock;
+       session->state     = BT_CONNECTED;
+
+       init_timer(&session->timer);
+
+       session->timer.function = hidp_idle_timeout;
+       session->timer.data     = (unsigned long) session;
+
+       skb_queue_head_init(&session->ctrl_transmit);
+       skb_queue_head_init(&session->intr_transmit);
+
+       session->flags   = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
+       session->idle_to = req->idle_to;
+
+       if (session->input)
+               hidp_setup_input(session, req);
+
+       __hidp_link_session(session);
+
+       hidp_set_timer(session);
+
+       err = kernel_thread(hidp_session, session, CLONE_KERNEL);
+       if (err < 0)
+               goto unlink;
+
+       if (session->input) {
+               hidp_send_message(session, 0x70);
+               session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
+
+               session->leds = 0xff;
+               hidp_input_event(session->input, EV_LED, 0, 0);
+       }
+
+       up_write(&hidp_session_sem);
+       return 0;
+
+unlink:
+       hidp_del_timer(session);
+
+       __hidp_unlink_session(session);
+
+       if (session->input)
+               input_unregister_device(session->input);
+
+failed:
+       up_write(&hidp_session_sem);
+
+       if (session->input)
+               kfree(session->input);
+
+       kfree(session);
+       return err;
+}
+
+int hidp_del_connection(struct hidp_conndel_req *req)
+{
+       struct hidp_session *session;
+       int err = 0;
+
+       BT_DBG("");
+
+       down_read(&hidp_session_sem);
+
+       session = __hidp_get_session(&req->bdaddr);
+       if (session) {
+               if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
+                       hidp_send_message(session, 0x15);
+               } else {
+                       /* Flush the transmit queues */
+                       skb_queue_purge(&session->ctrl_transmit);
+                       skb_queue_purge(&session->intr_transmit);
+
+                       /* Kill session thread */
+                       atomic_inc(&session->terminate);
+                       hidp_schedule(session);
+               }
+       } else
+               err = -ENOENT;
+
+       up_read(&hidp_session_sem);
+       return err;
+}
+
+int hidp_get_connlist(struct hidp_connlist_req *req)
+{
+       struct list_head *p;
+       int err = 0, n = 0;
+
+       BT_DBG("");
+
+       down_read(&hidp_session_sem);
+
+       list_for_each(p, &hidp_session_list) {
+               struct hidp_session *session;
+               struct hidp_conninfo ci;
+
+               session = list_entry(p, struct hidp_session, list);
+
+               __hidp_copy_session(session, &ci);
+
+               if (copy_to_user(req->ci, &ci, sizeof(ci))) {
+                       err = -EFAULT;
+                       break;
+               }
+
+               if (++n >= req->cnum)
+                       break;
+
+               req->ci++;
+       }
+       req->cnum = n;
+
+       up_read(&hidp_session_sem);
+       return err;
+}
+
+int hidp_get_conninfo(struct hidp_conninfo *ci)
+{
+       struct hidp_session *session;
+       int err = 0;
+
+       down_read(&hidp_session_sem);
+
+       session = __hidp_get_session(&ci->bdaddr);
+       if (session)
+               __hidp_copy_session(session, ci);
+       else
+               err = -ENOENT;
+
+       up_read(&hidp_session_sem);
+       return err;
+}
+
+static int __init hidp_init(void)
+{
+       l2cap_load();
+
+       BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
+
+       return hidp_init_sockets();
+}
+
+static void __exit hidp_exit(void)
+{
+       hidp_cleanup_sockets();
+}
+
+module_init(hidp_init);
+module_exit(hidp_exit);
+
+MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
+MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("bt-proto-6");
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
new file mode 100644 (file)
index 0000000..98a742a
--- /dev/null
@@ -0,0 +1,122 @@
+/* 
+   HIDP implementation for Linux Bluetooth stack (BlueZ).
+   Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 as
+   published by the Free Software Foundation;
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   SOFTWARE IS DISCLAIMED.
+*/
+
+#ifndef __HIDP_H
+#define __HIDP_H
+
+#include <linux/types.h>
+#include <net/bluetooth/bluetooth.h>
+
+/* HIDP ioctl defines */
+#define HIDPCONNADD    _IOW('H', 200, int)
+#define HIDPCONNDEL    _IOW('H', 201, int)
+#define HIDPGETCONNLIST        _IOR('H', 210, int)
+#define HIDPGETCONNINFO        _IOR('H', 211, int)
+
+#define HIDP_VIRTUAL_CABLE_UNPLUG      0
+#define HIDP_BOOT_PROTOCOL_MODE                1
+#define HIDP_BLUETOOTH_VENDOR_ID       9
+
+struct hidp_connadd_req {
+       int   ctrl_sock;        // Connected control socket
+       int   intr_sock;        // Connteted interrupt socket
+       __u16 parser;
+       __u16 rd_size;
+       __u8 *rd_data;
+       __u8  country;
+       __u8  subclass;
+       __u16 vendor;
+       __u16 product;
+       __u16 version;
+       __u32 flags;
+       __u32 idle_to;
+       char  name[128];
+};
+
+struct hidp_conndel_req {
+       bdaddr_t bdaddr;
+       __u32    flags;
+};
+
+struct hidp_conninfo {
+       bdaddr_t bdaddr;
+       __u32    flags;
+       __u16    state;
+       __u16    vendor;
+       __u16    product;
+       __u16    version;
+       char     name[128];
+};
+
+struct hidp_connlist_req {
+       __u32  cnum;
+       struct hidp_conninfo __user *ci;
+};
+
+int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock);
+int hidp_del_connection(struct hidp_conndel_req *req);
+int hidp_get_connlist(struct hidp_connlist_req *req);
+int hidp_get_conninfo(struct hidp_conninfo *ci);
+
+/* HIDP session defines */
+struct hidp_session {
+       struct list_head list;
+
+       struct socket *ctrl_sock;
+       struct socket *intr_sock;
+
+       bdaddr_t bdaddr;
+
+       unsigned long state;
+       unsigned long flags;
+       unsigned long idle_to;
+
+       uint ctrl_mtu;
+       uint intr_mtu;
+
+       atomic_t terminate;
+
+       unsigned char keys[8];
+       unsigned char leds;
+
+       struct input_dev *input;
+
+       struct timer_list timer;
+
+       struct sk_buff_head ctrl_transmit;
+       struct sk_buff_head intr_transmit;
+};
+
+static inline void hidp_schedule(struct hidp_session *session)
+{
+       struct sock *ctrl_sk = session->ctrl_sock->sk;
+       struct sock *intr_sk = session->intr_sock->sk;
+
+       wake_up_interruptible(ctrl_sk->sk_sleep);
+       wake_up_interruptible(intr_sk->sk_sleep);
+}
+
+/* HIDP init defines */
+extern int __init hidp_init_sockets(void);
+extern void __exit hidp_cleanup_sockets(void);
+
+#endif /* __HIDP_H */
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
new file mode 100644 (file)
index 0000000..f65ec86
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * xfrm4_output.c - Common IPsec encapsulation code for IPv4.
+ * Copyright (c) 2004 Herbert Xu <herbert@gondor.apana.org.au>
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <net/inet_ecn.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+
+/* Add encapsulation header.
+ *
+ * In transport mode, the IP header will be moved forward to make space
+ * for the encapsulation header.
+ *
+ * In tunnel mode, the top IP header will be constructed per RFC 2401.
+ * The following fields in it shall be filled in by x->type->output:
+ *     tot_len
+ *     check
+ *
+ * On exit, skb->h will be set to the start of the payload to be processed
+ * by x->type->output and skb->nh will be set to the top IP header.
+ */
+static void xfrm4_encap(struct sk_buff *skb)
+{
+       struct dst_entry *dst = skb->dst;
+       struct xfrm_state *x = dst->xfrm;
+       struct iphdr *iph, *top_iph;
+
+       iph = skb->nh.iph;
+       skb->h.ipiph = iph;
+
+       skb->nh.raw = skb_push(skb, x->props.header_len);
+       top_iph = skb->nh.iph;
+
+       if (!x->props.mode) {
+               skb->h.raw += iph->ihl*4;
+               memmove(top_iph, iph, iph->ihl*4);
+               return;
+       }
+
+       top_iph->ihl = 5;
+       top_iph->version = 4;
+
+       /* DS disclosed */
+       top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
+       if (x->props.flags & XFRM_STATE_NOECN)
+               IP_ECN_clear(top_iph);
+
+       top_iph->frag_off = iph->frag_off & htons(IP_DF);
+       if (!top_iph->frag_off)
+               __ip_select_ident(top_iph, dst, 0);
+
+       /* TTL disclosed */
+       top_iph->ttl = iph->ttl;
+
+       top_iph->saddr = x->props.saddr.a4;
+       top_iph->daddr = x->id.daddr.a4;
+       top_iph->protocol = IPPROTO_IPIP;
+
+       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+}
+
+int xfrm4_output(struct sk_buff **pskb)
+{
+       struct sk_buff *skb = *pskb;
+       struct dst_entry *dst = skb->dst;
+       struct xfrm_state *x = dst->xfrm;
+       int err;
+       
+       if (skb->ip_summed == CHECKSUM_HW) {
+               err = skb_checksum_help(pskb, 0);
+               skb = *pskb;
+               if (err)
+                       goto error_nolock;
+       }
+
+       spin_lock_bh(&x->lock);
+       err = xfrm_state_check(x, skb);
+       if (err)
+               goto error;
+
+       if (x->props.mode) {
+               err = xfrm4_tunnel_check_size(skb);
+               if (err)
+                       goto error;
+       }
+
+       xfrm4_encap(skb);
+
+       err = x->type->output(pskb);
+       skb = *pskb;
+       if (err)
+               goto error;
+
+       x->curlft.bytes += skb->len;
+       x->curlft.packets++;
+
+       spin_unlock_bh(&x->lock);
+       
+       if (!(skb->dst = dst_pop(dst))) {
+               err = -EHOSTUNREACH;
+               goto error_nolock;
+       }
+       err = NET_XMIT_BYPASS;
+
+out_exit:
+       return err;
+error:
+       spin_unlock_bh(&x->lock);
+error_nolock:
+       kfree_skb(skb);
+       goto out_exit;
+}
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
new file mode 100644 (file)
index 0000000..f5a0654
--- /dev/null
@@ -0,0 +1,634 @@
+/*
+ * Copyright (C)2003,2004 USAGI/WIDE Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors     Mitsuru KANDA  <mk@linux-ipv6.org>
+ *             YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
+ *
+ * Based on net/ipv4/xfrm4_tunnel.c
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/xfrm.h>
+#include <linux/list.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+#include <net/icmp.h>
+#include <net/ipv6.h>
+#include <linux/ipv6.h>
+#include <linux/icmpv6.h>
+
+#ifdef CONFIG_IPV6_XFRM6_TUNNEL_DEBUG
+# define X6TDEBUG      3
+#else
+# define X6TDEBUG      1
+#endif
+
+#define X6TPRINTK(fmt, args...)                printk(fmt, ## args)
+#define X6TNOPRINTK(fmt, args...)      do { ; } while(0)
+
+#if X6TDEBUG >= 1
+# define X6TPRINTK1    X6TPRINTK
+#else
+# define X6TPRINTK1    X6TNOPRINTK
+#endif
+
+#if X6TDEBUG >= 3
+# define X6TPRINTK3    X6TPRINTK
+#else
+# define X6TPRINTK3    X6TNOPRINTK
+#endif
+
+/*
+ * xfrm_tunnel_spi things are for allocating unique id ("spi") 
+ * per xfrm_address_t.
+ */
+struct xfrm6_tunnel_spi {
+       struct hlist_node list_byaddr;
+       struct hlist_node list_byspi;
+       xfrm_address_t addr;
+       u32 spi;
+       atomic_t refcnt;
+#ifdef XFRM6_TUNNEL_SPI_MAGIC
+       u32 magic;
+#endif
+};
+
+#ifdef CONFIG_IPV6_XFRM6_TUNNEL_DEBUG
+# define XFRM6_TUNNEL_SPI_MAGIC 0xdeadbeef
+#endif
+
+static rwlock_t xfrm6_tunnel_spi_lock = RW_LOCK_UNLOCKED;
+
+static u32 xfrm6_tunnel_spi;
+
+#define XFRM6_TUNNEL_SPI_MIN   1
+#define XFRM6_TUNNEL_SPI_MAX   0xffffffff
+
+static kmem_cache_t *xfrm6_tunnel_spi_kmem;
+
+#define XFRM6_TUNNEL_SPI_BYADDR_HSIZE 256
+#define XFRM6_TUNNEL_SPI_BYSPI_HSIZE 256
+
+static struct hlist_head xfrm6_tunnel_spi_byaddr[XFRM6_TUNNEL_SPI_BYADDR_HSIZE];
+static struct hlist_head xfrm6_tunnel_spi_byspi[XFRM6_TUNNEL_SPI_BYSPI_HSIZE];
+
+#ifdef XFRM6_TUNNEL_SPI_MAGIC
+static int x6spi_check_magic(const struct xfrm6_tunnel_spi *x6spi,
+                            const char *name)
+{
+       if (unlikely(x6spi->magic != XFRM6_TUNNEL_SPI_MAGIC)) {
+               X6TPRINTK3(KERN_DEBUG "%s(): x6spi object "
+                                     "at %p has corrupted magic %08x "
+                                     "(should be %08x)\n",
+                          name, x6spi, x6spi->magic, XFRM6_TUNNEL_SPI_MAGIC);
+               return -1;
+       }
+       return 0;
+}
+#else
+static int inline x6spi_check_magic(const struct xfrm6_tunnel_spi *x6spi,
+                                   const char *name)
+{
+       return 0;
+}
+#endif
+
+#define X6SPI_CHECK_MAGIC(x6spi) x6spi_check_magic((x6spi), __FUNCTION__)
+
+
+static unsigned inline xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr)
+{
+       unsigned h;
+
+       X6TPRINTK3(KERN_DEBUG "%s(addr=%p)\n", __FUNCTION__, addr);
+
+       h = addr->a6[0] ^ addr->a6[1] ^ addr->a6[2] ^ addr->a6[3];
+       h ^= h >> 16;
+       h ^= h >> 8;
+       h &= XFRM6_TUNNEL_SPI_BYADDR_HSIZE - 1;
+
+       X6TPRINTK3(KERN_DEBUG "%s() = %u\n", __FUNCTION__, h);
+
+       return h;
+}
+
+static unsigned inline xfrm6_tunnel_spi_hash_byspi(u32 spi)
+{
+       return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE;
+}
+
+
+static int xfrm6_tunnel_spi_init(void)
+{
+       int i;
+
+       X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
+
+       xfrm6_tunnel_spi = 0;
+       xfrm6_tunnel_spi_kmem = kmem_cache_create("xfrm6_tunnel_spi",
+                                                 sizeof(struct xfrm6_tunnel_spi),
+                                                 0, SLAB_HWCACHE_ALIGN,
+                                                 NULL, NULL);
+       if (!xfrm6_tunnel_spi_kmem) {
+               X6TPRINTK1(KERN_ERR
+                          "%s(): failed to allocate xfrm6_tunnel_spi_kmem\n",
+                          __FUNCTION__);
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++)
+               INIT_HLIST_HEAD(&xfrm6_tunnel_spi_byaddr[i]);
+       for (i = 0; i < XFRM6_TUNNEL_SPI_BYSPI_HSIZE; i++)
+               INIT_HLIST_HEAD(&xfrm6_tunnel_spi_byspi[i]);
+       return 0;
+}
+
+static void xfrm6_tunnel_spi_fini(void)
+{
+       int i;
+
+       X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
+
+       for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++) {
+               if (!hlist_empty(&xfrm6_tunnel_spi_byaddr[i]))
+                       goto err;
+       }
+       for (i = 0; i < XFRM6_TUNNEL_SPI_BYSPI_HSIZE; i++) {
+               if (!hlist_empty(&xfrm6_tunnel_spi_byspi[i]))
+                       goto err;
+       }
+       kmem_cache_destroy(xfrm6_tunnel_spi_kmem);
+       xfrm6_tunnel_spi_kmem = NULL;
+       return;
+err:
+       X6TPRINTK1(KERN_ERR "%s(): table is not empty\n", __FUNCTION__);
+       return;
+}
+
+static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
+{
+       struct xfrm6_tunnel_spi *x6spi;
+       struct hlist_node *pos;
+
+       X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr);
+
+       hlist_for_each_entry(x6spi, pos,
+                            &xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)],
+                            list_byaddr) {
+               if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) {
+                       X6SPI_CHECK_MAGIC(x6spi);
+                       X6TPRINTK3(KERN_DEBUG "%s() = %p(%u)\n", __FUNCTION__, x6spi, x6spi->spi);
+                       return x6spi;
+               }
+       }
+
+       X6TPRINTK3(KERN_DEBUG "%s() = NULL(0)\n", __FUNCTION__);
+       return NULL;
+}
+
+u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
+{
+       struct xfrm6_tunnel_spi *x6spi;
+       u32 spi;
+
+       X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr);
+
+       read_lock_bh(&xfrm6_tunnel_spi_lock);
+       x6spi = __xfrm6_tunnel_spi_lookup(saddr);
+       spi = x6spi ? x6spi->spi : 0;
+       read_unlock_bh(&xfrm6_tunnel_spi_lock);
+       return spi;
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup);
+
+static u32 __xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
+{
+       u32 spi;
+       struct xfrm6_tunnel_spi *x6spi;
+       struct hlist_node *pos;
+       unsigned index;
+
+       X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr);
+
+       if (xfrm6_tunnel_spi < XFRM6_TUNNEL_SPI_MIN ||
+           xfrm6_tunnel_spi >= XFRM6_TUNNEL_SPI_MAX)
+               xfrm6_tunnel_spi = XFRM6_TUNNEL_SPI_MIN;
+       else
+               xfrm6_tunnel_spi++;
+
+       for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) {
+               index = xfrm6_tunnel_spi_hash_byspi(spi);
+               hlist_for_each_entry(x6spi, pos, 
+                                    &xfrm6_tunnel_spi_byspi[index], 
+                                    list_byspi) {
+                       if (x6spi->spi == spi)
+                               goto try_next_1;
+               }
+               xfrm6_tunnel_spi = spi;
+               goto alloc_spi;
+try_next_1:;
+       }
+       for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) {
+               index = xfrm6_tunnel_spi_hash_byspi(spi);
+               hlist_for_each_entry(x6spi, pos, 
+                                    &xfrm6_tunnel_spi_byspi[index], 
+                                    list_byspi) {
+                       if (x6spi->spi == spi)
+                               goto try_next_2;
+               }
+               xfrm6_tunnel_spi = spi;
+               goto alloc_spi;
+try_next_2:;
+       }
+       spi = 0;
+       goto out;
+alloc_spi:
+       X6TPRINTK3(KERN_DEBUG "%s(): allocate new spi for "
+                             "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", 
+                             __FUNCTION__, 
+                             NIP6(*(struct in6_addr *)saddr));
+       x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, SLAB_ATOMIC);
+       if (!x6spi) {
+               X6TPRINTK1(KERN_ERR "%s(): kmem_cache_alloc() failed\n", 
+                          __FUNCTION__);
+               goto out;
+       }
+#ifdef XFRM6_TUNNEL_SPI_MAGIC
+       x6spi->magic = XFRM6_TUNNEL_SPI_MAGIC;
+#endif
+       memcpy(&x6spi->addr, saddr, sizeof(x6spi->addr));
+       x6spi->spi = spi;
+       atomic_set(&x6spi->refcnt, 1);
+
+       hlist_add_head(&x6spi->list_byspi, &xfrm6_tunnel_spi_byspi[index]);
+
+       index = xfrm6_tunnel_spi_hash_byaddr(saddr);
+       hlist_add_head(&x6spi->list_byaddr, &xfrm6_tunnel_spi_byaddr[index]);
+       X6SPI_CHECK_MAGIC(x6spi);
+out:
+       X6TPRINTK3(KERN_DEBUG "%s() = %u\n", __FUNCTION__, spi);
+       return spi;
+}
+
+u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
+{
+       struct xfrm6_tunnel_spi *x6spi;
+       u32 spi;
+
+       X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr);
+
+       write_lock_bh(&xfrm6_tunnel_spi_lock);
+       x6spi = __xfrm6_tunnel_spi_lookup(saddr);
+       if (x6spi) {
+               atomic_inc(&x6spi->refcnt);
+               spi = x6spi->spi;
+       } else
+               spi = __xfrm6_tunnel_alloc_spi(saddr);
+       write_unlock_bh(&xfrm6_tunnel_spi_lock);
+
+       X6TPRINTK3(KERN_DEBUG "%s() = %u\n", __FUNCTION__, spi);
+
+       return spi;
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_alloc_spi);
+
+void xfrm6_tunnel_free_spi(xfrm_address_t *saddr)
+{
+       struct xfrm6_tunnel_spi *x6spi;
+       struct hlist_node *pos, *n;
+
+       X6TPRINTK3(KERN_DEBUG "%s(saddr=%p)\n", __FUNCTION__, saddr);
+
+       write_lock_bh(&xfrm6_tunnel_spi_lock);
+
+       hlist_for_each_entry_safe(x6spi, pos, n, 
+                                 &xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)],
+                                 list_byaddr)
+       {
+               if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) {
+                       X6TPRINTK3(KERN_DEBUG "%s(): x6spi object "
+                                             "for %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
+                                             "found at %p\n",
+                                  __FUNCTION__, 
+                                  NIP6(*(struct in6_addr *)saddr),
+                                  x6spi);
+                       X6SPI_CHECK_MAGIC(x6spi);
+                       if (atomic_dec_and_test(&x6spi->refcnt)) {
+                               hlist_del(&x6spi->list_byaddr);
+                               hlist_del(&x6spi->list_byspi);
+                               kmem_cache_free(xfrm6_tunnel_spi_kmem, x6spi);
+                               break;
+                       }
+               }
+       }
+       write_unlock_bh(&xfrm6_tunnel_spi_lock);
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_free_spi);
+
+int xfrm6_tunnel_check_size(struct sk_buff *skb)
+{
+       int mtu, ret = 0;
+       struct dst_entry *dst = skb->dst;
+
+       mtu = dst_pmtu(dst) - sizeof(struct ipv6hdr);
+       if (mtu < IPV6_MIN_MTU)
+               mtu = IPV6_MIN_MTU;
+
+       if (skb->len > mtu) {
+               icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
+               ret = -EMSGSIZE;
+       }
+
+       return ret;
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_check_size);
+
+static int xfrm6_tunnel_output(struct sk_buff **pskb)
+{
+       struct sk_buff *skb = *pskb;
+       struct dst_entry *dst = skb->dst;
+       struct xfrm_state *x = dst->xfrm;
+       struct ipv6hdr *iph, *top_iph;
+       int err;
+
+       if ((err = xfrm6_tunnel_check_size(skb)) != 0)
+               goto error_nolock;
+
+       iph = skb->nh.ipv6h;
+
+       top_iph = (struct ipv6hdr *)skb_push(skb, x->props.header_len);
+       top_iph->version = 6;
+       top_iph->priority = iph->priority;
+       top_iph->flow_lbl[0] = iph->flow_lbl[0];
+       top_iph->flow_lbl[1] = iph->flow_lbl[1];
+       top_iph->flow_lbl[2] = iph->flow_lbl[2];
+       top_iph->nexthdr = IPPROTO_IPV6; 
+       top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+       top_iph->hop_limit = iph->hop_limit;
+       memcpy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr, sizeof(struct in6_addr));
+       memcpy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr, sizeof(struct in6_addr));
+       skb->nh.raw = skb->data;
+       skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr);
+
+       x->curlft.bytes += skb->len;
+       x->curlft.packets++;
+
+       spin_unlock_bh(&x->lock);
+
+       if ((skb->dst = dst_pop(dst)) == NULL) { 
+               kfree_skb(skb);
+               err = -EHOSTUNREACH;
+               goto error_nolock;
+       }
+
+       return NET_XMIT_BYPASS;
+
+error_nolock:
+       kfree_skb(skb);
+       return err;
+}
+
+static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+{
+       if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 
+               return -EINVAL;
+
+       skb->mac.raw = skb->nh.raw;
+       skb->nh.raw = skb->data;
+       dst_release(skb->dst);
+       skb->dst = NULL;
+       skb->protocol = htons(ETH_P_IPV6);
+       skb->pkt_type = PACKET_HOST;
+       netif_rx(skb);
+
+       return 0;
+}
+
+static struct xfrm6_tunnel *xfrm6_tunnel_handler;
+static DECLARE_MUTEX(xfrm6_tunnel_sem);
+
+int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
+{
+       int ret;
+
+       down(&xfrm6_tunnel_sem);
+       ret = 0;
+       if (xfrm6_tunnel_handler != NULL)
+               ret = -EINVAL;
+       if (!ret)
+               xfrm6_tunnel_handler = handler;
+       up(&xfrm6_tunnel_sem);
+
+       return ret;
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_register);
+
+int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
+{
+       int ret;
+
+       down(&xfrm6_tunnel_sem);
+       ret = 0;
+       if (xfrm6_tunnel_handler != handler)
+               ret = -EINVAL;
+       if (!ret)
+               xfrm6_tunnel_handler = NULL;
+       up(&xfrm6_tunnel_sem);
+
+       synchronize_net();
+
+       return ret;
+}
+
+EXPORT_SYMBOL(xfrm6_tunnel_deregister);
+
+static int xfrm6_tunnel_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+{
+       struct sk_buff *skb = *pskb;
+       struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
+       struct xfrm_state *x = NULL;
+       struct ipv6hdr *iph = skb->nh.ipv6h;
+       int err = 0;
+       u32 spi;
+
+       /* device-like_ip6ip6_handler() */
+       if (handler) {
+               err = handler->handler(pskb, nhoffp);
+               if (!err)
+                       goto out;
+       }
+
+       spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
+       x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, 
+                       spi,
+                       IPPROTO_IPV6, AF_INET6);
+
+       if (!x)
+               goto drop;
+
+       spin_lock(&x->lock);
+
+       if (unlikely(x->km.state != XFRM_STATE_VALID))
+               goto drop_unlock;
+
+       err = xfrm6_tunnel_input(x, NULL, skb);
+       if (err)
+               goto drop_unlock;
+
+       x->curlft.bytes += skb->len;
+       x->curlft.packets++; 
+       spin_unlock(&x->lock); 
+       xfrm_state_put(x); 
+
+out:
+       return 0;
+
+drop_unlock:
+       spin_unlock(&x->lock);
+       xfrm_state_put(x);
+drop:
+       kfree_skb(skb);
+       return -1;
+}
+
+static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+                            int type, int code, int offset, __u32 info)
+{
+       struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
+
+       /* call here first for device-like ip6ip6 err handling */
+       if (handler) {
+               handler->err_handler(skb, opt, type, code, offset, info);
+               return;
+       }
+
+       /* xfrm6_tunnel native err handling */
+       switch (type) {
+       case ICMPV6_DEST_UNREACH: 
+               switch (code) {
+               case ICMPV6_NOROUTE: 
+               case ICMPV6_ADM_PROHIBITED:
+               case ICMPV6_NOT_NEIGHBOUR:
+               case ICMPV6_ADDR_UNREACH:
+               case ICMPV6_PORT_UNREACH:
+               default:
+                       X6TPRINTK3(KERN_DEBUG
+                                  "xfrm6_tunnel: Destination Unreach.\n");
+                       break;
+               }
+               break;
+       case ICMPV6_PKT_TOOBIG:
+                       X6TPRINTK3(KERN_DEBUG 
+                                  "xfrm6_tunnel: Packet Too Big.\n");
+               break;
+       case ICMPV6_TIME_EXCEED:
+               switch (code) {
+               case ICMPV6_EXC_HOPLIMIT:
+                       X6TPRINTK3(KERN_DEBUG
+                                  "xfrm6_tunnel: Too small Hoplimit.\n");
+                       break;
+               case ICMPV6_EXC_FRAGTIME:
+               default: 
+                       break;
+               }
+               break;
+       case ICMPV6_PARAMPROB:
+               switch (code) {
+               case ICMPV6_HDR_FIELD: break;
+               case ICMPV6_UNK_NEXTHDR: break;
+               case ICMPV6_UNK_OPTION: break;
+               }
+               break;
+       default:
+               break;
+       }
+       return;
+}
+
+static int xfrm6_tunnel_init_state(struct xfrm_state *x, void *args)
+{
+       if (!x->props.mode)
+               return -EINVAL;
+
+       x->props.header_len = sizeof(struct ipv6hdr);
+
+       return 0;
+}
+
+static void xfrm6_tunnel_destroy(struct xfrm_state *x)
+{
+       xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr);
+}
+
+static struct xfrm_type xfrm6_tunnel_type = {
+       .description    = "IP6IP6",
+       .owner          = THIS_MODULE,
+       .proto          = IPPROTO_IPV6,
+       .init_state     = xfrm6_tunnel_init_state,
+       .destructor     = xfrm6_tunnel_destroy,
+       .input          = xfrm6_tunnel_input,
+       .output         = xfrm6_tunnel_output,
+};
+
+static struct inet6_protocol xfrm6_tunnel_protocol = {
+       .handler        = xfrm6_tunnel_rcv,
+       .err_handler    = xfrm6_tunnel_err, 
+       .flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
+};
+
+void __init xfrm6_tunnel_init(void)
+{
+       X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
+
+       if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0) {
+               X6TPRINTK1(KERN_ERR
+                          "xfrm6_tunnel init: can't add xfrm type\n");
+               return;
+       }
+       if (inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) {
+               X6TPRINTK1(KERN_ERR
+                          "xfrm6_tunnel init(): can't add protocol\n");
+               xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
+               return;
+       }
+       if (xfrm6_tunnel_spi_init() < 0) {
+               X6TPRINTK1(KERN_ERR
+                          "xfrm6_tunnel init: failed to initialize spi\n");
+               inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6);
+               xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
+               return;
+       }
+}
+
+void __exit xfrm6_tunnel_fini(void)
+{
+       X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
+
+       xfrm6_tunnel_spi_fini();
+       if (inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0)
+               X6TPRINTK1(KERN_ERR 
+                          "xfrm6_tunnel close: can't remove protocol\n");
+       if (xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6) < 0)
+               X6TPRINTK1(KERN_ERR
+                          "xfrm6_tunnel close: can't remove xfrm type\n");
+}
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
new file mode 100644 (file)
index 0000000..70a3e8e
--- /dev/null
@@ -0,0 +1,858 @@
+/*
+ * net/sched/sch_netem.c       Network emulator
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ *
+ * Authors:    Stephen Hemminger <shemminger@osdl.org>
+ *             Catalin(ux aka Dino) BOIE <catab at umbrella dot ro>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+
+#include <net/pkt_sched.h>
+
+/*     Network emulator
+ *
+ *     This scheduler can alters spacing and order
+ *     Similar to NISTnet and BSD Dummynet.
+ */
+
+struct netem_sched_data {
+       struct Qdisc    *qdisc;
+       struct sk_buff_head delayed;
+       struct timer_list timer;
+
+       u32 latency;
+       u32 loss;
+       u32 limit;
+       u32 counter;
+       u32 gap;
+       u32 jitter;
+};
+
+/* Time stamp put into socket buffer control block */
+struct netem_skb_cb {
+       psched_time_t   time_to_send;
+};
+
+/* This is the distribution table for the normal distribution produced
+ * with NISTnet tools.
+ * The entries represent a scaled inverse of the cumulative distribution
+ * function.
+ */
+#define TABLESIZE      2048
+#define TABLEFACTOR    8192
+
+static const short disttable[TABLESIZE] = {
+       -31473,         -26739,         -25226,         -24269,
+       -23560,         -22993,         -22518,         -22109,
+       -21749,         -21426,         -21133,         -20865,
+       -20618,         -20389,         -20174,         -19972,
+       -19782,         -19601,         -19430,         -19267,
+       -19112,         -18962,         -18819,         -18681,
+       -18549,         -18421,         -18298,         -18178,
+       -18062,         -17950,         -17841,         -17735,
+       -17632,         -17532,         -17434,         -17339,
+       -17245,         -17155,         -17066,         -16979,
+       -16894,         -16811,         -16729,         -16649,
+       -16571,         -16494,         -16419,         -16345,
+       -16272,         -16201,         -16130,         -16061,
+       -15993,         -15926,         -15861,         -15796,
+       -15732,         -15669,         -15607,         -15546,
+       -15486,         -15426,         -15368,         -15310,
+       -15253,         -15196,         -15140,         -15086,
+       -15031,         -14977,         -14925,         -14872,
+       -14821,         -14769,         -14719,         -14669,
+       -14619,         -14570,         -14522,         -14473,
+       -14426,         -14379,         -14332,         -14286,
+       -14241,         -14196,         -14150,         -14106,
+       -14062,         -14019,         -13976,         -13933,
+       -13890,         -13848,         -13807,         -13765,
+       -13724,         -13684,         -13643,         -13604,
+       -13564,         -13525,         -13486,         -13447,
+       -13408,         -13370,         -13332,         -13295,
+       -13258,         -13221,         -13184,         -13147,
+       -13111,         -13075,         -13040,         -13004,
+       -12969,         -12934,         -12899,         -12865,
+       -12830,         -12796,         -12762,         -12729,
+       -12695,         -12662,         -12629,         -12596,
+       -12564,         -12531,         -12499,         -12467,
+       -12435,         -12404,         -12372,         -12341,
+       -12310,         -12279,         -12248,         -12218,
+       -12187,         -12157,         -12127,         -12097,
+       -12067,         -12038,         -12008,         -11979,
+       -11950,         -11921,         -11892,         -11863,
+       -11835,         -11806,         -11778,         -11750,
+       -11722,         -11694,         -11666,         -11639,
+       -11611,         -11584,         -11557,         -11530,
+       -11503,         -11476,         -11450,         -11423,
+       -11396,         -11370,         -11344,         -11318,
+       -11292,         -11266,         -11240,         -11214,
+       -11189,         -11164,         -11138,         -11113,
+       -11088,         -11063,         -11038,         -11013,
+       -10988,         -10964,         -10939,         -10915,
+       -10891,         -10866,         -10843,         -10818,
+       -10794,         -10770,         -10747,         -10723,
+       -10700,         -10676,         -10652,         -10630,
+       -10606,         -10583,         -10560,         -10537,
+       -10514,         -10491,         -10469,         -10446,
+       -10424,         -10401,         -10378,         -10356,
+       -10334,         -10312,         -10290,         -10267,
+       -10246,         -10224,         -10202,         -10180,
+       -10158,         -10137,         -10115,         -10094,
+       -10072,         -10051,         -10030,         -10009,
+       -9988,          -9967,          -9945,          -9925,
+       -9904,          -9883,          -9862,          -9842,
+       -9821,          -9800,          -9780,          -9760,
+       -9739,          -9719,          -9699,          -9678,
+       -9658,          -9638,          -9618,          -9599,
+       -9578,          -9559,          -9539,          -9519,
+       -9499,          -9480,          -9461,          -9441,
+       -9422,          -9402,          -9383,          -9363,
+       -9344,          -9325,          -9306,          -9287,
+       -9268,          -9249,          -9230,          -9211,
+       -9192,          -9173,          -9155,          -9136,
+       -9117,          -9098,          -9080,          -9062,
+       -9043,          -9025,          -9006,          -8988,
+       -8970,          -8951,          -8933,          -8915,
+       -8897,          -8879,          -8861,          -8843,
+       -8825,          -8807,          -8789,          -8772,
+       -8754,          -8736,          -8718,          -8701,
+       -8683,          -8665,          -8648,          -8630,
+       -8613,          -8595,          -8578,          -8561,
+       -8543,          -8526,          -8509,          -8492,
+       -8475,          -8458,          -8441,          -8423,
+       -8407,          -8390,          -8373,          -8356,
+       -8339,          -8322,          -8305,          -8289,
+       -8272,          -8255,          -8239,          -8222,
+       -8206,          -8189,          -8172,          -8156,
+       -8140,          -8123,          -8107,          -8090,
+       -8074,          -8058,          -8042,          -8025,
+       -8009,          -7993,          -7977,          -7961,
+       -7945,          -7929,          -7913,          -7897,
+       -7881,          -7865,          -7849,          -7833,
+       -7817,          -7802,          -7786,          -7770,
+       -7754,          -7739,          -7723,          -7707,
+       -7692,          -7676,          -7661,          -7645,
+       -7630,          -7614,          -7599,          -7583,
+       -7568,          -7553,          -7537,          -7522,
+       -7507,          -7492,          -7476,          -7461,
+       -7446,          -7431,          -7416,          -7401,
+       -7385,          -7370,          -7356,          -7340,
+       -7325,          -7311,          -7296,          -7281,
+       -7266,          -7251,          -7236,          -7221,
+       -7207,          -7192,          -7177,          -7162,
+       -7148,          -7133,          -7118,          -7104,
+       -7089,          -7075,          -7060,          -7046,
+       -7031,          -7016,          -7002,          -6988,
+       -6973,          -6959,          -6944,          -6930,
+       -6916,          -6901,          -6887,          -6873,
+       -6859,          -6844,          -6830,          -6816,
+       -6802,          -6788,          -6774,          -6760,
+       -6746,          -6731,          -6717,          -6704,
+       -6690,          -6675,          -6661,          -6647,
+       -6633,          -6620,          -6606,          -6592,
+       -6578,          -6564,          -6550,          -6537,
+       -6523,          -6509,          -6495,          -6482,
+       -6468,          -6454,          -6441,          -6427,
+       -6413,          -6400,          -6386,          -6373,
+       -6359,          -6346,          -6332,          -6318,
+       -6305,          -6291,          -6278,          -6264,
+       -6251,          -6238,          -6224,          -6211,
+       -6198,          -6184,          -6171,          -6158,
+       -6144,          -6131,          -6118,          -6105,
+       -6091,          -6078,          -6065,          -6052,
+       -6039,          -6025,          -6012,          -5999,
+       -5986,          -5973,          -5960,          -5947,
+       -5934,          -5921,          -5908,          -5895,
+       -5882,          -5869,          -5856,          -5843,
+       -5830,          -5817,          -5804,          -5791,
+       -5779,          -5766,          -5753,          -5740,
+       -5727,          -5714,          -5702,          -5689,
+       -5676,          -5663,          -5650,          -5638,
+       -5625,          -5612,          -5600,          -5587,
+       -5575,          -5562,          -5549,          -5537,
+       -5524,          -5512,          -5499,          -5486,
+       -5474,          -5461,          -5449,          -5436,
+       -5424,          -5411,          -5399,          -5386,
+       -5374,          -5362,          -5349,          -5337,
+       -5324,          -5312,          -5299,          -5287,
+       -5275,          -5263,          -5250,          -5238,
+       -5226,          -5213,          -5201,          -5189,
+       -5177,          -5164,          -5152,          -5140,
+       -5128,          -5115,          -5103,          -5091,
+       -5079,          -5067,          -5055,          -5043,
+       -5030,          -5018,          -5006,          -4994,
+       -4982,          -4970,          -4958,          -4946,
+       -4934,          -4922,          -4910,          -4898,
+       -4886,          -4874,          -4862,          -4850,
+       -4838,          -4826,          -4814,          -4803,
+       -4791,          -4778,          -4767,          -4755,
+       -4743,          -4731,          -4719,          -4708,
+       -4696,          -4684,          -4672,          -4660,
+       -4649,          -4637,          -4625,          -4613,
+       -4601,          -4590,          -4578,          -4566,
+       -4554,          -4543,          -4531,          -4520,
+       -4508,          -4496,          -4484,          -4473,
+       -4461,          -4449,          -4438,          -4427,
+       -4415,          -4403,          -4392,          -4380,
+       -4368,          -4357,          -4345,          -4334,
+       -4322,          -4311,          -4299,          -4288,
+       -4276,          -4265,          -4253,          -4242,
+       -4230,          -4219,          -4207,          -4196,
+       -4184,          -4173,          -4162,          -4150,
+       -4139,          -4128,          -4116,          -4105,
+       -4094,          -4082,          -4071,          -4060,
+       -4048,          -4037,          -4026,          -4014,
+       -4003,          -3992,          -3980,          -3969,
+       -3958,          -3946,          -3935,          -3924,
+       -3913,          -3901,          -3890,          -3879,
+       -3868,          -3857,          -3845,          -3834,
+       -3823,          -3812,          -3801,          -3790,
+       -3779,          -3767,          -3756,          -3745,
+       -3734,          -3723,          -3712,          -3700,
+       -3689,          -3678,          -3667,          -3656,
+       -3645,          -3634,          -3623,          -3612,
+       -3601,          -3590,          -3579,          -3568,
+       -3557,          -3545,          -3535,          -3524,
+       -3513,          -3502,          -3491,          -3480,
+       -3469,          -3458,          -3447,          -3436,
+       -3425,          -3414,          -3403,          -3392,
+       -3381,          -3370,          -3360,          -3348,
+       -3337,          -3327,          -3316,          -3305,
+       -3294,          -3283,          -3272,          -3262,
+       -3251,          -3240,          -3229,          -3218,
+       -3207,          -3197,          -3185,          -3175,
+       -3164,          -3153,          -3142,          -3132,
+       -3121,          -3110,          -3099,          -3088,
+       -3078,          -3067,          -3056,          -3045,
+       -3035,          -3024,          -3013,          -3003,
+       -2992,          -2981,          -2970,          -2960,
+       -2949,          -2938,          -2928,          -2917,
+       -2906,          -2895,          -2885,          -2874,
+       -2864,          -2853,          -2842,          -2832,
+       -2821,          -2810,          -2800,          -2789,
+       -2778,          -2768,          -2757,          -2747,
+       -2736,          -2725,          -2715,          -2704,
+       -2694,          -2683,          -2673,          -2662,
+       -2651,          -2641,          -2630,          -2620,
+       -2609,          -2599,          -2588,          -2578,
+       -2567,          -2556,          -2546,          -2535,
+       -2525,          -2515,          -2504,          -2493,
+       -2483,          -2472,          -2462,          -2451,
+       -2441,          -2431,          -2420,          -2410,
+       -2399,          -2389,          -2378,          -2367,
+       -2357,          -2347,          -2336,          -2326,
+       -2315,          -2305,          -2295,          -2284,
+       -2274,          -2263,          -2253,          -2243,
+       -2232,          -2222,          -2211,          -2201,
+       -2191,          -2180,          -2170,          -2159,
+       -2149,          -2139,          -2128,          -2118,
+       -2107,          -2097,          -2087,          -2076,
+       -2066,          -2056,          -2046,          -2035,
+       -2025,          -2014,          -2004,          -1994,
+       -1983,          -1973,          -1963,          -1953,
+       -1942,          -1932,          -1921,          -1911,
+       -1901,          -1891,          -1880,          -1870,
+       -1860,          -1849,          -1839,          -1829,
+       -1819,          -1808,          -1798,          -1788,
+       -1778,          -1767,          -1757,          -1747,
+       -1736,          -1726,          -1716,          -1706,
+       -1695,          -1685,          -1675,          -1665,
+       -1654,          -1644,          -1634,          -1624,
+       -1613,          -1603,          -1593,          -1583,
+       -1573,          -1563,          -1552,          -1542,
+       -1532,          -1522,          -1511,          -1501,
+       -1491,          -1481,          -1471,          -1461,
+       -1450,          -1440,          -1430,          -1420,
+       -1409,          -1400,          -1389,          -1379,
+       -1369,          -1359,          -1348,          -1339,
+       -1328,          -1318,          -1308,          -1298,
+       -1288,          -1278,          -1267,          -1257,
+       -1247,          -1237,          -1227,          -1217,
+       -1207,          -1196,          -1186,          -1176,
+       -1166,          -1156,          -1146,          -1135,
+       -1126,          -1115,          -1105,          -1095,
+       -1085,          -1075,          -1065,          -1055,
+       -1044,          -1034,          -1024,          -1014,
+       -1004,          -994,           -984,           -974,
+       -964,           -954,           -944,           -933,
+       -923,           -913,           -903,           -893,
+       -883,           -873,           -863,           -853,
+       -843,           -833,           -822,           -812,
+       -802,           -792,           -782,           -772,
+       -762,           -752,           -742,           -732,
+       -722,           -712,           -702,           -691,
+       -682,           -671,           -662,           -651,
+       -641,           -631,           -621,           -611,
+       -601,           -591,           -581,           -571,
+       -561,           -551,           -541,           -531,
+       -521,           -511,           -501,           -491,
+       -480,           -471,           -460,           -451,
+       -440,           -430,           -420,           -410,
+       -400,           -390,           -380,           -370,
+       -360,           -350,           -340,           -330,
+       -320,           -310,           -300,           -290,
+       -280,           -270,           -260,           -250,
+       -240,           -230,           -220,           -210,
+       -199,           -190,           -179,           -170,
+       -159,           -150,           -139,           -129,
+       -119,           -109,           -99,            -89,
+       -79,            -69,            -59,            -49,
+       -39,            -29,            -19,            -9,
+       1,              11,             21,             31,
+       41,             51,             61,             71,
+       81,             91,             101,            111,
+       121,            131,            141,            152,
+       161,            172,            181,            192,
+       202,            212,            222,            232,
+       242,            252,            262,            272,
+       282,            292,            302,            312,
+       322,            332,            342,            352,
+       362,            372,            382,            392,
+       402,            412,            422,            433,
+       442,            453,            462,            473,
+       483,            493,            503,            513,
+       523,            533,            543,            553,
+       563,            573,            583,            593,
+       603,            613,            623,            633,
+       643,            653,            664,            673,
+       684,            694,            704,            714,
+       724,            734,            744,            754,
+       764,            774,            784,            794,
+       804,            815,            825,            835,
+       845,            855,            865,            875,
+       885,            895,            905,            915,
+       925,            936,            946,            956,
+       966,            976,            986,            996,
+       1006,           1016,           1026,           1037,
+       1047,           1057,           1067,           1077,
+       1087,           1097,           1107,           1117,
+       1128,           1138,           1148,           1158,
+       1168,           1178,           1188,           1198,
+       1209,           1219,           1229,           1239,
+       1249,           1259,           1269,           1280,
+       1290,           1300,           1310,           1320,
+       1330,           1341,           1351,           1361,
+       1371,           1381,           1391,           1402,
+       1412,           1422,           1432,           1442,
+       1452,           1463,           1473,           1483,
+       1493,           1503,           1513,           1524,
+       1534,           1544,           1554,           1565,
+       1575,           1585,           1595,           1606,
+       1616,           1626,           1636,           1647,
+       1656,           1667,           1677,           1687,
+       1697,           1708,           1718,           1729,
+       1739,           1749,           1759,           1769,
+       1780,           1790,           1800,           1810,
+       1821,           1831,           1841,           1851,
+       1862,           1872,           1883,           1893,
+       1903,           1913,           1923,           1934,
+       1944,           1955,           1965,           1975,
+       1985,           1996,           2006,           2016,
+       2027,           2037,           2048,           2058,
+       2068,           2079,           2089,           2099,
+       2110,           2120,           2130,           2141,
+       2151,           2161,           2172,           2182,
+       2193,           2203,           2213,           2224,
+       2234,           2245,           2255,           2265,
+       2276,           2286,           2297,           2307,
+       2318,           2328,           2338,           2349,
+       2359,           2370,           2380,           2391,
+       2401,           2412,           2422,           2433,
+       2443,           2454,           2464,           2475,
+       2485,           2496,           2506,           2517,
+       2527,           2537,           2548,           2559,
+       2569,           2580,           2590,           2601,
+       2612,           2622,           2632,           2643,
+       2654,           2664,           2675,           2685,
+       2696,           2707,           2717,           2728,
+       2738,           2749,           2759,           2770,
+       2781,           2791,           2802,           2813,
+       2823,           2834,           2845,           2855,
+       2866,           2877,           2887,           2898,
+       2909,           2919,           2930,           2941,
+       2951,           2962,           2973,           2984,
+       2994,           3005,           3015,           3027,
+       3037,           3048,           3058,           3069,
+       3080,           3091,           3101,           3113,
+       3123,           3134,           3145,           3156,
+       3166,           3177,           3188,           3199,
+       3210,           3220,           3231,           3242,
+       3253,           3264,           3275,           3285,
+       3296,           3307,           3318,           3329,
+       3340,           3351,           3362,           3373,
+       3384,           3394,           3405,           3416,
+       3427,           3438,           3449,           3460,
+       3471,           3482,           3493,           3504,
+       3515,           3526,           3537,           3548,
+       3559,           3570,           3581,           3592,
+       3603,           3614,           3625,           3636,
+       3647,           3659,           3670,           3681,
+       3692,           3703,           3714,           3725,
+       3736,           3747,           3758,           3770,
+       3781,           3792,           3803,           3814,
+       3825,           3837,           3848,           3859,
+       3870,           3881,           3893,           3904,
+       3915,           3926,           3937,           3949,
+       3960,           3971,           3983,           3994,
+       4005,           4017,           4028,           4039,
+       4051,           4062,           4073,           4085,
+       4096,           4107,           4119,           4130,
+       4141,           4153,           4164,           4175,
+       4187,           4198,           4210,           4221,
+       4233,           4244,           4256,           4267,
+       4279,           4290,           4302,           4313,
+       4325,           4336,           4348,           4359,
+       4371,           4382,           4394,           4406,
+       4417,           4429,           4440,           4452,
+       4464,           4475,           4487,           4499,
+       4510,           4522,           4533,           4545,
+       4557,           4569,           4581,           4592,
+       4604,           4616,           4627,           4639,
+       4651,           4663,           4674,           4686,
+       4698,           4710,           4722,           4734,
+       4746,           4758,           4769,           4781,
+       4793,           4805,           4817,           4829,
+       4841,           4853,           4865,           4877,
+       4889,           4900,           4913,           4925,
+       4936,           4949,           4961,           4973,
+       4985,           4997,           5009,           5021,
+       5033,           5045,           5057,           5070,
+       5081,           5094,           5106,           5118,
+       5130,           5143,           5155,           5167,
+       5179,           5191,           5204,           5216,
+       5228,           5240,           5253,           5265,
+       5278,           5290,           5302,           5315,
+       5327,           5340,           5352,           5364,
+       5377,           5389,           5401,           5414,
+       5426,           5439,           5451,           5464,
+       5476,           5489,           5502,           5514,
+       5527,           5539,           5552,           5564,
+       5577,           5590,           5603,           5615,
+       5628,           5641,           5653,           5666,
+       5679,           5691,           5704,           5717,
+       5730,           5743,           5756,           5768,
+       5781,           5794,           5807,           5820,
+       5833,           5846,           5859,           5872,
+       5885,           5897,           5911,           5924,
+       5937,           5950,           5963,           5976,
+       5989,           6002,           6015,           6028,
+       6042,           6055,           6068,           6081,
+       6094,           6108,           6121,           6134,
+       6147,           6160,           6174,           6187,
+       6201,           6214,           6227,           6241,
+       6254,           6267,           6281,           6294,
+       6308,           6321,           6335,           6348,
+       6362,           6375,           6389,           6403,
+       6416,           6430,           6443,           6457,
+       6471,           6485,           6498,           6512,
+       6526,           6540,           6554,           6567,
+       6581,           6595,           6609,           6623,
+       6637,           6651,           6665,           6679,
+       6692,           6706,           6721,           6735,
+       6749,           6763,           6777,           6791,
+       6805,           6819,           6833,           6848,
+       6862,           6876,           6890,           6905,
+       6919,           6933,           6948,           6962,
+       6976,           6991,           7005,           7020,
+       7034,           7049,           7064,           7078,
+       7093,           7107,           7122,           7136,
+       7151,           7166,           7180,           7195,
+       7210,           7225,           7240,           7254,
+       7269,           7284,           7299,           7314,
+       7329,           7344,           7359,           7374,
+       7389,           7404,           7419,           7434,
+       7449,           7465,           7480,           7495,
+       7510,           7526,           7541,           7556,
+       7571,           7587,           7602,           7618,
+       7633,           7648,           7664,           7680,
+       7695,           7711,           7726,           7742,
+       7758,           7773,           7789,           7805,
+       7821,           7836,           7852,           7868,
+       7884,           7900,           7916,           7932,
+       7948,           7964,           7981,           7997,
+       8013,           8029,           8045,           8061,
+       8078,           8094,           8110,           8127,
+       8143,           8160,           8176,           8193,
+       8209,           8226,           8242,           8259,
+       8276,           8292,           8309,           8326,
+       8343,           8360,           8377,           8394,
+       8410,           8428,           8444,           8462,
+       8479,           8496,           8513,           8530,
+       8548,           8565,           8582,           8600,
+       8617,           8634,           8652,           8670,
+       8687,           8704,           8722,           8740,
+       8758,           8775,           8793,           8811,
+       8829,           8847,           8865,           8883,
+       8901,           8919,           8937,           8955,
+       8974,           8992,           9010,           9029,
+       9047,           9066,           9084,           9103,
+       9121,           9140,           9159,           9177,
+       9196,           9215,           9234,           9253,
+       9272,           9291,           9310,           9329,
+       9349,           9368,           9387,           9406,
+       9426,           9445,           9465,           9484,
+       9504,           9524,           9544,           9563,
+       9583,           9603,           9623,           9643,
+       9663,           9683,           9703,           9723,
+       9744,           9764,           9785,           9805,
+       9826,           9846,           9867,           9888,
+       9909,           9930,           9950,           9971,
+       9993,           10013,          10035,          10056,
+       10077,          10099,          10120,          10142,
+       10163,          10185,          10207,          10229,
+       10251,          10273,          10294,          10317,
+       10339,          10361,          10384,          10406,
+       10428,          10451,          10474,          10496,
+       10519,          10542,          10565,          10588,
+       10612,          10635,          10658,          10682,
+       10705,          10729,          10752,          10776,
+       10800,          10824,          10848,          10872,
+       10896,          10921,          10945,          10969,
+       10994,          11019,          11044,          11069,
+       11094,          11119,          11144,          11169,
+       11195,          11221,          11246,          11272,
+       11298,          11324,          11350,          11376,
+       11402,          11429,          11456,          11482,
+       11509,          11536,          11563,          11590,
+       11618,          11645,          11673,          11701,
+       11728,          11756,          11785,          11813,
+       11842,          11870,          11899,          11928,
+       11957,          11986,          12015,          12045,
+       12074,          12104,          12134,          12164,
+       12194,          12225,          12255,          12286,
+       12317,          12348,          12380,          12411,
+       12443,          12475,          12507,          12539,
+       12571,          12604,          12637,          12670,
+       12703,          12737,          12771,          12804,
+       12839,          12873,          12907,          12942,
+       12977,          13013,          13048,          13084,
+       13120,          13156,          13192,          13229,
+       13267,          13304,          13341,          13379,
+       13418,          13456,          13495,          13534,
+       13573,          13613,          13653,          13693,
+       13734,          13775,          13817,          13858,
+       13901,          13943,          13986,          14029,
+       14073,          14117,          14162,          14206,
+       14252,          14297,          14343,          14390,
+       14437,          14485,          14533,          14582,
+       14631,          14680,          14731,          14782,
+       14833,          14885,          14937,          14991,
+       15044,          15099,          15154,          15210,
+       15266,          15324,          15382,          15441,
+       15500,          15561,          15622,          15684,
+       15747,          15811,          15877,          15943,
+       16010,          16078,          16148,          16218,
+       16290,          16363,          16437,          16513,
+       16590,          16669,          16749,          16831,
+       16915,          17000,          17088,          17177,
+       17268,          17362,          17458,          17556,
+       17657,          17761,          17868,          17977,
+       18090,          18207,          18328,          18452,
+       18581,          18715,          18854,          18998,
+       19149,          19307,          19472,          19645,
+       19828,          20021,          20226,          20444,
+       20678,          20930,          21204,          21503,
+       21835,          22206,          22630,          23124,
+       23721,          24478,          25529,          27316,
+};
+
+/* tabledist - return a pseudo-randomly distributed value with mean mu and
+ * std deviation sigma.  Uses table lookup to approximate the desired
+ * distribution, and a uniformly-distributed pseudo-random source.
+ */
+static inline int tabledist(int mu, int sigma)
+{
+       int x;
+       int index;
+       int sigmamod, sigmadiv;
+
+       if (sigma == 0)
+               return mu;
+
+       index = (net_random() & (TABLESIZE-1));
+       sigmamod = sigma%TABLEFACTOR;
+       sigmadiv = sigma/TABLEFACTOR;
+       x = sigmamod*disttable[index];
+
+       if (x >= 0)
+               x += TABLEFACTOR/2;
+       else
+               x -= TABLEFACTOR/2;
+
+       x /= TABLEFACTOR;
+       x += sigmadiv*disttable[index];
+       x += mu;
+       return x;
+}
+
+/* Enqueue packets with underlying discipline (fifo)
+ * but mark them with current time first.
+ */
+static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+       struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+       struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb;
+       psched_time_t now;
+       long delay;
+
+       pr_debug("netem_enqueue skb=%p @%lu\n", skb, jiffies);
+
+       /* Random packet drop 0 => none, ~0 => all */
+       if (q->loss && q->loss >= net_random()) {
+               sch->stats.drops++;
+               return 0;       /* lie about loss so TCP doesn't know */
+       }
+
+
+       /* If doing simple delay then gap == 0 so all packets
+        * go into the delayed holding queue
+        * otherwise if doing out of order only "1 out of gap"
+        * packets will be delayed.
+        */
+       if (q->counter < q->gap) {
+               int ret;
+
+               ++q->counter;
+               ret = q->qdisc->enqueue(skb, q->qdisc);
+               if (ret)
+                       sch->stats.drops++;
+               return ret;
+       }
+       
+       q->counter = 0;
+       
+       PSCHED_GET_TIME(now);
+       if (q->jitter) 
+               delay = tabledist(q->latency, q->jitter);
+       else
+               delay = q->latency;
+
+       PSCHED_TADD2(now, delay, cb->time_to_send);
+       
+       /* Always queue at tail to keep packets in order */
+       __skb_queue_tail(&q->delayed, skb);
+       sch->q.qlen++;
+       sch->stats.bytes += skb->len;
+       sch->stats.packets++;
+       return 0;
+}
+
+/* Requeue packets but don't change time stamp */
+static int netem_requeue(struct sk_buff *skb, struct Qdisc *sch)
+{
+       struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+       int ret;
+
+       if ((ret = q->qdisc->ops->requeue(skb, q->qdisc)) == 0)
+               sch->q.qlen++;
+
+       return ret;
+}
+
+static unsigned int netem_drop(struct Qdisc* sch)
+{
+       struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+       unsigned int len;
+
+       if ((len = q->qdisc->ops->drop(q->qdisc)) != 0) {
+               sch->q.qlen--;
+               sch->stats.drops++;
+       }
+       return len;
+}
+
+/* Dequeue packet.
+ *  Move all packets that are ready to send from the delay holding
+ *  list to the underlying qdisc, then just call dequeue
+ */
+static struct sk_buff *netem_dequeue(struct Qdisc *sch)
+{
+       struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+       struct sk_buff *skb;
+       psched_time_t now;
+
+       PSCHED_GET_TIME(now);
+       while ((skb = skb_peek(&q->delayed)) != NULL) {
+               const struct netem_skb_cb *cb
+                       = (const struct netem_skb_cb *)skb->cb;
+               long delay 
+                       = PSCHED_US2JIFFIE(PSCHED_TDIFF(cb->time_to_send, now));
+               pr_debug("netem_dequeue: delay queue %p@%lu %ld\n",
+                        skb, jiffies, delay);
+
+               /* if more time remaining? */
+               if (delay > 0) {
+                       mod_timer(&q->timer, jiffies + delay);
+                       break;
+               }
+               __skb_unlink(skb, &q->delayed);
+
+               if (q->qdisc->enqueue(skb, q->qdisc))
+                       sch->stats.drops++;
+       }
+
+       skb = q->qdisc->dequeue(q->qdisc);
+       if (skb) 
+               sch->q.qlen--;
+       return skb;
+}
+
+static void netem_watchdog(unsigned long arg)
+{
+       struct Qdisc *sch = (struct Qdisc *)arg;
+
+       pr_debug("netem_watchdog: fired @%lu\n", jiffies);
+       netif_schedule(sch->dev);
+}
+
+static void netem_reset(struct Qdisc *sch)
+{
+       struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+
+       qdisc_reset(q->qdisc);
+       skb_queue_purge(&q->delayed);
+
+       sch->q.qlen = 0;
+       del_timer_sync(&q->timer);
+}
+
+static int set_fifo_limit(struct Qdisc *q, int limit)
+{
+        struct rtattr *rta;
+       int ret = -ENOMEM;
+
+       rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL);
+       if (rta) {
+               rta->rta_type = RTM_NEWQDISC;
+               rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt)); 
+               ((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit;
+               
+               ret = q->ops->change(q, rta);
+               kfree(rta);
+       }
+       return ret;
+}
+
+static int netem_change(struct Qdisc *sch, struct rtattr *opt)
+{
+       struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+       struct tc_netem_qopt *qopt = RTA_DATA(opt);
+       struct Qdisc *child;
+       int ret;
+
+       if (opt->rta_len < RTA_LENGTH(sizeof(*qopt)))
+               return -EINVAL;
+
+       child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+       if (!child)
+               return -EINVAL;
+
+       ret = set_fifo_limit(child, qopt->limit);
+       if (ret) {
+               qdisc_destroy(child);
+               return ret;
+       }
+
+       sch_tree_lock(sch);
+       if (child) {
+               child = xchg(&q->qdisc, child);
+               if (child != &noop_qdisc)
+                       qdisc_destroy(child);
+       
+               q->latency = qopt->latency;
+               q->jitter = qopt->jitter;
+               q->limit = qopt->limit;
+               q->gap = qopt->gap;
+               q->loss = qopt->loss;
+       }
+       sch_tree_unlock(sch);
+
+       return 0;
+}
+
+static int netem_init(struct Qdisc *sch, struct rtattr *opt)
+{
+       struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+
+       if (!opt)
+               return -EINVAL;
+
+       skb_queue_head_init(&q->delayed);
+       q->qdisc = &noop_qdisc;
+
+       init_timer(&q->timer);
+       q->timer.function = netem_watchdog;
+       q->timer.data = (unsigned long) sch;
+       q->counter = 0;
+
+       return netem_change(sch, opt);
+}
+
+static void netem_destroy(struct Qdisc *sch)
+{
+       struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+
+       del_timer_sync(&q->timer);
+}
+
+static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+       struct netem_sched_data *q = (struct netem_sched_data *)sch->data;
+       unsigned char    *b = skb->tail;
+       struct tc_netem_qopt qopt;
+
+       qopt.latency = q->latency;
+       qopt.jitter = q->jitter;
+       qopt.limit = sch->dev->tx_queue_len;
+       qopt.loss = q->loss;
+       qopt.gap = q->gap;
+
+       RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
+
+       return skb->len;
+
+rtattr_failure:
+       skb_trim(skb, b - skb->data);
+       return -1;
+}
+
+static struct Qdisc_ops netem_qdisc_ops = {
+       .id             =       "netem",
+       .priv_size      =       sizeof(struct netem_sched_data),
+       .enqueue        =       netem_enqueue,
+       .dequeue        =       netem_dequeue,
+       .requeue        =       netem_requeue,
+       .drop           =       netem_drop,
+       .init           =       netem_init,
+       .reset          =       netem_reset,
+       .destroy        =       netem_destroy,
+       .change         =       netem_change,
+       .dump           =       netem_dump,
+       .owner          =       THIS_MODULE,
+};
+
+
+static int __init netem_module_init(void)
+{
+       return register_qdisc(&netem_qdisc_ops);
+}
+static void __exit netem_module_exit(void)
+{
+       unregister_qdisc(&netem_qdisc_ops);
+}
+module_init(netem_module_init)
+module_exit(netem_module_exit)
+MODULE_LICENSE("GPL");
diff --git a/scripts/modsign/Makefile b/scripts/modsign/Makefile
new file mode 100644 (file)
index 0000000..947f5f9
--- /dev/null
@@ -0,0 +1,27 @@
+# Set the following to `true' to make a debuggable build.
+# Leave this set to `false' for production use.
+DEBUG = true
+
+
+ROOT =         mod-extract
+VERSION =      0.1
+INSTALL_DIR =  /usr/local/bin
+RELEASE_NAME = $(ROOT)-$(VERSION)
+
+CC = gcc
+
+INCLUDES = 
+CFLAGS = -g -O -Wall
+
+OBJS = mod-extract.o
+
+all: $(ROOT)
+
+$(ROOT): $(OBJS)
+       $(CC) $(LDFLAGS) -o $(ROOT) $(OBJS) -lbfd -liberty $(LIB_OBJS) $(ARCH_LIB_OBJS)
+
+.c.o:
+       $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@
+
+clean:
+       -rm $(OBJS) $(ROOT)
diff --git a/scripts/modsign/mod-extract.c b/scripts/modsign/mod-extract.c
new file mode 100644 (file)
index 0000000..f8502e7
--- /dev/null
@@ -0,0 +1,109 @@
+
+
+
+#include <errno.h>
+#include <error.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <bfd.h>
+
+/* This should be set in a Makefile somehow */
+#define TARGET "i686-pc-linux-gnu"
+
+static FILE *out;
+
+static void dump_data(bfd *abfd)
+{
+       asection *section;
+       bfd_byte *data = 0;
+       bfd_size_type size;
+       bfd_size_type addr_offset;
+       bfd_size_type stop_offset;
+       unsigned int opb = bfd_octets_per_byte(abfd);
+       unsigned int cksum;
+
+       for (section = abfd->sections; section != NULL; section = section->next) {
+               if (section->flags & SEC_HAS_CONTENTS) {
+                       if (bfd_section_size(abfd, section) == 0)
+                               continue;
+
+                       /* We only care about sections with "text" or "data" in their names */
+                       if ((strstr(section->name, "text") == NULL) &&
+                           (strstr(section->name, "data") == NULL))
+                               continue;
+
+                       cksum = 0;
+
+                       size = bfd_section_size(abfd, section) / opb;
+
+                       printf("Contents of section %s size %lu", section->name, size);
+
+                       data = (bfd_byte *) malloc(size);
+
+                       bfd_get_section_contents(abfd, section, (PTR) data, 0, size);
+
+                       stop_offset = size;
+
+                       printf(" idata %02x%02x%02x%02x", data[0], data[1], data[2], data[3]);
+
+                       for (addr_offset = 0; addr_offset < stop_offset; ++addr_offset) {
+                               cksum += (unsigned int) data[addr_offset];
+                               fputc(data[addr_offset], out);
+                       }
+                       free (data);
+
+                       printf(" checksum %08x\n", cksum);
+               }
+       }
+}
+
+void set_default_bfd_target(void)
+{
+       const char *target = TARGET;
+
+       if (!bfd_set_default_target(target))
+               fprintf(stderr, "can't set BFD default target to `%s': %s", target, bfd_errmsg (bfd_get_error ()));
+}
+
+int main (int argc, char *argv[])
+{
+       char *in_file;
+       char *out_file;
+       bfd *file;
+       char **matching;
+
+       if (argc != 3) {
+               fprintf(stderr, "%s [infile] [outfile]\n", argv[0]);
+               exit(1);
+       }
+
+       in_file = argv[1];
+       out_file = argv[2];
+
+       bfd_init();
+       set_default_bfd_target();
+
+
+//     file = bfd_openr(in_file, "elf32-i386");
+       file = bfd_openr(in_file, NULL);
+       if (file == NULL) {
+               fprintf(stderr, "error \"%s\" trying to open %s\n", strerror(errno), in_file);
+               exit(1);
+       }
+
+       out = fopen(out_file, "w");
+       if (out == NULL) {
+               fprintf(stderr, "error \"%s\" trying to create %s\n", strerror(errno), out_file);
+               exit(1);
+       }
+
+       if (bfd_check_format_matches(file, bfd_object, &matching)) {
+               dump_data (file);
+       }
+
+       fclose(out);
+
+       return 0;
+}
diff --git a/scripts/modsign/mod-extract.sh b/scripts/modsign/mod-extract.sh
new file mode 100644 (file)
index 0000000..a08cb08
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+sections=`objdump -h $1 |
+egrep \(text\|data\) |
+    while read sid sname stuff
+do
+  echo $sname
+done`
+
+echo $sections
+
+#objcopy -O binary $sections $1 x.raw
+objcopy -O binary -j .text $1 x.raw
+
+echo -n >x.raw
+for i in $sections
+do
+  objcopy -O binary -j $i $1 x.raw.part
+  cat x.raw.part >>x.raw
+done
+rm x.raw.part
+mv x.raw $2
diff --git a/scripts/modsign/modsign.sh b/scripts/modsign/modsign.sh
new file mode 100644 (file)
index 0000000..4d3eaa2
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+
+if [ $# = "0" ] ; then
+       echo
+#      echo "usage: $0 <module_to_sign> <key_name>"
+       echo "usage: $0 <module_to_sign>"
+       echo
+       exit 1
+fi
+
+module=$1
+#key=$2
+
+# strip out only the sections that we care about
+sh scripts/modsign/mod-extract.sh $module $module.out
+
+# sign the sections
+#gpg --no-greeting --default-key $key -b $module.out
+gpg --no-greeting --no-default-keyring --secret-keyring ../kernel.sec --keyring ../kernel.pub -b $module.out
+
+# check the signature
+#gpg --verify rxrpc.ko.out.sig rxrpc.ko.out
+
+## sha1 the sections
+#sha1sum $module.out | awk "{print \$1}" > $module.sha1
+#
+## encrypt the sections
+#gpg --no-greeting -e -o - -r $key $module.sha1 > $module.crypt
+
+# add the encrypted data to the module
+#objcopy --add-section module_sig=$module.crypt $module $module.signed
+objcopy --add-section module_sig=$module.out.sig $module $module.signed
+objcopy --set-section-flags module_sig=alloc $module.signed
+rm -f $module.out*
diff --git a/scripts/package/Makefile b/scripts/package/Makefile
new file mode 100644 (file)
index 0000000..f3df4bc
--- /dev/null
@@ -0,0 +1,71 @@
+# Makefile for the different targets used to generate full packages of a kernel
+# It uses the generic clean infrastructure of kbuild
+
+# Ignore the following files/directories during tar operation
+TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS
+
+
+# RPM target
+# ---------------------------------------------------------------------------
+# The rpm target generates two rpm files:
+# /usr/src/packages/SRPMS/kernel-2.6.7rc2-1.src.rpm
+# /usr/src/packages/RPMS/i386/kernel-2.6.7rc2-1.<arch>.rpm
+# The src.rpm files includes all source for the kernel being built
+# The <arch>.rpm includes kernel configuration, modules etc.
+#
+# Process to create the rpm files
+# a) clean the kernel
+# b) Generate .spec file
+# c) Build a tar ball, using symlink to make kernel version
+#    first entry in the path
+# d) and pack the result to a tar.gz file
+# e) generate the rpm files, based on kernel.spec
+# - Use /. to avoid tar packing just the symlink
+
+# Do we have rpmbuild, otherwise fall back to the older rpm
+RPM := $(shell if [ -x "/usr/bin/rpmbuild" ]; then echo rpmbuild; \
+                  else echo rpm; fi)
+
+# Remove hyphens since they have special meaning in RPM filenames
+KERNELPATH := kernel-$(subst -,,$(KERNELRELEASE))
+MKSPEC     := $(srctree)/scripts/package/mkspec
+PREV       := set -e; cd ..;
+
+.PHONY: rpm-pkg rpm
+
+$(objtree)/kernel.spec: $(MKSPEC)
+       $(CONFIG_SHELL) $(MKSPEC) > $@
+
+rpm-pkg rpm: $(objtree)/kernel.spec
+       $(MAKE) clean
+       $(PREV) ln -sf $(srctree) $(KERNELPATH)
+       $(PREV) tar -cz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/.
+       $(PREV) rm $(KERNELPATH)
+
+       set -e; \
+       $(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version
+       set -e; \
+       mv -f $(objtree)/.tmp_version $(objtree)/.version
+
+       $(RPM) --target $(UTS_MACHINE) -ta ../$(KERNELPATH).tar.gz
+       rm ../$(KERNELPATH).tar.gz
+
+clean-rule +=  rm -f $(objtree)/kernel.spec
+
+# Deb target
+# ---------------------------------------------------------------------------
+#
+.PHONY: deb-pkg
+deb-pkg:
+       $(MAKE)
+       $(CONFIG_SHELL) $(srctree)/scripts/package/builddeb
+
+clean-rule += && rm -rf $(objtree)/debian/
+
+
+# Help text displayed when executing 'make help'
+# ---------------------------------------------------------------------------
+help:
+       @echo  '  rpm-pkg         - Build the kernel as an RPM package'
+       @echo  '  deb-pkg         - Build the kernel as an deb package'
+
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
new file mode 100644 (file)
index 0000000..968a0a7
--- /dev/null
@@ -0,0 +1,79 @@
+#!/bin/sh
+#
+# builddeb 1.2
+# Copyright 2003 Wichert Akkerman <wichert@wiggy.net>
+#
+# Simple script to generate a deb package for a Linux kernel. All the
+# complexity of what to do with a kernel after it is installer or removed
+# is left to other scripts and packages: they can install scripts in the
+# /etc/kernel/{pre,post}{inst,rm}.d/ directories that will be called on
+# package install and removal.
+
+set -e
+
+# Some variables and settings used throughout the script
+version="$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+tmpdir="$objtree/debian/tmp"
+
+# Setup the directory structure
+rm -rf "$tmpdir"
+mkdir -p "$tmpdir/DEBIAN" "$tmpdir/lib" "$tmpdir/boot"
+
+# Build and install the kernel
+cp System.map "$tmpdir/boot/System.map-$version"
+cp .config "$tmpdir/boot/config-$version"
+cp $KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version"
+
+if grep -q '^CONFIG_MODULES=y' .config ; then
+       INSTALL_MOD_PATH="$tmpdir" make modules_install
+fi
+
+# Install the maintainer scripts
+for script in postinst postrm preinst prerm ; do
+       mkdir -p "$tmpdir/etc/kernel/$script.d"
+       cat <<EOF > "$tmpdir/DEBIAN/$script"
+#!/bin/sh
+
+set -e
+
+test -d /etc/kernel/$script.d && run-parts --arg="$version" /etc/kernel/$script.d
+exit 0
+EOF
+       chmod 755 "$tmpdir/DEBIAN/$script"
+done
+
+name="Kernel Compiler <$(id -nu)@$(hostname -f)>"
+# Generate a simple changelog template
+cat <<EOF > debian/changelog
+linux ($version) unstable; urgency=low
+
+  * A standard release
+
+ -- $name  $(date -R)
+EOF
+
+# Generate a control file
+cat <<EOF > debian/control
+Source: linux
+Section: base
+Priority: optional
+Maintainer: $name
+Standards-Version: 3.6.1
+
+Package: linux-$version
+Architecture: any
+Description: Linux kernel, version $version
+ This package contains the Linux kernel, modules and corresponding other
+ files version $version.
+EOF
+
+# Fix some ownership and permissions
+chown -R root:root "$tmpdir"
+chmod -R go-w "$tmpdir"
+
+# Perform the final magic
+dpkg-gencontrol -isp
+dpkg --build "$tmpdir" ..
+
+exit 0
+
diff --git a/scripts/package/mkspec b/scripts/package/mkspec
new file mode 100644 (file)
index 0000000..3ecfc23
--- /dev/null
@@ -0,0 +1,63 @@
+#!/bin/sh
+#
+#      Output a simple RPM spec file that uses no fancy features requring
+#      RPM v4. This is intended to work with any RPM distro.
+#
+#      The only gothic bit here is redefining install_post to avoid
+#      stripping the symbols from files in the kernel which we want
+#
+#      Patched for non-x86 by Opencon (L) 2002 <opencon@rio.skydome.net>
+#
+
+# starting to output the spec
+if [ "`grep CONFIG_DRM=y .config | cut -f2 -d\=`" = "y" ]; then
+       PROVIDES=kernel-drm
+fi
+
+PROVIDES="$PROVIDES kernel-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+
+echo "Name: kernel"
+echo "Summary: The Linux Kernel"
+echo "Version: "$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION | sed -e "s/-//g"
+# we need to determine the NEXT version number so that uname and
+# rpm -q will agree
+echo "Release: `. $srctree/scripts/mkversion`"
+echo "License: GPL"
+echo "Group: System Environment/Kernel"
+echo "Vendor: The Linux Community"
+echo "URL: http://www.kernel.org"
+echo -n "Source: kernel-$VERSION.$PATCHLEVEL.$SUBLEVEL"
+echo "$EXTRAVERSION.tar.gz" | sed -e "s/-//g"
+echo "BuildRoot: /var/tmp/%{name}-%{PACKAGE_VERSION}-root"
+echo "Provides: $PROVIDES"
+echo "%define __spec_install_post /usr/lib/rpm/brp-compress || :"
+echo "%define debug_package %{nil}"
+echo ""
+echo "%description"
+echo "The Linux Kernel, the operating system core itself"
+echo ""
+echo "%prep"
+echo "%setup -q"
+echo ""
+echo "%build"
+echo "make clean && make"
+echo ""
+echo "%install"
+echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib $RPM_BUILD_ROOT/lib/modules'
+
+echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make modules_install'
+echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+
+echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+
+echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo ""
+echo "%clean"
+echo '#echo -rf $RPM_BUILD_ROOT'
+echo ""
+echo "%files"
+echo '%defattr (-, root, root)'
+echo "%dir /lib/modules"
+echo "/lib/modules/$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo "/boot/*"
+echo ""