[oe] [PATCH 3/6] Add kernel support for the Technologic Systems TS7500 ARM SBCs
UDel V2G Team
v2g.udel at gmail.com
Wed Mar 30 14:07:07 UTC 2011
* Adds a custom kernel with all the patches for the Cavium FA 526 core
Signed-off-by: UDel V2G Team <v2g.udel at gmail.com>
---
.../ts75xx/cavium-userspace-irq-2.6.35.patch | 181 +
recipes/linux/linux-ts75xx-2.6.35/ts75xx/defconfig | 1603 +
.../linux/linux-ts75xx-2.6.35/ts75xx/defconfig.bak | 1521 +
.../ts75xx/ts7500-2.6.35.11.patch |85527 ++++++++++++++++++++
.../ts75xx/unionfs-2.5.8_for_2.6.35.11.patch |11286 +++
recipes/linux/linux-ts75xx_2.6.35.bb | 141 +
6 files changed, 100259 insertions(+), 0 deletions(-)
create mode 100644 recipes/linux/linux-ts75xx-2.6.35/ts75xx/cavium-userspace-irq-2.6.35.patch
create mode 100644 recipes/linux/linux-ts75xx-2.6.35/ts75xx/defconfig
create mode 100644 recipes/linux/linux-ts75xx-2.6.35/ts75xx/defconfig.bak
create mode 100644 recipes/linux/linux-ts75xx-2.6.35/ts75xx/ts7500-2.6.35.11.patch
create mode 100644 recipes/linux/linux-ts75xx-2.6.35/ts75xx/unionfs-2.5.8_for_2.6.35.11.patch
create mode 100644 recipes/linux/linux-ts75xx_2.6.35.bb
diff --git a/recipes/linux/linux-ts75xx-2.6.35/ts75xx/cavium-userspace-irq-2.6.35.patch b/recipes/linux/linux-ts75xx-2.6.35/ts75xx/cavium-userspace-irq-2.6.35.patch
new file mode 100644
index 0000000..5240ca9
--- /dev/null
+++ b/recipes/linux/linux-ts75xx-2.6.35/ts75xx/cavium-userspace-irq-2.6.35.patch
@@ -0,0 +1,181 @@
+--- linux-2.6.35/kernel/irq/proc.c 2010-08-01 18:11:14.000000000 -0400
++++ linux-2.6.35.11-ts7500/kernel/irq/proc.c 2011-02-27 01:18:59.000000000 -0500
+@@ -11,6 +11,7 @@
+ #include <linux/proc_fs.h>
+ #include <linux/seq_file.h>
+ #include <linux/interrupt.h>
++#include <linux/poll.h>
+
+ #include "internals.h"
+
+@@ -265,21 +266,165 @@
+
+ #define MAX_NAMELEN 10
+
++struct irq_proc {
++ unsigned long irq;
++ wait_queue_head_t q;
++ atomic_t count;
++ char devname[TASK_COMM_LEN];
++};
++
++static irqreturn_t irq_proc_irq_handler(int irq, void *vidp)
++{
++ struct irq_proc *idp = (struct irq_proc *)vidp;
++ unsigned long stamp;
++
++ BUG_ON(idp->irq != irq);
++
++ disable_irq_nosync(irq);
++ atomic_inc(&idp->count);
++
++ wake_up(&idp->q);
++ return IRQ_HANDLED;
++}
++
++
++/*
++ * Signal to userspace an interrupt has occured.
++ */
++static ssize_t irq_proc_read(struct file *filp, char __user *bufp, size_t len, loff_t *ppos)
++{
++ struct irq_proc *ip = (struct irq_proc *)filp->private_data;
++ struct irq_desc *idp = irq_desc + ip->irq;
++ int pending;
++
++ DEFINE_WAIT(wait);
++
++ if (len < sizeof(int))
++ return -EINVAL;
++
++ pending = atomic_read(&ip->count);
++ if (pending == 0) {
++ if (idp->status & IRQ_DISABLED)
++ enable_irq(ip->irq);
++ if (filp->f_flags & O_NONBLOCK)
++ return -EWOULDBLOCK;
++ }
++
++ while (pending == 0) {
++ prepare_to_wait(&ip->q, &wait, TASK_INTERRUPTIBLE);
++ pending = atomic_read(&ip->count);
++ if (pending == 0)
++ schedule();
++ finish_wait(&ip->q, &wait);
++ if (signal_pending(current))
++ return -ERESTARTSYS;
++ }
++
++ if (copy_to_user(bufp, &pending, sizeof pending))
++ return -EFAULT;
++
++ *ppos += sizeof pending;
++
++ atomic_sub(pending, &ip->count);
++ return sizeof pending;
++}
++
++
++static int irq_proc_open(struct inode *inop, struct file *filp)
++{
++ struct irq_proc *ip;
++ struct proc_dir_entry *ent = PDE(inop);
++ int error;
++
++ ip = kmalloc(sizeof *ip, GFP_KERNEL);
++ if (ip == NULL)
++ return -ENOMEM;
++
++ memset(ip, 0, sizeof(*ip));
++ strcpy(ip->devname, current->comm);
++ init_waitqueue_head(&ip->q);
++ atomic_set(&ip->count, 0);
++ ip->irq = (unsigned long)ent->data;
++
++ error = request_irq(ip->irq,
++ irq_proc_irq_handler,
++ 0,
++ ip->devname,
++ ip);
++ if (error < 0) {
++ kfree(ip);
++ return error;
++ }
++ filp->private_data = (void *)ip;
++
++ return 0;
++}
++
++static int irq_proc_release(struct inode *inop, struct file *filp)
++{
++ struct irq_proc *ip = (struct irq_proc *)filp->private_data;
++
++ free_irq(ip->irq, ip);
++ filp->private_data = NULL;
++ kfree(ip);
++ return 0;
++}
++
++static unsigned int irq_proc_poll(struct file *filp, struct poll_table_struct *wait)
++{
++ struct irq_proc *ip = (struct irq_proc *)filp->private_data;
++ struct irq_desc *idp = irq_desc + ip->irq;
++
++ if (atomic_read(&ip->count) > 0)
++ return POLLIN | POLLRDNORM; /* readable */
++
++ /* if interrupts disabled and we don't have one to process... */
++ if (idp->status & IRQ_DISABLED)
++ enable_irq(ip->irq);
++
++ poll_wait(filp, &ip->q, wait);
++
++ if (atomic_read(&ip->count) > 0)
++ return POLLIN | POLLRDNORM; /* readable */
++
++ return 0;
++}
++
++static struct file_operations irq_proc_file_operations = {
++ .read = irq_proc_read,
++ .open = irq_proc_open,
++ .release = irq_proc_release,
++ .poll = irq_proc_poll,
++};
++
+ void register_irq_proc(unsigned int irq, struct irq_desc *desc)
+ {
++ struct proc_dir_entry *entry;
+ char name [MAX_NAMELEN];
+
+- if (!root_irq_dir || (desc->chip == &no_irq_chip) || desc->dir)
++ if (!root_irq_dir)
+ return;
+
+ memset(name, 0, MAX_NAMELEN);
+ sprintf(name, "%d", irq);
+
+ /* create /proc/irq/1234 */
+- desc->dir = proc_mkdir(name, root_irq_dir);
+- if (!desc->dir)
+- return;
+-
++ if (!irq_desc[irq].dir) {
++ /* create /proc/irq/1234 */
++ irq_desc[irq].dir = proc_mkdir(name, root_irq_dir);
++
++ /*
++ * Create handles for user-mode interrupt handlers
++ * if the kernel hasn't already grabbed the IRQ
++ */
++ entry = create_proc_entry("irq", 0600, irq_desc[irq].dir);
++ if (entry) {
++ entry->data = (void *)(unsigned long)irq;
++ entry->read_proc = NULL;
++ entry->write_proc = NULL;
++ entry->proc_fops = &irq_proc_file_operations;
++ }
++ }
+ #ifdef CONFIG_SMP
+ /* create /proc/irq/<irq>/smp_affinity */
+ proc_create_data("smp_affinity", 0600, desc->dir,
diff --git a/recipes/linux/linux-ts75xx-2.6.35/ts75xx/defconfig b/recipes/linux/linux-ts75xx-2.6.35/ts75xx/defconfig
new file mode 100644
index 0000000..3423e40
--- /dev/null
+++ b/recipes/linux/linux-ts75xx-2.6.35/ts75xx/defconfig
@@ -0,0 +1,1603 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.35.11
+# Wed Mar 23 14:22:38 2011
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_TIME=y
+# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION="${LOCALVERSION}"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_LZO is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_STR9100 is not set
+CONFIG_ARCH_STR8100=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CNS3XXX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_NUC93X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P6440 is not set
+# CONFIG_ARCH_S5P6442 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_PLAT_SPEAR is not set
+CONFIG_CONSOLE_BAUD_RATE=115200
+
+#
+# STR8100 Options
+#
+CONFIG_VIC_INTERRUPT=y
+# CONFIG_STR8100_DRAM_16M is not set
+# CONFIG_STR8100_DRAM_32M is not set
+CONFIG_STR8100_DRAM_64M=y
+CONFIG_STR8100_PCI33M=y
+# CONFIG_STR8100_PCI66M is not set
+# CONFIG_STR8100_DMA is not set
+# CONFIG_STR8100_HSDMA is not set
+CONFIG_STR8100_INFO=y
+# CONFIG_STR8100_USBD_REBOOT_INTHANDLER is not set
+# CONFIG_STR8100_I2S is not set
+# CONFIG_STR8100_I2S_DEMO is not set
+# CONFIG_STR8100_I2S_WM8772_DEMO is not set
+# CONFIG_LE88221_CONTROL is not set
+# CONFIG_STR8100_PCM_LEGERITY_2PHONE_DEMO is not set
+# CONFIG_STR8100_RTC is not set
+CONFIG_STR8100_GPIO=y
+CONFIG_STR8100_GPIO_INTERRUPT=y
+# CONFIG_STR8100_GPIO_GENERIC_INTERFACE is not set
+
+#
+# Flash MAP
+#
+# CONFIG_STR8100_FLASH_PART is not set
+
+#
+# Third Party Support
+#
+# CONFIG_STR8100_EWC_SUPPORT is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_FA526=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_CACHE_FA=y
+CONFIG_CPU_COPY_FA=y
+CONFIG_CPU_TLB_FA=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+CONFIG_CPU_FA_BTB=y
+# CONFIG_CPU_FA_WB_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+
+#
+# Bus support
+#
+CONFIG_PCI=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/ram0 init=/linuxrc console=/dev/ttyS0,115200 lpj=958464 debug"
+# CONFIG_CMDLINE_FORCE is not set
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+CONFIG_FPE_FASTFPE=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+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_IP_MROUTE 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_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CT_PROTO_DCCP is not set
+CONFIG_NF_CT_PROTO_GRE=m
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CT_PROTO_UDPLITE is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+# CONFIG_NF_CONNTRACK_FTP is not set
+# CONFIG_NF_CONNTRACK_H323 is not set
+# CONFIG_NF_CONNTRACK_IRC is not set
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+CONFIG_NF_CONNTRACK_PPTP=m
+# CONFIG_NF_CONNTRACK_SANE is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+# CONFIG_NF_CONNTRACK_TFTP is not set
+# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=m
+# CONFIG_NETFILTER_XT_CONNMARK is not set
+
+#
+# Xtables targets
+#
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_CT is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_HL=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+# CONFIG_NF_NAT_SNMP_BASIC is not set
+CONFIG_NF_NAT_PROTO_GRE=m
+# CONFIG_NF_NAT_FTP is not set
+# CONFIG_NF_NAT_IRC is not set
+# CONFIG_NF_NAT_TFTP is not set
+# CONFIG_NF_NAT_AMANDA is not set
+CONFIG_NF_NAT_PPTP=m
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
+CONFIG_IP_NF_MANGLE=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_NF_CONNTRACK_IPV6 is not set
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP 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_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+
+#
+# Some wireless drivers require a rate control algorithm
+#
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=m
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=m
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# The newer stack is recommended.
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_NET_ETHERNET is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_FAST_BRIDGE is not set
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF 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_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
+# CONFIG_CHELSIO_T3 is not set
+CONFIG_CHELSIO_T4_DEPENDS=y
+# CONFIG_CHELSIO_T4 is not set
+# CONFIG_ENIC is not set
+# CONFIG_IXGBE is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
+# CONFIG_QLCNIC is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
+# CONFIG_BE2NET is not set
+
+#
+# CNS2100 NIC support
+#
+CONFIG_STAR_NIC=y
+CONFIG_STAR_NIC_PHY_INTERNAL_PHY=y
+# CONFIG_STAR_NIC_PHY_VSC8601 is not set
+# CONFIG_STAR_NIC_PHY_IP101A is not set
+# CONFIG_STAR_NIC_PHY_IP1001 is not set
+# CONFIG_TR is not set
+CONFIG_WLAN=y
+# CONFIG_ATMEL is not set
+# CONFIG_PRISM54 is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_HOSTAP is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_PPP_DEFLATE=y
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+# CONFIG_NET_FC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_VMXNET3 is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=m
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+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_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=m
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=m
+CONFIG_SERIO_SERPORT=m
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=m
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_CTSRTS is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_RAMOOPS is not set
+# CONFIG_I2C is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_STR8100=y
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=m
+CONFIG_SSB_SPROM=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+# CONFIG_SSB_B43_PCI_BRIDGE is not set
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_DRIVER_PCICORE=y
+CONFIG_MFD_SUPPORT=y
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_MC13783 is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_AB8500_CORE is not set
+# CONFIG_LPC_SCH is not set
+# CONFIG_MFD_RDC321X is not set
+# CONFIG_MFD_JANZ_CMODIO is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGA_ARB is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_3M_PCT is not set
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CANDO is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EGALAX is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MOSART is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_QUANTA is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_ROCCAT_KONE is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_STANTUM is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_HCD_SSB is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_EZUSB is not set
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_CH341 is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP210X is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_IUU is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_QCAUX is not set
+# CONFIG_USB_SERIAL_QUALCOMM is not set
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_SYMBOL is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
+# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set
+# CONFIG_USB_SERIAL_ZIO is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+CONFIG_USB_GADGET_R8A66597=y
+CONFIG_USB_R8A66597=m
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FUNCTIONFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_MASS_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_NOKIA is not set
+# CONFIG_USB_G_MULTI is not set
+# CONFIG_USB_G_HID is not set
+# CONFIG_USB_G_WEBCAM is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_ULPI is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_FS_XIP=y
+CONFIG_JBD=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# Caches
+#
+# CONFIG_FSCACHE 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 is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_UNION_FS=m
+# CONFIG_UNION_FS_XATTR is not set
+# CONFIG_UNION_FS_DEBUG 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_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 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 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_OC_ETM is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_MANAGER_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff --git a/recipes/linux/linux-ts75xx-2.6.35/ts75xx/defconfig.bak b/recipes/linux/linux-ts75xx-2.6.35/ts75xx/defconfig.bak
new file mode 100644
index 0000000..71a3a82
--- /dev/null
+++ b/recipes/linux/linux-ts75xx-2.6.35/ts75xx/defconfig.bak
@@ -0,0 +1,1521 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.35.11
+# Sat Feb 26 21:00:50 2011
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_TIME=y
+# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_LZO is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_STR9100 is not set
+CONFIG_ARCH_STR8100=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CNS3XXX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_NUC93X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P6440 is not set
+# CONFIG_ARCH_S5P6442 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_PLAT_SPEAR is not set
+CONFIG_CONSOLE_BAUD_RATE=115200
+
+#
+# STR8100 Options
+#
+CONFIG_VIC_INTERRUPT=y
+# CONFIG_STR8100_DRAM_16M is not set
+# CONFIG_STR8100_DRAM_32M is not set
+CONFIG_STR8100_DRAM_64M=y
+CONFIG_STR8100_PCI33M=y
+# CONFIG_STR8100_PCI66M is not set
+# CONFIG_STR8100_DMA is not set
+# CONFIG_STR8100_HSDMA is not set
+CONFIG_STR8100_INFO=y
+# CONFIG_STR8100_USBD_REBOOT_INTHANDLER is not set
+# CONFIG_STR8100_I2S is not set
+# CONFIG_STR8100_I2S_DEMO is not set
+# CONFIG_STR8100_I2S_WM8772_DEMO is not set
+# CONFIG_LE88221_CONTROL is not set
+# CONFIG_STR8100_PCM_LEGERITY_2PHONE_DEMO is not set
+# CONFIG_STR8100_RTC is not set
+CONFIG_STR8100_GPIO=y
+CONFIG_STR8100_GPIO_INTERRUPT=y
+# CONFIG_STR8100_GPIO_GENERIC_INTERFACE is not set
+
+#
+# Flash MAP
+#
+# CONFIG_STR8100_FLASH_PART is not set
+
+#
+# Third Party Support
+#
+# CONFIG_STR8100_EWC_SUPPORT is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_FA526=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_CACHE_FA=y
+CONFIG_CPU_COPY_FA=y
+CONFIG_CPU_TLB_FA=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+CONFIG_CPU_FA_BTB=y
+# CONFIG_CPU_FA_WB_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+
+#
+# Bus support
+#
+CONFIG_PCI=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/ram0 init=/linuxrc lpj=958464 console=null"
+# CONFIG_CMDLINE_FORCE is not set
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+CONFIG_FPE_FASTFPE=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+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_IP_MROUTE 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_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+CONFIG_NETFILTER=y
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP 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_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+# CONFIG_IP_NF_MATCH_DSCP is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+# CONFIG_IP_NF_TARGET_TCPMSS is not set
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+
+#
+# Some wireless drivers require a rate control algorithm
+#
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=m
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# 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_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=m
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# The newer stack is recommended.
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_NET_ETHERNET is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_FAST_BRIDGE is not set
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF 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_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
+# CONFIG_CHELSIO_T3 is not set
+CONFIG_CHELSIO_T4_DEPENDS=y
+# CONFIG_CHELSIO_T4 is not set
+# CONFIG_ENIC is not set
+# CONFIG_IXGBE is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
+# CONFIG_QLCNIC is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
+# CONFIG_BE2NET is not set
+
+#
+# CNS2100 NIC support
+#
+CONFIG_STAR_NIC=y
+CONFIG_STAR_NIC_PHY_INTERNAL_PHY=y
+# CONFIG_STAR_NIC_PHY_VSC8601 is not set
+# CONFIG_STAR_NIC_PHY_IP101A is not set
+# CONFIG_STAR_NIC_PHY_IP1001 is not set
+# CONFIG_TR is not set
+CONFIG_WLAN=y
+# CONFIG_ATMEL is not set
+# CONFIG_PRISM54 is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_HOSTAP is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_PPP_DEFLATE=y
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+# CONFIG_NET_FC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_VMXNET3 is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=m
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+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_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=m
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=m
+CONFIG_SERIO_SERPORT=m
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=m
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_CTSRTS is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_RAMOOPS is not set
+# CONFIG_I2C is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_STR8100=y
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=m
+CONFIG_SSB_SPROM=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+# CONFIG_SSB_B43_PCI_BRIDGE is not set
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_DRIVER_PCICORE=y
+CONFIG_MFD_SUPPORT=y
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_MC13783 is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_AB8500_CORE is not set
+# CONFIG_LPC_SCH is not set
+# CONFIG_MFD_RDC321X is not set
+# CONFIG_MFD_JANZ_CMODIO is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGA_ARB is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_3M_PCT is not set
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CANDO is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EGALAX is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MOSART is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_QUANTA is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_ROCCAT_KONE is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_STANTUM is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_HCD_SSB is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_EZUSB is not set
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_CH341 is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP210X is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_IUU is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_QCAUX is not set
+# CONFIG_USB_SERIAL_QUALCOMM is not set
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_SYMBOL is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
+# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set
+# CONFIG_USB_SERIAL_ZIO is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+CONFIG_USB_GADGET_R8A66597=y
+CONFIG_USB_R8A66597=m
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FUNCTIONFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_MASS_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_NOKIA is not set
+# CONFIG_USB_G_MULTI is not set
+# CONFIG_USB_G_HID is not set
+# CONFIG_USB_G_WEBCAM is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_ULPI is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_FS_XIP=y
+CONFIG_JBD=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_FSNOTIFY is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY=y
+# CONFIG_INOTIFY_USER is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE 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 is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 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 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_OC_ETM is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=m
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_MANAGER_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff --git a/recipes/linux/linux-ts75xx-2.6.35/ts75xx/ts7500-2.6.35.11.patch b/recipes/linux/linux-ts75xx-2.6.35/ts75xx/ts7500-2.6.35.11.patch
new file mode 100644
index 0000000..97fcd7b
--- /dev/null
+++ b/recipes/linux/linux-ts75xx-2.6.35/ts75xx/ts7500-2.6.35.11.patch
@@ -0,0 +1,85527 @@
+diff -rupN linux-2.6.35.11/arch/arm/boot/bootp/bootp.lds linux-2.6.35.11-ts7500/arch/arm/boot/bootp/bootp.lds
+--- linux-2.6.35.11/arch/arm/boot/bootp/bootp.lds 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/boot/bootp/bootp.lds 2011-03-14 11:18:24.000000000 -0400
+@@ -17,6 +17,8 @@ SECTIONS
+ *(.start)
+ *(.text)
+ initrd_size = initrd_end - initrd_start;
++/* scott.kernel */
++ kernel_size = kernel_end - kernel_start;
+ _etext = .;
+ }
+
+diff -rupN linux-2.6.35.11/arch/arm/boot/bootp/init.S linux-2.6.35.11-ts7500/arch/arm/boot/bootp/init.S
+--- linux-2.6.35.11/arch/arm/boot/bootp/init.S 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/boot/bootp/init.S 2011-03-14 11:18:24.000000000 -0400
+@@ -22,9 +22,13 @@
+
+ _start: add lr, pc, #-0x8 @ lr = current load addr
+ adr r13, data
+- ldmia r13!, {r4-r6} @ r5 = dest, r6 = length
++ ldmia r13!, {r4-r6} @ r5 = initrd_phys, r6 = initrd_size
+ add r4, r4, lr @ r4 = initrd_start + load addr
+ bl move @ move the initrd
++ ldmia r13!, {r4-r6} @ r5 = kernel_phys, r6 = kernel_size
++ add r4, r4, lr @ r4 = kernel_start + load addr
++ mov r12, r5 @ save kernel_phys to r12
++ bl move @ move the kernel
+
+ /*
+ * Setup the initrd parameters to pass to the kernel. This can only be
+@@ -49,7 +53,7 @@ _start: add lr, pc, #-0x8 @ lr = curre
+ /*
+ * find the end of the tag list, and then add an INITRD tag on the end.
+ * If there is already an INITRD tag, then we ignore it; the last INITRD
+- * tag takes precedence.
++ * tag takes precidence.
+ */
+ taglist: ldr r10, [r9, #0] @ tag length
+ teq r10, #0 @ last tag (zero length)?
+@@ -58,7 +62,11 @@ taglist: ldr r10, [r9, #0] @ tag length
+
+ mov r5, #4 @ Size of initrd tag (4 words)
+ stmia r9, {r5, r6, r7, r8, r10}
++/* scott.kernel */
++ mov pc, r12
++/* scott.kernel
+ b kernel_start @ call kernel
++*/
+
+ /*
+ * Move the block of memory length r6 from address r4 to address r5
+@@ -77,6 +85,10 @@ move: ldmia r4!, {r7 - r10} @ move 32-
+ data: .word initrd_start @ source initrd address
+ .word initrd_phys @ destination initrd address
+ .word initrd_size @ initrd size
++/* scott.kernel */
++ .word kernel_start @ source kernel address
++ .word kernel_phys @ destination kernel address
++ .word kernel_size @ kernel size
+
+ .word 0x54410001 @ r5 = ATAG_CORE
+ .word 0x54420005 @ r6 = ATAG_INITRD2
+diff -rupN linux-2.6.35.11/arch/arm/boot/bootp/init.S.old linux-2.6.35.11-ts7500/arch/arm/boot/bootp/init.S.old
+--- linux-2.6.35.11/arch/arm/boot/bootp/init.S.old 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/boot/bootp/init.S.old 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,86 @@
++/*
++ * linux/arch/arm/boot/bootp/init.S
++ *
++ * Copyright (C) 2000-2003 Russell King.
++ *
++ * 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.
++ *
++ * "Header" file for splitting kernel + initrd. Note that we pass
++ * r0 through to r3 straight through.
++ *
++ * This demonstrates how to append code to the start of the kernel
++ * zImage, and boot the kernel without copying it around. This
++ * example would be simpler; if we didn't have an object of unknown
++ * size immediately following the kernel, we could build this into
++ * a binary blob, and concatenate the zImage using the cat command.
++ */
++ .section .start,#alloc,#execinstr
++ .type _start, #function
++ .globl _start
++
++_start: add lr, pc, #-0x8 @ lr = current load addr
++ adr r13, data
++ ldmia r13!, {r4-r6} @ r5 = dest, r6 = length
++ add r4, r4, lr @ r4 = initrd_start + load addr
++ bl move @ move the initrd
++
++/*
++ * Setup the initrd parameters to pass to the kernel. This can only be
++ * passed in via the tagged list.
++ */
++ ldmia r13, {r5-r9} @ get size and addr of initrd
++ @ r5 = ATAG_CORE
++ @ r6 = ATAG_INITRD2
++ @ r7 = initrd start
++ @ r8 = initrd end
++ @ r9 = param_struct address
++
++ ldr r10, [r9, #4] @ get first tag
++ teq r10, r5 @ is it ATAG_CORE?
++/*
++ * If we didn't find a valid tag list, create a dummy ATAG_CORE entry.
++ */
++ movne r10, #0 @ terminator
++ movne r4, #2 @ Size of this entry (2 words)
++ stmneia r9, {r4, r5, r10} @ Size, ATAG_CORE, terminator
++
++/*
++ * find the end of the tag list, and then add an INITRD tag on the end.
++ * If there is already an INITRD tag, then we ignore it; the last INITRD
++ * tag takes precedence.
++ */
++taglist: ldr r10, [r9, #0] @ tag length
++ teq r10, #0 @ last tag (zero length)?
++ addne r9, r9, r10, lsl #2
++ bne taglist
++
++ mov r5, #4 @ Size of initrd tag (4 words)
++ stmia r9, {r5, r6, r7, r8, r10}
++ b kernel_start @ call kernel
++
++/*
++ * Move the block of memory length r6 from address r4 to address r5
++ */
++move: ldmia r4!, {r7 - r10} @ move 32-bytes at a time
++ stmia r5!, {r7 - r10}
++ ldmia r4!, {r7 - r10}
++ stmia r5!, {r7 - r10}
++ subs r6, r6, #8 * 4
++ bcs move
++ mov pc, lr
++
++ .size _start, . - _start
++
++ .type data,#object
++data: .word initrd_start @ source initrd address
++ .word initrd_phys @ destination initrd address
++ .word initrd_size @ initrd size
++
++ .word 0x54410001 @ r5 = ATAG_CORE
++ .word 0x54420005 @ r6 = ATAG_INITRD2
++ .word initrd_phys @ r7
++ .word initrd_size @ r8
++ .word params_phys @ r9
++ .size data, . - data
+diff -rupN linux-2.6.35.11/arch/arm/boot/bootp/Makefile linux-2.6.35.11-ts7500/arch/arm/boot/bootp/Makefile
+--- linux-2.6.35.11/arch/arm/boot/bootp/Makefile 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/boot/bootp/Makefile 2011-03-14 11:18:24.000000000 -0400
+@@ -7,6 +7,7 @@
+
+ LDFLAGS_bootp :=-p --no-undefined -X \
+ --defsym initrd_phys=$(INITRD_PHYS) \
++ --defsym kernel_phys=$(KERNEL_PHYS) \
+ --defsym params_phys=$(PARAMS_PHYS) -T
+ AFLAGS_initrd.o :=-DINITRD=\"$(INITRD)\"
+
+diff -rupN linux-2.6.35.11/arch/arm/boot/compressed/head.S linux-2.6.35.11-ts7500/arch/arm/boot/compressed/head.S
+--- linux-2.6.35.11/arch/arm/boot/compressed/head.S 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/boot/compressed/head.S 2011-03-14 11:18:24.000000000 -0400
+@@ -71,6 +71,21 @@ wait: mrc p14, 0, pc, c0, c1, 0
+ mov \rb, #0x50000000
+ add \rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT
+ .endm
++#elif defined(CONFIG_ARCH_STR9100)
++ .macro loadsp, rb
++ mov \rb, #0x78000000
++ .endm
++ .macro writeb, rb
++ strb \rb, [r3, #0]
++ .endm
++#elif defined(CONFIG_ARCH_STR8100)
++ .macro loadsp, rb
++ mov \rb, #0x78000000
++ .endm
++
++ .macro writeb, rb
++ strb \rb, [r3, #0]
++ .endm
+ #else
+ .macro loadsp, rb, tmp
+ addruart \rb, \tmp
+@@ -444,6 +459,15 @@ __setup_mmu: sub r3, r4, #16384 @ Page
+ mov pc, lr
+ ENDPROC(__setup_mmu)
+
++
++/* added by ivan wang for no cache support */
++__armv4_no_mmu_cache:
++ orr r0,r0,#0
++ orr r0,r0,#0
++ mov pc,lr
++ orr r0,r0,#0
++ orr r0,r0,#0
++
+ __armv4_mmu_cache_on:
+ mov r12, lr
+ #ifdef CONFIG_MMU
+@@ -530,6 +554,13 @@ __common_mmu_cache_on:
+ .align 5 @ cache line aligned
+ 1: mcr p15, 0, r0, c1, c0, 0 @ load control register
+ mrc p15, 0, r0, c1, c0, 0 @ and read it back to
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++ /* FA520/FA526 need > 2 nops */
++ mov r0,r0
++ mov r0,r0
++ mov r0,r0
++ mov r0,r0
++#endif
+ sub pc, lr, r0, lsr #32 @ properly flush pipeline
+ #endif
+
+@@ -712,12 +743,13 @@ proc_types:
+ b __armv5tej_mmu_cache_flush
+ #endif
+
++#if (0)
+ .word 0x66015261 @ FA526
+ .word 0xff01fff1
+ W(b) __fa526_cache_on
+ W(b) __armv4_mmu_cache_off
+ W(b) __fa526_cache_flush
+-
++#endif
+ @ These match on the architecture ID
+
+ .word 0x00020000 @ ARMv4T
+@@ -726,6 +758,18 @@ proc_types:
+ W(b) __armv4_mmu_cache_off
+ W(b) __armv4_mmu_cache_flush
+
++#if (1)
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++ .word 0x66015261 @ FA526, ARMv4
++ .word 0xff01fff1
++ W(b) __armv4_mmu_cache_on
++ @W(b) __fa526_cache_on
++ W(b) __armv4_mmu_cache_off
++ W(b) __armv4_mmu_cache_flush
++ @W(b) __fa526_cache_flush
++#endif
++#endif
++
+ .word 0x00050000 @ ARMv5TE
+ .word 0x000f0000
+ W(b) __armv4_mmu_cache_on
+@@ -801,6 +845,13 @@ __armv4_mmu_cache_off:
+ mrc p15, 0, r0, c1, c0
+ bic r0, r0, #0x000d
+ mcr p15, 0, r0, c1, c0 @ turn MMU and cache off
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++ /* FA520/FA526 need > 2 nops */
++ mov r0,r0
++ mov r0,r0
++ mov r0,r0
++ mov r0,r0
++#endif
+ mov r0, #0
+ mcr p15, 0, r0, c7, c7 @ invalidate whole cache v4
+ mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4
+@@ -970,6 +1021,10 @@ __armv4_mmu_cache_flush:
+ mov r11, #8
+ mov r11, r11, lsl r3 @ cache line size in bytes
+ no_cache_id:
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++ mov r1,#0
++ mcr p15, 0, r1, c7, c10, 0 @ clean D cache
++#endif
+ mov r1, pc
+ bic r1, r1, #63 @ align to longest cache line
+ add r2, r1, r2
+diff -rupN linux-2.6.35.11/arch/arm/boot/compressed/head.S.orig linux-2.6.35.11-ts7500/arch/arm/boot/compressed/head.S.orig
+--- linux-2.6.35.11/arch/arm/boot/compressed/head.S.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/boot/compressed/head.S.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,1072 @@
++/*
++ * linux/arch/arm/boot/compressed/head.S
++ *
++ * Copyright (C) 1996-2002 Russell King
++ * Copyright (C) 2004 Hyok S. Choi (MPU support)
++ *
++ * 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.
++ */
++#include <linux/linkage.h>
++
++/*
++ * Debugging stuff
++ *
++ * Note that these macros must not contain any code which is not
++ * 100% relocatable. Any attempt to do so will result in a crash.
++ * Please select one of the following when turning on debugging.
++ */
++#ifdef DEBUG
++
++#if defined(CONFIG_DEBUG_ICEDCC)
++
++#ifdef CONFIG_CPU_V6
++ .macro loadsp, rb, tmp
++ .endm
++ .macro writeb, ch, rb
++ mcr p14, 0, \ch, c0, c5, 0
++ .endm
++#elif defined(CONFIG_CPU_V7)
++ .macro loadsp, rb, tmp
++ .endm
++ .macro writeb, ch, rb
++wait: mrc p14, 0, pc, c0, c1, 0
++ bcs wait
++ mcr p14, 0, \ch, c0, c5, 0
++ .endm
++#elif defined(CONFIG_CPU_XSCALE)
++ .macro loadsp, rb, tmp
++ .endm
++ .macro writeb, ch, rb
++ mcr p14, 0, \ch, c8, c0, 0
++ .endm
++#else
++ .macro loadsp, rb, tmp
++ .endm
++ .macro writeb, ch, rb
++ mcr p14, 0, \ch, c1, c0, 0
++ .endm
++#endif
++
++#else
++
++#include <mach/debug-macro.S>
++
++ .macro writeb, ch, rb
++ senduart \ch, \rb
++ .endm
++
++#if defined(CONFIG_ARCH_SA1100)
++ .macro loadsp, rb, tmp
++ mov \rb, #0x80000000 @ physical base address
++#ifdef CONFIG_DEBUG_LL_SER3
++ add \rb, \rb, #0x00050000 @ Ser3
++#else
++ add \rb, \rb, #0x00010000 @ Ser1
++#endif
++ .endm
++#elif defined(CONFIG_ARCH_S3C2410)
++ .macro loadsp, rb, tmp
++ mov \rb, #0x50000000
++ add \rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT
++ .endm
++#else
++ .macro loadsp, rb, tmp
++ addruart \rb, \tmp
++ .endm
++#endif
++#endif
++#endif
++
++ .macro kputc,val
++ mov r0, \val
++ bl putc
++ .endm
++
++ .macro kphex,val,len
++ mov r0, \val
++ mov r1, #\len
++ bl phex
++ .endm
++
++ .macro debug_reloc_start
++#ifdef DEBUG
++ kputc #'\n'
++ kphex r6, 8 /* processor id */
++ kputc #':'
++ kphex r7, 8 /* architecture id */
++#ifdef CONFIG_CPU_CP15
++ kputc #':'
++ mrc p15, 0, r0, c1, c0
++ kphex r0, 8 /* control reg */
++#endif
++ kputc #'\n'
++ kphex r5, 8 /* decompressed kernel start */
++ kputc #'-'
++ kphex r9, 8 /* decompressed kernel end */
++ kputc #'>'
++ kphex r4, 8 /* kernel execution address */
++ kputc #'\n'
++#endif
++ .endm
++
++ .macro debug_reloc_end
++#ifdef DEBUG
++ kphex r5, 8 /* end of kernel */
++ kputc #'\n'
++ mov r0, r4
++ bl memdump /* dump 256 bytes at start of kernel */
++#endif
++ .endm
++
++ .section ".start", #alloc, #execinstr
++/*
++ * sort out different calling conventions
++ */
++ .align
++start:
++ .type start,#function
++ .rept 8
++ mov r0, r0
++ .endr
++
++ b 1f
++ .word 0x016f2818 @ Magic numbers to help the loader
++ .word start @ absolute load/run zImage address
++ .word _edata @ zImage end address
++1: mov r7, r1 @ save architecture ID
++ mov r8, r2 @ save atags pointer
++
++#ifndef __ARM_ARCH_2__
++ /*
++ * Booting from Angel - need to enter SVC mode and disable
++ * FIQs/IRQs (numeric definitions from angel arm.h source).
++ * We only do this if we were in user mode on entry.
++ */
++ mrs r2, cpsr @ get current mode
++ tst r2, #3 @ not user?
++ bne not_angel
++ mov r0, #0x17 @ angel_SWIreason_EnterSVC
++ ARM( swi 0x123456 ) @ angel_SWI_ARM
++ THUMB( svc 0xab ) @ angel_SWI_THUMB
++not_angel:
++ mrs r2, cpsr @ turn off interrupts to
++ orr r2, r2, #0xc0 @ prevent angel from running
++ msr cpsr_c, r2
++#else
++ teqp pc, #0x0c000003 @ turn off interrupts
++#endif
++
++ /*
++ * Note that some cache flushing and other stuff may
++ * be needed here - is there an Angel SWI call for this?
++ */
++
++ /*
++ * some architecture specific code can be inserted
++ * by the linker here, but it should preserve r7, r8, and r9.
++ */
++
++ .text
++ adr r0, LC0
++ ARM( ldmia r0, {r1, r2, r3, r4, r5, r6, r11, ip, sp})
++ THUMB( ldmia r0, {r1, r2, r3, r4, r5, r6, r11, ip} )
++ THUMB( ldr sp, [r0, #32] )
++ subs r0, r0, r1 @ calculate the delta offset
++
++ @ if delta is zero, we are
++ beq not_relocated @ running at the address we
++ @ were linked at.
++
++ /*
++ * We're running at a different address. We need to fix
++ * up various pointers:
++ * r5 - zImage base address (_start)
++ * r6 - size of decompressed image
++ * r11 - GOT start
++ * ip - GOT end
++ */
++ add r5, r5, r0
++ add r11, r11, r0
++ add ip, ip, r0
++
++#ifndef CONFIG_ZBOOT_ROM
++ /*
++ * If we're running fully PIC === CONFIG_ZBOOT_ROM = n,
++ * we need to fix up pointers into the BSS region.
++ * r2 - BSS start
++ * r3 - BSS end
++ * sp - stack pointer
++ */
++ add r2, r2, r0
++ add r3, r3, r0
++ add sp, sp, r0
++
++ /*
++ * Relocate all entries in the GOT table.
++ */
++1: ldr r1, [r11, #0] @ relocate entries in the GOT
++ add r1, r1, r0 @ table. This fixes up the
++ str r1, [r11], #4 @ C references.
++ cmp r11, ip
++ blo 1b
++#else
++
++ /*
++ * Relocate entries in the GOT table. We only relocate
++ * the entries that are outside the (relocated) BSS region.
++ */
++1: ldr r1, [r11, #0] @ relocate entries in the GOT
++ cmp r1, r2 @ entry < bss_start ||
++ cmphs r3, r1 @ _end < entry
++ addlo r1, r1, r0 @ table. This fixes up the
++ str r1, [r11], #4 @ C references.
++ cmp r11, ip
++ blo 1b
++#endif
++
++not_relocated: mov r0, #0
++1: str r0, [r2], #4 @ clear bss
++ str r0, [r2], #4
++ str r0, [r2], #4
++ str r0, [r2], #4
++ cmp r2, r3
++ blo 1b
++
++ /*
++ * The C runtime environment should now be setup
++ * sufficiently. Turn the cache on, set up some
++ * pointers, and start decompressing.
++ */
++ bl cache_on
++
++ mov r1, sp @ malloc space above stack
++ add r2, sp, #0x10000 @ 64k max
++
++/*
++ * Check to see if we will overwrite ourselves.
++ * r4 = final kernel address
++ * r5 = start of this image
++ * r6 = size of decompressed image
++ * r2 = end of malloc space (and therefore this image)
++ * We basically want:
++ * r4 >= r2 -> OK
++ * r4 + image length <= r5 -> OK
++ */
++ cmp r4, r2
++ bhs wont_overwrite
++ add r0, r4, r6
++ cmp r0, r5
++ bls wont_overwrite
++
++ mov r5, r2 @ decompress after malloc space
++ mov r0, r5
++ mov r3, r7
++ bl decompress_kernel
++
++ add r0, r0, #127 + 128 @ alignment + stack
++ bic r0, r0, #127 @ align the kernel length
++/*
++ * r0 = decompressed kernel length
++ * r1-r3 = unused
++ * r4 = kernel execution address
++ * r5 = decompressed kernel start
++ * r7 = architecture ID
++ * r8 = atags pointer
++ * r9-r12,r14 = corrupted
++ */
++ add r1, r5, r0 @ end of decompressed kernel
++ adr r2, reloc_start
++ ldr r3, LC1
++ add r3, r2, r3
++1: ldmia r2!, {r9 - r12, r14} @ copy relocation code
++ stmia r1!, {r9 - r12, r14}
++ ldmia r2!, {r9 - r12, r14}
++ stmia r1!, {r9 - r12, r14}
++ cmp r2, r3
++ blo 1b
++ mov sp, r1
++ add sp, sp, #128 @ relocate the stack
++
++ bl cache_clean_flush
++ ARM( add pc, r5, r0 ) @ call relocation code
++ THUMB( add r12, r5, r0 )
++ THUMB( mov pc, r12 ) @ call relocation code
++
++/*
++ * We're not in danger of overwriting ourselves. Do this the simple way.
++ *
++ * r4 = kernel execution address
++ * r7 = architecture ID
++ */
++wont_overwrite: mov r0, r4
++ mov r3, r7
++ bl decompress_kernel
++ b call_kernel
++
++ .align 2
++ .type LC0, #object
++LC0: .word LC0 @ r1
++ .word __bss_start @ r2
++ .word _end @ r3
++ .word zreladdr @ r4
++ .word _start @ r5
++ .word _image_size @ r6
++ .word _got_start @ r11
++ .word _got_end @ ip
++ .word user_stack+4096 @ sp
++LC1: .word reloc_end - reloc_start
++ .size LC0, . - LC0
++
++#ifdef CONFIG_ARCH_RPC
++ .globl params
++params: ldr r0, =params_phys
++ mov pc, lr
++ .ltorg
++ .align
++#endif
++
++/*
++ * Turn on the cache. We need to setup some page tables so that we
++ * can have both the I and D caches on.
++ *
++ * We place the page tables 16k down from the kernel execution address,
++ * and we hope that nothing else is using it. If we're using it, we
++ * will go pop!
++ *
++ * On entry,
++ * r4 = kernel execution address
++ * r7 = architecture number
++ * r8 = atags pointer
++ * r9 = run-time address of "start" (???)
++ * On exit,
++ * r1, r2, r3, r9, r10, r12 corrupted
++ * This routine must preserve:
++ * r4, r5, r6, r7, r8
++ */
++ .align 5
++cache_on: mov r3, #8 @ cache_on function
++ b call_cache_fn
++
++/*
++ * Initialize the highest priority protection region, PR7
++ * to cover all 32bit address and cacheable and bufferable.
++ */
++__armv4_mpu_cache_on:
++ mov r0, #0x3f @ 4G, the whole
++ mcr p15, 0, r0, c6, c7, 0 @ PR7 Area Setting
++ mcr p15, 0, r0, c6, c7, 1
++
++ mov r0, #0x80 @ PR7
++ mcr p15, 0, r0, c2, c0, 0 @ D-cache on
++ mcr p15, 0, r0, c2, c0, 1 @ I-cache on
++ mcr p15, 0, r0, c3, c0, 0 @ write-buffer on
++
++ mov r0, #0xc000
++ mcr p15, 0, r0, c5, c0, 1 @ I-access permission
++ mcr p15, 0, r0, c5, c0, 0 @ D-access permission
++
++ mov r0, #0
++ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
++ mcr p15, 0, r0, c7, c5, 0 @ flush(inval) I-Cache
++ mcr p15, 0, r0, c7, c6, 0 @ flush(inval) D-Cache
++ mrc p15, 0, r0, c1, c0, 0 @ read control reg
++ @ ...I .... ..D. WC.M
++ orr r0, r0, #0x002d @ .... .... ..1. 11.1
++ orr r0, r0, #0x1000 @ ...1 .... .... ....
++
++ mcr p15, 0, r0, c1, c0, 0 @ write control reg
++
++ mov r0, #0
++ mcr p15, 0, r0, c7, c5, 0 @ flush(inval) I-Cache
++ mcr p15, 0, r0, c7, c6, 0 @ flush(inval) D-Cache
++ mov pc, lr
++
++__armv3_mpu_cache_on:
++ mov r0, #0x3f @ 4G, the whole
++ mcr p15, 0, r0, c6, c7, 0 @ PR7 Area Setting
++
++ mov r0, #0x80 @ PR7
++ mcr p15, 0, r0, c2, c0, 0 @ cache on
++ mcr p15, 0, r0, c3, c0, 0 @ write-buffer on
++
++ mov r0, #0xc000
++ mcr p15, 0, r0, c5, c0, 0 @ access permission
++
++ mov r0, #0
++ mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
++ mrc p15, 0, r0, c1, c0, 0 @ read control reg
++ @ .... .... .... WC.M
++ orr r0, r0, #0x000d @ .... .... .... 11.1
++ mov r0, #0
++ mcr p15, 0, r0, c1, c0, 0 @ write control reg
++
++ mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
++ mov pc, lr
++
++__setup_mmu: sub r3, r4, #16384 @ Page directory size
++ bic r3, r3, #0xff @ Align the pointer
++ bic r3, r3, #0x3f00
++/*
++ * Initialise the page tables, turning on the cacheable and bufferable
++ * bits for the RAM area only.
++ */
++ mov r0, r3
++ mov r9, r0, lsr #18
++ mov r9, r9, lsl #18 @ start of RAM
++ add r10, r9, #0x10000000 @ a reasonable RAM size
++ mov r1, #0x12
++ orr r1, r1, #3 << 10
++ add r2, r3, #16384
++1: cmp r1, r9 @ if virt > start of RAM
++ orrhs r1, r1, #0x0c @ set cacheable, bufferable
++ cmp r1, r10 @ if virt > end of RAM
++ bichs r1, r1, #0x0c @ clear cacheable, bufferable
++ str r1, [r0], #4 @ 1:1 mapping
++ add r1, r1, #1048576
++ teq r0, r2
++ bne 1b
++/*
++ * If ever we are running from Flash, then we surely want the cache
++ * to be enabled also for our execution instance... We map 2MB of it
++ * so there is no map overlap problem for up to 1 MB compressed kernel.
++ * If the execution is in RAM then we would only be duplicating the above.
++ */
++ mov r1, #0x1e
++ orr r1, r1, #3 << 10
++ mov r2, pc, lsr #20
++ orr r1, r1, r2, lsl #20
++ add r0, r3, r2, lsl #2
++ str r1, [r0], #4
++ add r1, r1, #1048576
++ str r1, [r0]
++ mov pc, lr
++ENDPROC(__setup_mmu)
++
++__armv4_mmu_cache_on:
++ mov r12, lr
++#ifdef CONFIG_MMU
++ bl __setup_mmu
++ mov r0, #0
++ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
++ mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
++ mrc p15, 0, r0, c1, c0, 0 @ read control reg
++ orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement
++ orr r0, r0, #0x0030
++#ifdef CONFIG_CPU_ENDIAN_BE8
++ orr r0, r0, #1 << 25 @ big-endian page tables
++#endif
++ bl __common_mmu_cache_on
++ mov r0, #0
++ mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
++#endif
++ mov pc, r12
++
++__armv7_mmu_cache_on:
++ mov r12, lr
++#ifdef CONFIG_MMU
++ mrc p15, 0, r11, c0, c1, 4 @ read ID_MMFR0
++ tst r11, #0xf @ VMSA
++ blne __setup_mmu
++ mov r0, #0
++ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
++ tst r11, #0xf @ VMSA
++ mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
++#endif
++ mrc p15, 0, r0, c1, c0, 0 @ read control reg
++ orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement
++ orr r0, r0, #0x003c @ write buffer
++#ifdef CONFIG_MMU
++#ifdef CONFIG_CPU_ENDIAN_BE8
++ orr r0, r0, #1 << 25 @ big-endian page tables
++#endif
++ orrne r0, r0, #1 @ MMU enabled
++ movne r1, #-1
++ mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer
++ mcrne p15, 0, r1, c3, c0, 0 @ load domain access control
++#endif
++ mcr p15, 0, r0, c1, c0, 0 @ load control register
++ mrc p15, 0, r0, c1, c0, 0 @ and read it back
++ mov r0, #0
++ mcr p15, 0, r0, c7, c5, 4 @ ISB
++ mov pc, r12
++
++__fa526_cache_on:
++ mov r12, lr
++ bl __setup_mmu
++ mov r0, #0
++ mcr p15, 0, r0, c7, c7, 0 @ Invalidate whole cache
++ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
++ mcr p15, 0, r0, c8, c7, 0 @ flush UTLB
++ mrc p15, 0, r0, c1, c0, 0 @ read control reg
++ orr r0, r0, #0x1000 @ I-cache enable
++ bl __common_mmu_cache_on
++ mov r0, #0
++ mcr p15, 0, r0, c8, c7, 0 @ flush UTLB
++ mov pc, r12
++
++__arm6_mmu_cache_on:
++ mov r12, lr
++ bl __setup_mmu
++ mov r0, #0
++ mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
++ mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3
++ mov r0, #0x30
++ bl __common_mmu_cache_on
++ mov r0, #0
++ mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3
++ mov pc, r12
++
++__common_mmu_cache_on:
++#ifndef CONFIG_THUMB2_KERNEL
++#ifndef DEBUG
++ orr r0, r0, #0x000d @ Write buffer, mmu
++#endif
++ mov r1, #-1
++ mcr p15, 0, r3, c2, c0, 0 @ load page table pointer
++ mcr p15, 0, r1, c3, c0, 0 @ load domain access control
++ b 1f
++ .align 5 @ cache line aligned
++1: mcr p15, 0, r0, c1, c0, 0 @ load control register
++ mrc p15, 0, r0, c1, c0, 0 @ and read it back to
++ sub pc, lr, r0, lsr #32 @ properly flush pipeline
++#endif
++
++/*
++ * All code following this line is relocatable. It is relocated by
++ * the above code to the end of the decompressed kernel image and
++ * executed there. During this time, we have no stacks.
++ *
++ * r0 = decompressed kernel length
++ * r1-r3 = unused
++ * r4 = kernel execution address
++ * r5 = decompressed kernel start
++ * r7 = architecture ID
++ * r8 = atags pointer
++ * r9-r12,r14 = corrupted
++ */
++ .align 5
++reloc_start: add r9, r5, r0
++ sub r9, r9, #128 @ do not copy the stack
++ debug_reloc_start
++ mov r1, r4
++1:
++ .rept 4
++ ldmia r5!, {r0, r2, r3, r10 - r12, r14} @ relocate kernel
++ stmia r1!, {r0, r2, r3, r10 - r12, r14}
++ .endr
++
++ cmp r5, r9
++ blo 1b
++ mov sp, r1
++ add sp, sp, #128 @ relocate the stack
++ debug_reloc_end
++
++call_kernel: bl cache_clean_flush
++ bl cache_off
++ mov r0, #0 @ must be zero
++ mov r1, r7 @ restore architecture number
++ mov r2, r8 @ restore atags pointer
++ mov pc, r4 @ call kernel
++
++/*
++ * Here follow the relocatable cache support functions for the
++ * various processors. This is a generic hook for locating an
++ * entry and jumping to an instruction at the specified offset
++ * from the start of the block. Please note this is all position
++ * independent code.
++ *
++ * r1 = corrupted
++ * r2 = corrupted
++ * r3 = block offset
++ * r9 = corrupted
++ * r12 = corrupted
++ */
++
++call_cache_fn: adr r12, proc_types
++#ifdef CONFIG_CPU_CP15
++ mrc p15, 0, r9, c0, c0 @ get processor ID
++#else
++ ldr r9, =CONFIG_PROCESSOR_ID
++#endif
++1: ldr r1, [r12, #0] @ get value
++ ldr r2, [r12, #4] @ get mask
++ eor r1, r1, r9 @ (real ^ match)
++ tst r1, r2 @ & mask
++ ARM( addeq pc, r12, r3 ) @ call cache function
++ THUMB( addeq r12, r3 )
++ THUMB( moveq pc, r12 ) @ call cache function
++ add r12, r12, #4*5
++ b 1b
++
++/*
++ * Table for cache operations. This is basically:
++ * - CPU ID match
++ * - CPU ID mask
++ * - 'cache on' method instruction
++ * - 'cache off' method instruction
++ * - 'cache flush' method instruction
++ *
++ * We match an entry using: ((real_id ^ match) & mask) == 0
++ *
++ * Writethrough caches generally only need 'on' and 'off'
++ * methods. Writeback caches _must_ have the flush method
++ * defined.
++ */
++ .align 2
++ .type proc_types,#object
++proc_types:
++ .word 0x41560600 @ ARM6/610
++ .word 0xffffffe0
++ W(b) __arm6_mmu_cache_off @ works, but slow
++ W(b) __arm6_mmu_cache_off
++ mov pc, lr
++ THUMB( nop )
++@ b __arm6_mmu_cache_on @ untested
++@ b __arm6_mmu_cache_off
++@ b __armv3_mmu_cache_flush
++
++ .word 0x00000000 @ old ARM ID
++ .word 0x0000f000
++ mov pc, lr
++ THUMB( nop )
++ mov pc, lr
++ THUMB( nop )
++ mov pc, lr
++ THUMB( nop )
++
++ .word 0x41007000 @ ARM7/710
++ .word 0xfff8fe00
++ W(b) __arm7_mmu_cache_off
++ W(b) __arm7_mmu_cache_off
++ mov pc, lr
++ THUMB( nop )
++
++ .word 0x41807200 @ ARM720T (writethrough)
++ .word 0xffffff00
++ W(b) __armv4_mmu_cache_on
++ W(b) __armv4_mmu_cache_off
++ mov pc, lr
++ THUMB( nop )
++
++ .word 0x41007400 @ ARM74x
++ .word 0xff00ff00
++ W(b) __armv3_mpu_cache_on
++ W(b) __armv3_mpu_cache_off
++ W(b) __armv3_mpu_cache_flush
++
++ .word 0x41009400 @ ARM94x
++ .word 0xff00ff00
++ W(b) __armv4_mpu_cache_on
++ W(b) __armv4_mpu_cache_off
++ W(b) __armv4_mpu_cache_flush
++
++ .word 0x00007000 @ ARM7 IDs
++ .word 0x0000f000
++ mov pc, lr
++ THUMB( nop )
++ mov pc, lr
++ THUMB( nop )
++ mov pc, lr
++ THUMB( nop )
++
++ @ Everything from here on will be the new ID system.
++
++ .word 0x4401a100 @ sa110 / sa1100
++ .word 0xffffffe0
++ W(b) __armv4_mmu_cache_on
++ W(b) __armv4_mmu_cache_off
++ W(b) __armv4_mmu_cache_flush
++
++ .word 0x6901b110 @ sa1110
++ .word 0xfffffff0
++ W(b) __armv4_mmu_cache_on
++ W(b) __armv4_mmu_cache_off
++ W(b) __armv4_mmu_cache_flush
++
++ .word 0x56056900
++ .word 0xffffff00 @ PXA9xx
++ W(b) __armv4_mmu_cache_on
++ W(b) __armv4_mmu_cache_off
++ W(b) __armv4_mmu_cache_flush
++
++ .word 0x56158000 @ PXA168
++ .word 0xfffff000
++ W(b) __armv4_mmu_cache_on
++ W(b) __armv4_mmu_cache_off
++ W(b) __armv5tej_mmu_cache_flush
++
++ .word 0x56050000 @ Feroceon
++ .word 0xff0f0000
++ W(b) __armv4_mmu_cache_on
++ W(b) __armv4_mmu_cache_off
++ W(b) __armv5tej_mmu_cache_flush
++
++#ifdef CONFIG_CPU_FEROCEON_OLD_ID
++ /* this conflicts with the standard ARMv5TE entry */
++ .long 0x41009260 @ Old Feroceon
++ .long 0xff00fff0
++ b __armv4_mmu_cache_on
++ b __armv4_mmu_cache_off
++ b __armv5tej_mmu_cache_flush
++#endif
++
++ .word 0x66015261 @ FA526
++ .word 0xff01fff1
++ W(b) __fa526_cache_on
++ W(b) __armv4_mmu_cache_off
++ W(b) __fa526_cache_flush
++
++ @ These match on the architecture ID
++
++ .word 0x00020000 @ ARMv4T
++ .word 0x000f0000
++ W(b) __armv4_mmu_cache_on
++ W(b) __armv4_mmu_cache_off
++ W(b) __armv4_mmu_cache_flush
++
++ .word 0x00050000 @ ARMv5TE
++ .word 0x000f0000
++ W(b) __armv4_mmu_cache_on
++ W(b) __armv4_mmu_cache_off
++ W(b) __armv4_mmu_cache_flush
++
++ .word 0x00060000 @ ARMv5TEJ
++ .word 0x000f0000
++ W(b) __armv4_mmu_cache_on
++ W(b) __armv4_mmu_cache_off
++ W(b) __armv5tej_mmu_cache_flush
++
++ .word 0x0007b000 @ ARMv6
++ .word 0x000ff000
++ W(b) __armv4_mmu_cache_on
++ W(b) __armv4_mmu_cache_off
++ W(b) __armv6_mmu_cache_flush
++
++ .word 0x560f5810 @ Marvell PJ4 ARMv6
++ .word 0xff0ffff0
++ W(b) __armv4_mmu_cache_on
++ W(b) __armv4_mmu_cache_off
++ W(b) __armv6_mmu_cache_flush
++
++ .word 0x000f0000 @ new CPU Id
++ .word 0x000f0000
++ W(b) __armv7_mmu_cache_on
++ W(b) __armv7_mmu_cache_off
++ W(b) __armv7_mmu_cache_flush
++
++ .word 0 @ unrecognised type
++ .word 0
++ mov pc, lr
++ THUMB( nop )
++ mov pc, lr
++ THUMB( nop )
++ mov pc, lr
++ THUMB( nop )
++
++ .size proc_types, . - proc_types
++
++/*
++ * Turn off the Cache and MMU. ARMv3 does not support
++ * reading the control register, but ARMv4 does.
++ *
++ * On exit, r0, r1, r2, r3, r9, r12 corrupted
++ * This routine must preserve: r4, r6, r7
++ */
++ .align 5
++cache_off: mov r3, #12 @ cache_off function
++ b call_cache_fn
++
++__armv4_mpu_cache_off:
++ mrc p15, 0, r0, c1, c0
++ bic r0, r0, #0x000d
++ mcr p15, 0, r0, c1, c0 @ turn MPU and cache off
++ mov r0, #0
++ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
++ mcr p15, 0, r0, c7, c6, 0 @ flush D-Cache
++ mcr p15, 0, r0, c7, c5, 0 @ flush I-Cache
++ mov pc, lr
++
++__armv3_mpu_cache_off:
++ mrc p15, 0, r0, c1, c0
++ bic r0, r0, #0x000d
++ mcr p15, 0, r0, c1, c0, 0 @ turn MPU and cache off
++ mov r0, #0
++ mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
++ mov pc, lr
++
++__armv4_mmu_cache_off:
++#ifdef CONFIG_MMU
++ mrc p15, 0, r0, c1, c0
++ bic r0, r0, #0x000d
++ mcr p15, 0, r0, c1, c0 @ turn MMU and cache off
++ mov r0, #0
++ mcr p15, 0, r0, c7, c7 @ invalidate whole cache v4
++ mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4
++#endif
++ mov pc, lr
++
++__armv7_mmu_cache_off:
++ mrc p15, 0, r0, c1, c0
++#ifdef CONFIG_MMU
++ bic r0, r0, #0x000d
++#else
++ bic r0, r0, #0x000c
++#endif
++ mcr p15, 0, r0, c1, c0 @ turn MMU and cache off
++ mov r12, lr
++ bl __armv7_mmu_cache_flush
++ mov r0, #0
++#ifdef CONFIG_MMU
++ mcr p15, 0, r0, c8, c7, 0 @ invalidate whole TLB
++#endif
++ mcr p15, 0, r0, c7, c5, 6 @ invalidate BTC
++ mcr p15, 0, r0, c7, c10, 4 @ DSB
++ mcr p15, 0, r0, c7, c5, 4 @ ISB
++ mov pc, r12
++
++__arm6_mmu_cache_off:
++ mov r0, #0x00000030 @ ARM6 control reg.
++ b __armv3_mmu_cache_off
++
++__arm7_mmu_cache_off:
++ mov r0, #0x00000070 @ ARM7 control reg.
++ b __armv3_mmu_cache_off
++
++__armv3_mmu_cache_off:
++ mcr p15, 0, r0, c1, c0, 0 @ turn MMU and cache off
++ mov r0, #0
++ mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
++ mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3
++ mov pc, lr
++
++/*
++ * Clean and flush the cache to maintain consistency.
++ *
++ * On exit,
++ * r1, r2, r3, r9, r11, r12 corrupted
++ * This routine must preserve:
++ * r0, r4, r5, r6, r7
++ */
++ .align 5
++cache_clean_flush:
++ mov r3, #16
++ b call_cache_fn
++
++__armv4_mpu_cache_flush:
++ mov r2, #1
++ mov r3, #0
++ mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
++ mov r1, #7 << 5 @ 8 segments
++1: orr r3, r1, #63 << 26 @ 64 entries
++2: mcr p15, 0, r3, c7, c14, 2 @ clean & invalidate D index
++ subs r3, r3, #1 << 26
++ bcs 2b @ entries 63 to 0
++ subs r1, r1, #1 << 5
++ bcs 1b @ segments 7 to 0
++
++ teq r2, #0
++ mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
++ mcr p15, 0, ip, c7, c10, 4 @ drain WB
++ mov pc, lr
++
++__fa526_cache_flush:
++ mov r1, #0
++ mcr p15, 0, r1, c7, c14, 0 @ clean and invalidate D cache
++ mcr p15, 0, r1, c7, c5, 0 @ flush I cache
++ mcr p15, 0, r1, c7, c10, 4 @ drain WB
++ mov pc, lr
++
++__armv6_mmu_cache_flush:
++ mov r1, #0
++ mcr p15, 0, r1, c7, c14, 0 @ clean+invalidate D
++ mcr p15, 0, r1, c7, c5, 0 @ invalidate I+BTB
++ mcr p15, 0, r1, c7, c15, 0 @ clean+invalidate unified
++ mcr p15, 0, r1, c7, c10, 4 @ drain WB
++ mov pc, lr
++
++__armv7_mmu_cache_flush:
++ mrc p15, 0, r10, c0, c1, 5 @ read ID_MMFR1
++ tst r10, #0xf << 16 @ hierarchical cache (ARMv7)
++ mov r10, #0
++ beq hierarchical
++ mcr p15, 0, r10, c7, c14, 0 @ clean+invalidate D
++ b iflush
++hierarchical:
++ mcr p15, 0, r10, c7, c10, 5 @ DMB
++ stmfd sp!, {r0-r7, r9-r11}
++ mrc p15, 1, r0, c0, c0, 1 @ read clidr
++ ands r3, r0, #0x7000000 @ extract loc from clidr
++ mov r3, r3, lsr #23 @ left align loc bit field
++ beq finished @ if loc is 0, then no need to clean
++ mov r10, #0 @ start clean at cache level 0
++loop1:
++ add r2, r10, r10, lsr #1 @ work out 3x current cache level
++ mov r1, r0, lsr r2 @ extract cache type bits from clidr
++ and r1, r1, #7 @ mask of the bits for current cache only
++ cmp r1, #2 @ see what cache we have at this level
++ blt skip @ skip if no cache, or just i-cache
++ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
++ mcr p15, 0, r10, c7, c5, 4 @ isb to sych the new cssr&csidr
++ mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
++ and r2, r1, #7 @ extract the length of the cache lines
++ add r2, r2, #4 @ add 4 (line length offset)
++ ldr r4, =0x3ff
++ ands r4, r4, r1, lsr #3 @ find maximum number on the way size
++ clz r5, r4 @ find bit position of way size increment
++ ldr r7, =0x7fff
++ ands r7, r7, r1, lsr #13 @ extract max number of the index size
++loop2:
++ mov r9, r4 @ create working copy of max way size
++loop3:
++ ARM( orr r11, r10, r9, lsl r5 ) @ factor way and cache number into r11
++ ARM( orr r11, r11, r7, lsl r2 ) @ factor index number into r11
++ THUMB( lsl r6, r9, r5 )
++ THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11
++ THUMB( lsl r6, r7, r2 )
++ THUMB( orr r11, r11, r6 ) @ factor index number into r11
++ mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way
++ subs r9, r9, #1 @ decrement the way
++ bge loop3
++ subs r7, r7, #1 @ decrement the index
++ bge loop2
++skip:
++ add r10, r10, #2 @ increment cache number
++ cmp r3, r10
++ bgt loop1
++finished:
++ ldmfd sp!, {r0-r7, r9-r11}
++ mov r10, #0 @ swith back to cache level 0
++ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
++iflush:
++ mcr p15, 0, r10, c7, c10, 4 @ DSB
++ mcr p15, 0, r10, c7, c5, 0 @ invalidate I+BTB
++ mcr p15, 0, r10, c7, c10, 4 @ DSB
++ mcr p15, 0, r10, c7, c5, 4 @ ISB
++ mov pc, lr
++
++__armv5tej_mmu_cache_flush:
++1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate D cache
++ bne 1b
++ mcr p15, 0, r0, c7, c5, 0 @ flush I cache
++ mcr p15, 0, r0, c7, c10, 4 @ drain WB
++ mov pc, lr
++
++__armv4_mmu_cache_flush:
++ mov r2, #64*1024 @ default: 32K dcache size (*2)
++ mov r11, #32 @ default: 32 byte line size
++ mrc p15, 0, r3, c0, c0, 1 @ read cache type
++ teq r3, r9 @ cache ID register present?
++ beq no_cache_id
++ mov r1, r3, lsr #18
++ and r1, r1, #7
++ mov r2, #1024
++ mov r2, r2, lsl r1 @ base dcache size *2
++ tst r3, #1 << 14 @ test M bit
++ addne r2, r2, r2, lsr #1 @ +1/2 size if M == 1
++ mov r3, r3, lsr #12
++ and r3, r3, #3
++ mov r11, #8
++ mov r11, r11, lsl r3 @ cache line size in bytes
++no_cache_id:
++ mov r1, pc
++ bic r1, r1, #63 @ align to longest cache line
++ add r2, r1, r2
++1:
++ ARM( ldr r3, [r1], r11 ) @ s/w flush D cache
++ THUMB( ldr r3, [r1] ) @ s/w flush D cache
++ THUMB( add r1, r1, r11 )
++ teq r1, r2
++ bne 1b
++
++ mcr p15, 0, r1, c7, c5, 0 @ flush I cache
++ mcr p15, 0, r1, c7, c6, 0 @ flush D cache
++ mcr p15, 0, r1, c7, c10, 4 @ drain WB
++ mov pc, lr
++
++__armv3_mmu_cache_flush:
++__armv3_mpu_cache_flush:
++ mov r1, #0
++ mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3
++ mov pc, lr
++
++/*
++ * Various debugging routines for printing hex characters and
++ * memory, which again must be relocatable.
++ */
++#ifdef DEBUG
++ .align 2
++ .type phexbuf,#object
++phexbuf: .space 12
++ .size phexbuf, . - phexbuf
++
++phex: adr r3, phexbuf
++ mov r2, #0
++ strb r2, [r3, r1]
++1: subs r1, r1, #1
++ movmi r0, r3
++ bmi puts
++ and r2, r0, #15
++ mov r0, r0, lsr #4
++ cmp r2, #10
++ addge r2, r2, #7
++ add r2, r2, #'0'
++ strb r2, [r3, r1]
++ b 1b
++
++puts: loadsp r3, r1
++1: ldrb r2, [r0], #1
++ teq r2, #0
++ moveq pc, lr
++2: writeb r2, r3
++ mov r1, #0x00020000
++3: subs r1, r1, #1
++ bne 3b
++ teq r2, #'\n'
++ moveq r2, #'\r'
++ beq 2b
++ teq r0, #0
++ bne 1b
++ mov pc, lr
++putc:
++ mov r2, r0
++ mov r0, #0
++ loadsp r3, r1
++ b 2b
++
++memdump: mov r12, r0
++ mov r10, lr
++ mov r11, #0
++2: mov r0, r11, lsl #2
++ add r0, r0, r12
++ mov r1, #8
++ bl phex
++ mov r0, #':'
++ bl putc
++1: mov r0, #' '
++ bl putc
++ ldr r0, [r12, r11, lsl #2]
++ mov r1, #8
++ bl phex
++ and r0, r11, #7
++ teq r0, #3
++ moveq r0, #' '
++ bleq putc
++ and r0, r11, #7
++ add r11, r11, #1
++ teq r0, #7
++ bne 1b
++ mov r0, #'\n'
++ bl putc
++ cmp r11, #64
++ blt 2b
++ mov pc, r10
++#endif
++
++ .ltorg
++reloc_end:
++
++ .align
++ .section ".stack", "w"
++user_stack: .space 4096
+diff -rupN linux-2.6.35.11/arch/arm/boot/compressed/head-str8100.S linux-2.6.35.11-ts7500/arch/arm/boot/compressed/head-str8100.S
+--- linux-2.6.35.11/arch/arm/boot/compressed/head-str8100.S 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/boot/compressed/head-str8100.S 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,7 @@
++#include <asm/mach-types.h>
++
++ .section ".start", "ax"
++
++__str8100_start:
++ mov r7, #(MACH_TYPE_STR8100 & 0xFF00)
++ orr r7, r7, #(MACH_TYPE_STR8100 & 0x00FF)
+diff -rupN linux-2.6.35.11/arch/arm/boot/compressed/head-str9100.S linux-2.6.35.11-ts7500/arch/arm/boot/compressed/head-str9100.S
+--- linux-2.6.35.11/arch/arm/boot/compressed/head-str9100.S 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/boot/compressed/head-str9100.S 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,7 @@
++#include <asm/mach-types.h>
++
++ .section ".start", "ax"
++
++__str9100_start:
++ mov r7, #(MACH_TYPE_STR9100 & 0xFF00)
++ orr r7, r7, #(MACH_TYPE_STR9100 & 0x00FF)
+diff -rupN linux-2.6.35.11/arch/arm/boot/compressed/Makefile linux-2.6.35.11-ts7500/arch/arm/boot/compressed/Makefile
+--- linux-2.6.35.11/arch/arm/boot/compressed/Makefile 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/boot/compressed/Makefile 2011-03-14 11:18:24.000000000 -0400
+@@ -48,6 +48,14 @@ else
+ endif
+ endif
+
++ifeq ($(CONFIG_ARCH_STR9100),y)
++OBJS += head-str9100.o
++endif
++
++ifeq ($(CONFIG_ARCH_STR8100),y)
++OBJS += head-str8100.o
++endif
++
+ #
+ # We now have a PIC decompressor implementation. Decompressors running
+ # from RAM should not define ZTEXTADDR. Decompressors running directly
+diff -rupN linux-2.6.35.11/arch/arm/boot/compressed/Makefile.orig linux-2.6.35.11-ts7500/arch/arm/boot/compressed/Makefile.orig
+--- linux-2.6.35.11/arch/arm/boot/compressed/Makefile.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/boot/compressed/Makefile.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,129 @@
++#
++# linux/arch/arm/boot/compressed/Makefile
++#
++# create a compressed vmlinuz image from the original vmlinux
++#
++
++HEAD = head.o
++OBJS = misc.o decompress.o
++FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c
++
++#
++# Architecture dependencies
++#
++ifeq ($(CONFIG_ARCH_ACORN),y)
++OBJS += ll_char_wr.o font.o
++endif
++
++ifeq ($(CONFIG_ARCH_SHARK),y)
++OBJS += head-shark.o ofw-shark.o
++endif
++
++ifeq ($(CONFIG_ARCH_L7200),y)
++OBJS += head-l7200.o
++endif
++
++ifeq ($(CONFIG_ARCH_P720T),y)
++# Borrow this code from SA1100
++OBJS += head-sa1100.o
++endif
++
++ifeq ($(CONFIG_ARCH_SA1100),y)
++OBJS += head-sa1100.o
++endif
++
++ifeq ($(CONFIG_CPU_XSCALE),y)
++OBJS += head-xscale.o
++endif
++
++ifeq ($(CONFIG_PXA_SHARPSL),y)
++OBJS += head-sharpsl.o
++endif
++
++ifeq ($(CONFIG_CPU_ENDIAN_BE32),y)
++ifeq ($(CONFIG_CPU_CP15),y)
++OBJS += big-endian.o
++else
++# The endian should be set by h/w design.
++endif
++endif
++
++#
++# We now have a PIC decompressor implementation. Decompressors running
++# from RAM should not define ZTEXTADDR. Decompressors running directly
++# from ROM or Flash must define ZTEXTADDR (preferably via the config)
++# FIXME: Previous assignment to ztextaddr-y is lost here. See SHARK
++ifeq ($(CONFIG_ZBOOT_ROM),y)
++ZTEXTADDR := $(CONFIG_ZBOOT_ROM_TEXT)
++ZBSSADDR := $(CONFIG_ZBOOT_ROM_BSS)
++else
++ZTEXTADDR := 0
++ZBSSADDR := ALIGN(4)
++endif
++
++SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
++
++suffix_$(CONFIG_KERNEL_GZIP) = gzip
++suffix_$(CONFIG_KERNEL_LZO) = lzo
++suffix_$(CONFIG_KERNEL_LZMA) = lzma
++
++targets := vmlinux vmlinux.lds \
++ piggy.$(suffix_y) piggy.$(suffix_y).o \
++ font.o font.c head.o misc.o $(OBJS)
++
++# Make sure files are removed during clean
++extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S
++
++ifeq ($(CONFIG_FUNCTION_TRACER),y)
++ORIG_CFLAGS := $(KBUILD_CFLAGS)
++KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
++endif
++
++EXTRA_CFLAGS := -fpic -fno-builtin
++EXTRA_AFLAGS := -Wa,-march=all
++
++# Supply ZRELADDR, INITRD_PHYS and PARAMS_PHYS to the decompressor via
++# linker symbols. We only define initrd_phys and params_phys if the
++# machine class defined the corresponding makefile variable.
++LDFLAGS_vmlinux := --defsym zreladdr=$(ZRELADDR)
++ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
++LDFLAGS_vmlinux += --be8
++endif
++ifneq ($(INITRD_PHYS),)
++LDFLAGS_vmlinux += --defsym initrd_phys=$(INITRD_PHYS)
++endif
++ifneq ($(PARAMS_PHYS),)
++LDFLAGS_vmlinux += --defsym params_phys=$(PARAMS_PHYS)
++endif
++# ?
++LDFLAGS_vmlinux += -p
++# Report unresolved symbol references
++LDFLAGS_vmlinux += --no-undefined
++# Delete all temporary local symbols
++LDFLAGS_vmlinux += -X
++# Next argument is a linker script
++LDFLAGS_vmlinux += -T
++
++# For __aeabi_uidivmod
++lib1funcs = $(obj)/lib1funcs.o
++
++$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE
++ $(call cmd,shipped)
++
++$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
++ $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
++ $(call if_changed,ld)
++ @:
++
++$(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE
++ $(call if_changed,$(suffix_y))
++
++$(obj)/piggy.$(suffix_y).o: $(obj)/piggy.$(suffix_y) FORCE
++
++CFLAGS_font.o := -Dstatic=
++
++$(obj)/font.c: $(FONTC)
++ $(call cmd,shipped)
++
++$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config
++ @sed "$(SEDFLAGS)" < $< > $@
+diff -rupN linux-2.6.35.11/arch/arm/boot/compressed/misc.c linux-2.6.35.11-ts7500/arch/arm/boot/compressed/misc.c
+--- linux-2.6.35.11/arch/arm/boot/compressed/misc.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/boot/compressed/misc.c 2011-03-14 11:18:24.000000000 -0400
+@@ -101,8 +101,11 @@ static void icedcc_putc(int ch)
+ #endif
+
+ #define putc(ch) icedcc_putc(ch)
++#define flush() do { } while (0)
+ #endif
+
++#if defined(CONFIG_ARCH_STR8100) || defined(CONFIG_ARCH_STR9100)
++#else
+ static void putstr(const char *ptr)
+ {
+ char c;
+@@ -115,6 +118,7 @@ static void putstr(const char *ptr)
+
+ flush();
+ }
++#endif
+
+ #endif
+
+@@ -188,24 +192,38 @@ extern void do_decompress(u8 *input, int
+
+ #ifndef STANDALONE_DEBUG
+
++
+ unsigned long
+ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
+ unsigned long free_mem_ptr_end_p,
+ int arch_id)
+ {
++ extern void *foobar(int);
+ unsigned char *tmp;
+
+ output_data = (unsigned char *)output_start;
+ free_mem_ptr = free_mem_ptr_p;
+ free_mem_end_ptr = free_mem_ptr_end_p;
+ __machine_arch_type = arch_id;
+-
++
++
++ //putstr("\n\rfree_mem_ptr = 0x"); ser_puts_hex32((unsigned long)free_mem_ptr);
++ //putstr("\n\rfree_mem_end_ptr = 0x"); ser_puts_hex32((unsigned long)free_mem_end_ptr);
++ //putstr("\n\r__machine_arch_type = 0x"); ser_puts_hex32((unsigned long)__machine_arch_type);
++ //putstr("\n\r");
++
+ arch_decomp_setup();
+
+ tmp = (unsigned char *) (((unsigned long)input_data_end) - 4);
+ output_ptr = get_unaligned_le32(tmp);
+
+ putstr("Uncompressing Linux...");
++
++ //putstr("\n\rinput_data = 0x"); ser_puts_hex32((unsigned long)input_data);
++ //putstr("\n\rinput_data_end = 0x"); ser_puts_hex32((unsigned long)input_data_end);
++ //putstr("\n\routput_data = 0x"); ser_puts_hex32((unsigned long)output_data);
++ //putstr("\n\r");
++
+ do_decompress(input_data, input_data_end - input_data,
+ output_data, error);
+ putstr(" done, booting the kernel.\n");
+diff -rupN linux-2.6.35.11/arch/arm/boot/compressed/misc.c.orig linux-2.6.35.11-ts7500/arch/arm/boot/compressed/misc.c.orig
+--- linux-2.6.35.11/arch/arm/boot/compressed/misc.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/boot/compressed/misc.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,228 @@
++/*
++ * misc.c
++ *
++ * This is a collection of several routines from gzip-1.0.3
++ * adapted for Linux.
++ *
++ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
++ *
++ * Modified for ARM Linux by Russell King
++ *
++ * Nicolas Pitre <nico at visuaide.com> 1999/04/14 :
++ * For this code to run directly from Flash, all constant variables must
++ * be marked with 'const' and all other variables initialized at run-time
++ * only. This way all non constant variables will end up in the bss segment,
++ * which should point to addresses in RAM and cleared to 0 on start.
++ * This allows for a much quicker boot time.
++ */
++
++unsigned int __machine_arch_type;
++
++#define _LINUX_STRING_H_
++
++#include <linux/compiler.h> /* for inline */
++#include <linux/types.h> /* for size_t */
++#include <linux/stddef.h> /* for NULL */
++#include <linux/linkage.h>
++#include <asm/string.h>
++
++#include <asm/unaligned.h>
++
++#ifdef STANDALONE_DEBUG
++#define putstr printf
++#else
++
++static void putstr(const char *ptr);
++extern void error(char *x);
++
++#include <mach/uncompress.h>
++
++#ifdef CONFIG_DEBUG_ICEDCC
++
++#ifdef CONFIG_CPU_V6
++
++static void icedcc_putc(int ch)
++{
++ int status, i = 0x4000000;
++
++ do {
++ if (--i < 0)
++ return;
++
++ asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (status));
++ } while (status & (1 << 29));
++
++ asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch));
++}
++
++#elif defined(CONFIG_CPU_V7)
++
++static void icedcc_putc(int ch)
++{
++ asm(
++ "wait: mrc p14, 0, pc, c0, c1, 0 \n\
++ bcs wait \n\
++ mcr p14, 0, %0, c0, c5, 0 "
++ : : "r" (ch));
++}
++
++#elif defined(CONFIG_CPU_XSCALE)
++
++static void icedcc_putc(int ch)
++{
++ int status, i = 0x4000000;
++
++ do {
++ if (--i < 0)
++ return;
++
++ asm volatile ("mrc p14, 0, %0, c14, c0, 0" : "=r" (status));
++ } while (status & (1 << 28));
++
++ asm("mcr p14, 0, %0, c8, c0, 0" : : "r" (ch));
++}
++
++#else
++
++static void icedcc_putc(int ch)
++{
++ int status, i = 0x4000000;
++
++ do {
++ if (--i < 0)
++ return;
++
++ asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
++ } while (status & 2);
++
++ asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));
++}
++
++#endif
++
++#define putc(ch) icedcc_putc(ch)
++#endif
++
++static void putstr(const char *ptr)
++{
++ char c;
++
++ while ((c = *ptr++) != '\0') {
++ if (c == '\n')
++ putc('\r');
++ putc(c);
++ }
++
++ flush();
++}
++
++#endif
++
++void *memcpy(void *__dest, __const void *__src, size_t __n)
++{
++ int i = 0;
++ unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
++
++ for (i = __n >> 3; i > 0; i--) {
++ *d++ = *s++;
++ *d++ = *s++;
++ *d++ = *s++;
++ *d++ = *s++;
++ *d++ = *s++;
++ *d++ = *s++;
++ *d++ = *s++;
++ *d++ = *s++;
++ }
++
++ if (__n & 1 << 2) {
++ *d++ = *s++;
++ *d++ = *s++;
++ *d++ = *s++;
++ *d++ = *s++;
++ }
++
++ if (__n & 1 << 1) {
++ *d++ = *s++;
++ *d++ = *s++;
++ }
++
++ if (__n & 1)
++ *d++ = *s++;
++
++ return __dest;
++}
++
++/*
++ * gzip delarations
++ */
++extern char input_data[];
++extern char input_data_end[];
++
++unsigned char *output_data;
++unsigned long output_ptr;
++
++unsigned long free_mem_ptr;
++unsigned long free_mem_end_ptr;
++
++#ifndef arch_error
++#define arch_error(x)
++#endif
++
++void error(char *x)
++{
++ arch_error(x);
++
++ putstr("\n\n");
++ putstr(x);
++ putstr("\n\n -- System halted");
++
++ while(1); /* Halt */
++}
++
++asmlinkage void __div0(void)
++{
++ error("Attempting division by 0!");
++}
++
++extern void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));
++
++#ifndef STANDALONE_DEBUG
++
++unsigned long
++decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
++ unsigned long free_mem_ptr_end_p,
++ int arch_id)
++{
++ unsigned char *tmp;
++
++ output_data = (unsigned char *)output_start;
++ free_mem_ptr = free_mem_ptr_p;
++ free_mem_end_ptr = free_mem_ptr_end_p;
++ __machine_arch_type = arch_id;
++
++ arch_decomp_setup();
++
++ tmp = (unsigned char *) (((unsigned long)input_data_end) - 4);
++ output_ptr = get_unaligned_le32(tmp);
++
++ putstr("Uncompressing Linux...");
++ do_decompress(input_data, input_data_end - input_data,
++ output_data, error);
++ putstr(" done, booting the kernel.\n");
++ return output_ptr;
++}
++#else
++
++char output_buffer[1500*1024];
++
++int main()
++{
++ output_data = output_buffer;
++
++ putstr("Uncompressing Linux...");
++ decompress(input_data, input_data_end - input_data,
++ NULL, NULL, output_data, NULL, error);
++ putstr("done.\n");
++ return 0;
++}
++#endif
+diff -rupN linux-2.6.35.11/arch/arm/boot/Makefile linux-2.6.35.11-ts7500/arch/arm/boot/Makefile
+--- linux-2.6.35.11/arch/arm/boot/Makefile 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/boot/Makefile 2011-03-14 11:18:24.000000000 -0400
+@@ -24,8 +24,10 @@ endif
+ ZRELADDR := $(zreladdr-y)
+ PARAMS_PHYS := $(params_phys-y)
+ INITRD_PHYS := $(initrd_phys-y)
++# scott.kernel
++KERNEL_PHYS := $(kernel_phys-y)
+
+-export ZRELADDR INITRD_PHYS PARAMS_PHYS
++export ZRELADDR INITRD_PHYS KERNEL_PHYS PARAMS_PHYS
+
+ targets := Image zImage xipImage bootpImage uImage
+
+diff -rupN linux-2.6.35.11/arch/arm/configs/ts7500_defconfig linux-2.6.35.11-ts7500/arch/arm/configs/ts7500_defconfig
+--- linux-2.6.35.11/arch/arm/configs/ts7500_defconfig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/configs/ts7500_defconfig 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,1423 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.36
++# Wed Nov 10 09:28:19 2010
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
++CONFIG_HAVE_PROC_CPU=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_NEED_DMA_MAP_STATE=y
++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++CONFIG_CONSTRUCTORS=y
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_CROSS_COMPILE=""
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_HAVE_KERNEL_GZIP=y
++CONFIG_HAVE_KERNEL_LZMA=y
++CONFIG_HAVE_KERNEL_LZO=y
++CONFIG_KERNEL_GZIP=y
++# CONFIG_KERNEL_LZMA is not set
++# CONFIG_KERNEL_LZO is not set
++# CONFIG_SWAP is not set
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++
++#
++# RCU Subsystem
++#
++CONFIG_TREE_RCU=y
++# CONFIG_TREE_PREEMPT_RCU is not set
++# CONFIG_TINY_RCU is not set
++# CONFIG_RCU_TRACE is not set
++CONFIG_RCU_FANOUT=32
++# CONFIG_RCU_FANOUT_EXACT is not set
++# CONFIG_TREE_RCU_TRACE is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=16
++# CONFIG_CGROUPS is not set
++CONFIG_SYSFS_DEPRECATED=y
++CONFIG_SYSFS_DEPRECATED_V2=y
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_RD_GZIP=y
++# CONFIG_RD_BZIP2 is not set
++# CONFIG_RD_LZMA is not set
++# CONFIG_RD_LZO is not set
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++# CONFIG_SYSCTL_SYSCALL is not set
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++CONFIG_HAVE_PERF_EVENTS=y
++CONFIG_PERF_USE_VMALLOC=y
++
++#
++# Kernel Performance Events And Counters
++#
++# CONFIG_PERF_EVENTS is not set
++# CONFIG_PERF_COUNTERS is not set
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_PCI_QUIRKS=y
++CONFIG_COMPAT_BRK=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++# CONFIG_PROFILING is not set
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
++
++#
++# GCOV-based kernel profiling
++#
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_SLABINFO=y
++CONFIG_RT_MUTEXES=y
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++# CONFIG_MODULE_FORCE_LOAD is not set
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_BLOCK=y
++# CONFIG_LBDAF is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_DEADLINE=y
++# CONFIG_IOSCHED_CFQ is not set
++CONFIG_DEFAULT_DEADLINE=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="deadline"
++# CONFIG_INLINE_SPIN_TRYLOCK is not set
++# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
++# CONFIG_INLINE_SPIN_LOCK is not set
++# CONFIG_INLINE_SPIN_LOCK_BH is not set
++# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
++# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
++# CONFIG_INLINE_SPIN_UNLOCK is not set
++# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
++# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
++# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
++# CONFIG_INLINE_READ_TRYLOCK is not set
++# CONFIG_INLINE_READ_LOCK is not set
++# CONFIG_INLINE_READ_LOCK_BH is not set
++# CONFIG_INLINE_READ_LOCK_IRQ is not set
++# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
++# CONFIG_INLINE_READ_UNLOCK is not set
++# CONFIG_INLINE_READ_UNLOCK_BH is not set
++# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
++# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
++# CONFIG_INLINE_WRITE_TRYLOCK is not set
++# CONFIG_INLINE_WRITE_LOCK is not set
++# CONFIG_INLINE_WRITE_LOCK_BH is not set
++# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
++# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
++# CONFIG_INLINE_WRITE_UNLOCK is not set
++# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
++# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
++# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
++# CONFIG_MUTEX_SPIN_ON_OWNER is not set
++# CONFIG_FREEZER is not set
++
++#
++# System Type
++#
++CONFIG_MMU=y
++# CONFIG_ARCH_STR9100 is not set
++CONFIG_ARCH_STR8100=y
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_VEXPRESS is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_BCMRING is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CNS3XXX is not set
++# CONFIG_ARCH_GEMINI is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_STMP3XXX is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_DOVE is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_LOKI is not set
++# CONFIG_ARCH_LPC32XX is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_MMP is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_W90X900 is not set
++# CONFIG_ARCH_NUC93X is not set
++# CONFIG_ARCH_TEGRA is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_MSM is not set
++# CONFIG_ARCH_SHMOBILE is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_S3C64XX is not set
++# CONFIG_ARCH_S5P6440 is not set
++# CONFIG_ARCH_S5P6442 is not set
++# CONFIG_ARCH_S5PC100 is not set
++# CONFIG_ARCH_S5PV210 is not set
++# CONFIG_ARCH_S5PV310 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_U300 is not set
++# CONFIG_ARCH_U8500 is not set
++# CONFIG_ARCH_NOMADIK is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_PLAT_SPEAR is not set
++CONFIG_CONSOLE_BAUD_RATE=115200
++
++#
++# STR8100 Options
++#
++CONFIG_VIC_INTERRUPT=y
++# CONFIG_STR8100_DRAM_16M is not set
++# CONFIG_STR8100_DRAM_32M is not set
++CONFIG_STR8100_DRAM_64M=y
++CONFIG_STR8100_PCI33M=y
++# CONFIG_STR8100_PCI66M is not set
++# CONFIG_STR8100_DMA is not set
++# CONFIG_STR8100_HSDMA is not set
++CONFIG_STR8100_INFO=y
++# CONFIG_STR8100_USBD_REBOOT_INTHANDLER is not set
++# CONFIG_STR8100_I2S is not set
++# CONFIG_STR8100_I2S_DEMO is not set
++# CONFIG_STR8100_I2S_WM8772_DEMO is not set
++# CONFIG_LE88221_CONTROL is not set
++# CONFIG_STR8100_PCM_LEGERITY_2PHONE_DEMO is not set
++# CONFIG_STR8100_RTC is not set
++CONFIG_STR8100_GPIO=y
++CONFIG_STR8100_GPIO_INTERRUPT=y
++# CONFIG_STR8100_GPIO_GENERIC_INTERFACE is not set
++
++#
++# Flash MAP
++#
++# CONFIG_STR8100_FLASH_PART is not set
++
++#
++# Third Party Support
++#
++# CONFIG_STR8100_EWC_SUPPORT is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_FA526=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4=y
++CONFIG_CPU_PABRT_LEGACY=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_CACHE_FA=y
++CONFIG_CPU_COPY_FA=y
++CONFIG_CPU_TLB_FA=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++
++#
++# Processor Features
++#
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++CONFIG_CPU_FA_BTB=y
++# CONFIG_CPU_FA_WB_DISABLE is not set
++# CONFIG_CPU_BPREDICT_DISABLE is not set
++CONFIG_ARM_L1_CACHE_SHIFT=5
++
++#
++# Bus support
++#
++CONFIG_PCI=y
++CONFIG_PCI_SYSCALL=y
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCI_STUB is not set
++# CONFIG_PCI_IOV is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_VMSPLIT_3G=y
++# CONFIG_VMSPLIT_2G is not set
++# CONFIG_VMSPLIT_1G is not set
++CONFIG_PAGE_OFFSET=0xC0000000
++# CONFIG_PREEMPT_NONE is not set
++# CONFIG_PREEMPT_VOLUNTARY is not set
++CONFIG_PREEMPT=y
++CONFIG_HZ=100
++# CONFIG_AEABI is not set
++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
++# CONFIG_HIGHMEM is not set
++# CONFIG_SPARSE_IRQ is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_HAVE_MEMBLOCK=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=999999
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_KSM is not set
++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
++CONFIG_FORCE_MAX_ZONEORDER=11
++CONFIG_ALIGNMENT_TRAP=y
++# CONFIG_UACCESS_WITH_MEMCPY is not set
++# CONFIG_CC_STACKPROTECTOR is not set
++# CONFIG_DEPRECATED_PARAM_STRUCT is not set
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="root=/dev/ram0 init=/linuxrc lpj=958464 console=null"
++# CONFIG_CMDLINE_FORCE is not set
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++# CONFIG_AUTO_ZRELADDR is not set
++
++#
++# CPU Power Management
++#
++# CONFIG_CPU_IDLE is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_HAVE_AOUT=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++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_IP_MROUTE 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_INET_XFRM_TUNNEL is not set
++CONFIG_INET_TUNNEL=m
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++CONFIG_INET_LRO=y
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++CONFIG_IPV6=m
++# CONFIG_IPV6_PRIVACY is not set
++# CONFIG_IPV6_ROUTER_PREF is not set
++# CONFIG_IPV6_OPTIMISTIC_DAD is not set
++# CONFIG_INET6_AH is not set
++# CONFIG_INET6_ESP is not set
++# CONFIG_INET6_IPCOMP is not set
++# CONFIG_IPV6_MIP6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++CONFIG_INET6_XFRM_MODE_TRANSPORT=m
++CONFIG_INET6_XFRM_MODE_TUNNEL=m
++CONFIG_INET6_XFRM_MODE_BEET=m
++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
++CONFIG_IPV6_SIT=m
++# CONFIG_IPV6_SIT_6RD is not set
++CONFIG_IPV6_NDISC_NODETYPE=y
++# CONFIG_IPV6_TUNNEL is not set
++# CONFIG_IPV6_MULTIPLE_TABLES is not set
++# CONFIG_IPV6_MROUTE is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_RDS is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_L2TP is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA 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_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_PHONET is not set
++# CONFIG_IEEE802154 is not set
++# CONFIG_NET_SCHED is not set
++# CONFIG_DCB is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++CONFIG_WIRELESS=y
++# CONFIG_CFG80211 is not set
++# CONFIG_LIB80211 is not set
++
++#
++# CFG80211 needs to be enabled for MAC80211
++#
++
++#
++# Some wireless drivers require a rate control algorithm
++#
++# CONFIG_WIMAX is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++# CONFIG_CAIF is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++# CONFIG_DEVTMPFS is not set
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=m
++CONFIG_FIRMWARE_IN_KERNEL=y
++CONFIG_EXTRA_FIRMWARE=""
++# CONFIG_SYS_HYPERVISOR is not set
++CONFIG_CONNECTOR=m
++# CONFIG_MTD is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# 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_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_DRBD is not set
++CONFIG_BLK_DEV_NBD=y
++# CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=4
++CONFIG_BLK_DEV_RAM_SIZE=16384
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MISC_DEVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI_MOD=m
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=m
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_SCSI_PROC_FS is not set
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=m
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=m
++# CONFIG_CHR_DEV_SCH is not set
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
++
++#
++# SCSI Transports
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++# CONFIG_SCSI_DH is not set
++# CONFIG_SCSI_OSD_INITIATOR is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++
++#
++# You can enable one or both FireWire driver stacks.
++#
++
++#
++# The newer stack is recommended.
++#
++# CONFIG_FIREWIRE is not set
++# CONFIG_IEEE1394 is not set
++# CONFIG_FIREWIRE_NOSY is not set
++# CONFIG_I2O is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_ARCNET is not set
++# CONFIG_PHYLIB is not set
++# CONFIG_NET_ETHERNET is not set
++CONFIG_NETDEV_1000=y
++# CONFIG_FAST_BRIDGE is not set
++# CONFIG_ACENIC is not set
++# CONFIG_DL2K is not set
++# CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_IP1000 is not set
++# CONFIG_IGB is not set
++# CONFIG_IGBVF 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_SKGE is not set
++# CONFIG_SKY2 is not set
++# CONFIG_VIA_VELOCITY is not set
++# CONFIG_TIGON3 is not set
++# CONFIG_BNX2 is not set
++# CONFIG_CNIC is not set
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++# CONFIG_ATL1E is not set
++# CONFIG_ATL1C is not set
++# CONFIG_JME is not set
++CONFIG_NETDEV_10000=y
++# CONFIG_CHELSIO_T1 is not set
++CONFIG_CHELSIO_T3_DEPENDS=y
++# CONFIG_CHELSIO_T3 is not set
++CONFIG_CHELSIO_T4_DEPENDS=y
++# CONFIG_CHELSIO_T4 is not set
++CONFIG_CHELSIO_T4VF_DEPENDS=y
++# CONFIG_CHELSIO_T4VF is not set
++# CONFIG_ENIC is not set
++# CONFIG_IXGBE is not set
++# CONFIG_IXGB is not set
++# CONFIG_S2IO is not set
++# CONFIG_VXGE is not set
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_EN is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
++# CONFIG_BNX2X is not set
++# CONFIG_QLCNIC is not set
++# CONFIG_QLGE is not set
++# CONFIG_SFC is not set
++# CONFIG_BE2NET is not set
++
++#
++# CNS2100 NIC support
++#
++CONFIG_STAR_NIC=y
++CONFIG_STAR_NIC_PHY_INTERNAL_PHY=y
++# CONFIG_STAR_NIC_PHY_VSC8601 is not set
++# CONFIG_STAR_NIC_PHY_IP101A is not set
++# CONFIG_STAR_NIC_PHY_IP1001 is not set
++# CONFIG_TR is not set
++CONFIG_WLAN=y
++# CONFIG_ATMEL is not set
++# CONFIG_PRISM54 is not set
++# CONFIG_USB_ZD1201 is not set
++# CONFIG_HOSTAP is not set
++
++#
++# Enable WiMAX (Networking options) to see the WiMAX drivers
++#
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_USB_IPHETH is not set
++# CONFIG_WAN is not set
++
++#
++# CAIF transport drivers
++#
++# CONFIG_FDDI is not set
++# CONFIG_HIPPI is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_VMXNET3 is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=m
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++# CONFIG_INPUT_SPARSEKMAP is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=m
++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_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=m
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_OPENCORES is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=m
++CONFIG_MOUSE_PS2_ALPS=y
++CONFIG_MOUSE_PS2_LOGIPS2PP=y
++CONFIG_MOUSE_PS2_SYNAPTICS=y
++CONFIG_MOUSE_PS2_TRACKPOINT=y
++# CONFIG_MOUSE_PS2_ELANTECH is not set
++# CONFIG_MOUSE_PS2_SENTELIC is not set
++# CONFIG_MOUSE_PS2_TOUCHKIT is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_APPLETOUCH is not set
++# CONFIG_MOUSE_BCM5974 is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=m
++CONFIG_SERIO_SERPORT=m
++# CONFIG_SERIO_PCIPS2 is not set
++CONFIG_SERIO_LIBPS2=m
++# CONFIG_SERIO_RAW is not set
++# CONFIG_SERIO_ALTERA_PS2 is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++CONFIG_DEVKMEM=y
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_N_GSM is not set
++# CONFIG_NOZOMI is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++# CONFIG_SERIAL_8250_PCI is not set
++CONFIG_SERIAL_8250_NR_UARTS=2
++CONFIG_SERIAL_8250_RUNTIME_UARTS=2
++# CONFIG_SERIAL_8250_EXTENDED is not set
++# CONFIG_SERIAL_8250_CTSRTS is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_MAX3100 is not set
++# CONFIG_SERIAL_MAX3107 is not set
++# CONFIG_SERIAL_MFD_HSU is not set
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_JSM is not set
++# CONFIG_SERIAL_TIMBERDALE is not set
++# CONFIG_SERIAL_ALTERA_JTAGUART is not set
++# CONFIG_SERIAL_ALTERA_UART is not set
++CONFIG_UNIX98_PTYS=y
++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_IPMI_HANDLER is not set
++CONFIG_HW_RANDOM=m
++# CONFIG_HW_RANDOM_TIMERIOMEM is not set
++# CONFIG_R3964 is not set
++# CONFIG_APPLICOM is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++CONFIG_DEVPORT=y
++# CONFIG_RAMOOPS is not set
++# CONFIG_I2C is not set
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BITBANG=y
++CONFIG_SPI_STR8100=y
++# CONFIG_SPI_XILINX is not set
++# CONFIG_SPI_DESIGNWARE is not set
++
++#
++# SPI Protocol Masters
++#
++# CONFIG_SPI_SPIDEV is not set
++# CONFIG_SPI_TLE62X0 is not set
++
++#
++# PPS support
++#
++# CONFIG_PPS is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++# CONFIG_WATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB=m
++CONFIG_SSB_SPROM=y
++CONFIG_SSB_PCIHOST_POSSIBLE=y
++CONFIG_SSB_PCIHOST=y
++# CONFIG_SSB_B43_PCI_BRIDGE is not set
++# CONFIG_SSB_SILENT is not set
++# CONFIG_SSB_DEBUG is not set
++CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
++CONFIG_SSB_DRIVER_PCICORE=y
++CONFIG_MFD_SUPPORT=y
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_MFD_MC13783 is not set
++# CONFIG_ABX500_CORE is not set
++# CONFIG_EZX_PCAP is not set
++# CONFIG_AB8500_CORE is not set
++# CONFIG_LPC_SCH is not set
++# CONFIG_MFD_RDC321X is not set
++# CONFIG_MFD_JANZ_CMODIO is not set
++# CONFIG_REGULATOR is not set
++# CONFIG_MEDIA_SUPPORT is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGA_ARB is not set
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++# CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=m
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=m
++# CONFIG_HID_PID is not set
++# CONFIG_USB_HIDDEV is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++
++#
++# Special HID drivers
++#
++# CONFIG_HID_3M_PCT is not set
++# CONFIG_HID_A4TECH is not set
++# CONFIG_HID_ACRUX_FF is not set
++# CONFIG_HID_APPLE is not set
++# CONFIG_HID_BELKIN is not set
++# CONFIG_HID_CANDO is not set
++# CONFIG_HID_CHERRY is not set
++# CONFIG_HID_CHICONY is not set
++# CONFIG_HID_CYPRESS is not set
++# CONFIG_HID_DRAGONRISE is not set
++# CONFIG_HID_EGALAX is not set
++# CONFIG_HID_EZKEY is not set
++# CONFIG_HID_KYE is not set
++# CONFIG_HID_GYRATION is not set
++# CONFIG_HID_TWINHAN is not set
++# CONFIG_HID_KENSINGTON is not set
++# CONFIG_HID_LOGITECH is not set
++# CONFIG_HID_MICROSOFT is not set
++# CONFIG_HID_MOSART is not set
++# CONFIG_HID_MONTEREY is not set
++# CONFIG_HID_NTRIG is not set
++# CONFIG_HID_ORTEK is not set
++# CONFIG_HID_PANTHERLORD is not set
++# CONFIG_HID_PETALYNX is not set
++# CONFIG_HID_PICOLCD is not set
++# CONFIG_HID_QUANTA is not set
++# CONFIG_HID_ROCCAT is not set
++# CONFIG_HID_ROCCAT_KONE is not set
++# CONFIG_HID_SAMSUNG is not set
++# CONFIG_HID_SONY is not set
++# CONFIG_HID_STANTUM is not set
++# CONFIG_HID_SUNPLUS is not set
++# CONFIG_HID_GREENASIA is not set
++# CONFIG_HID_SMARTJOYPLUS is not set
++# CONFIG_HID_TOPSEED is not set
++# CONFIG_HID_THRUSTMASTER is not set
++# CONFIG_HID_ZEROPLUS is not set
++# CONFIG_HID_ZYDACRON is not set
++CONFIG_USB_SUPPORT=y
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=m
++# CONFIG_USB_DEBUG is not set
++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++# CONFIG_USB_DEVICE_CLASS is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG_WHITELIST is not set
++# CONFIG_USB_OTG_BLACKLIST_HUB is not set
++# CONFIG_USB_MON is not set
++# CONFIG_USB_WUSB is not set
++# CONFIG_USB_WUSB_CBAF is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_C67X00_HCD is not set
++# CONFIG_USB_XHCI_HCD is not set
++CONFIG_USB_EHCI_HCD=m
++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++# CONFIG_USB_OXU210HP_HCD is not set
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_ISP1760_HCD is not set
++# CONFIG_USB_ISP1362_HCD is not set
++CONFIG_USB_OHCI_HCD=m
++# CONFIG_USB_OHCI_HCD_SSB is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++CONFIG_USB_UHCI_HCD=m
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++# CONFIG_USB_WHCI_HCD is not set
++# CONFIG_USB_HWA_HCD is not set
++# CONFIG_USB_MUSB_HDRC is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++# CONFIG_USB_WDM is not set
++# CONFIG_USB_TMC is not set
++
++#
++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
++#
++
++#
++# also be needed; see USB_STORAGE Help for more info
++#
++CONFIG_USB_STORAGE=m
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_ONETOUCH is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++
++#
++# USB port drivers
++#
++CONFIG_USB_SERIAL=m
++# CONFIG_USB_EZUSB is not set
++CONFIG_USB_SERIAL_GENERIC=y
++# CONFIG_USB_SERIAL_AIRCABLE is not set
++# CONFIG_USB_SERIAL_ARK3116 is not set
++# CONFIG_USB_SERIAL_BELKIN is not set
++# CONFIG_USB_SERIAL_CH341 is not set
++# CONFIG_USB_SERIAL_WHITEHEAT is not set
++# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
++# CONFIG_USB_SERIAL_CP210X is not set
++# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
++# CONFIG_USB_SERIAL_EMPEG is not set
++# CONFIG_USB_SERIAL_FTDI_SIO is not set
++# CONFIG_USB_SERIAL_FUNSOFT is not set
++# CONFIG_USB_SERIAL_VISOR is not set
++# CONFIG_USB_SERIAL_IPAQ is not set
++# CONFIG_USB_SERIAL_IR is not set
++# CONFIG_USB_SERIAL_EDGEPORT is not set
++# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
++# CONFIG_USB_SERIAL_GARMIN is not set
++# CONFIG_USB_SERIAL_IPW is not set
++# CONFIG_USB_SERIAL_IUU is not set
++# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
++# CONFIG_USB_SERIAL_KEYSPAN is not set
++# CONFIG_USB_SERIAL_KLSI is not set
++# CONFIG_USB_SERIAL_KOBIL_SCT is not set
++# CONFIG_USB_SERIAL_MCT_U232 is not set
++# CONFIG_USB_SERIAL_MOS7720 is not set
++# CONFIG_USB_SERIAL_MOS7840 is not set
++# CONFIG_USB_SERIAL_MOTOROLA is not set
++# CONFIG_USB_SERIAL_NAVMAN is not set
++# CONFIG_USB_SERIAL_PL2303 is not set
++# CONFIG_USB_SERIAL_OTI6858 is not set
++# CONFIG_USB_SERIAL_QCAUX is not set
++# CONFIG_USB_SERIAL_QUALCOMM is not set
++# CONFIG_USB_SERIAL_SPCP8X5 is not set
++# CONFIG_USB_SERIAL_HP4X is not set
++# CONFIG_USB_SERIAL_SAFE is not set
++# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
++# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
++# CONFIG_USB_SERIAL_SYMBOL is not set
++# CONFIG_USB_SERIAL_TI is not set
++# CONFIG_USB_SERIAL_CYBERJACK is not set
++# CONFIG_USB_SERIAL_XIRCOM is not set
++# CONFIG_USB_SERIAL_OPTION is not set
++# CONFIG_USB_SERIAL_OMNINET is not set
++# CONFIG_USB_SERIAL_OPTICON is not set
++# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set
++# CONFIG_USB_SERIAL_ZIO is not set
++# CONFIG_USB_SERIAL_SSU100 is not set
++# CONFIG_USB_SERIAL_DEBUG is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_SEVSEG is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++# CONFIG_USB_ISIGHTFW is not set
++CONFIG_USB_GADGET=m
++# CONFIG_USB_GADGET_DEBUG_FILES is not set
++CONFIG_USB_GADGET_VBUS_DRAW=2
++CONFIG_USB_GADGET_SELECTED=y
++CONFIG_USB_GADGET_R8A66597=y
++CONFIG_USB_R8A66597=m
++# CONFIG_USB_GADGET_M66592 is not set
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_CI13XXX is not set
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LANGWELL is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++CONFIG_USB_GADGET_DUALSPEED=y
++# CONFIG_USB_ZERO is not set
++# CONFIG_USB_ETH is not set
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FUNCTIONFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_MASS_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_G_PRINTER is not set
++# CONFIG_USB_CDC_COMPOSITE is not set
++# CONFIG_USB_G_MULTI is not set
++# CONFIG_USB_G_HID is not set
++# CONFIG_USB_G_DBGP is not set
++
++#
++# OTG and related infrastructure
++#
++# CONFIG_USB_ULPI is not set
++# CONFIG_NOP_USB_XCEIV is not set
++# CONFIG_UWB is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_ACCESSIBILITY is not set
++# CONFIG_INFINIBAND is not set
++CONFIG_RTC_LIB=y
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++# CONFIG_AUXDISPLAY is not set
++# CONFIG_UIO is not set
++# CONFIG_STAGING is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++CONFIG_EXT2_FS_XIP=y
++CONFIG_EXT3_FS=y
++# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
++# CONFIG_EXT3_FS_XATTR is not set
++# CONFIG_EXT4_FS is not set
++CONFIG_FS_XIP=y
++CONFIG_JBD=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_BTRFS_FS is not set
++# CONFIG_NILFS2_FS is not set
++CONFIG_FILE_LOCKING=y
++# CONFIG_FSNOTIFY is not set
++# CONFIG_DNOTIFY is not set
++# CONFIG_INOTIFY_USER is not set
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++# CONFIG_FUSE_FS is not set
++
++#
++# Caches
++#
++# CONFIG_FSCACHE 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 is not set
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
++CONFIG_PROC_PAGE_MONITOR=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++# CONFIG_MISC_FILESYSTEMS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++# CONFIG_NFS_V3 is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_ROOT_NFS is not set
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CEPH_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++# CONFIG_SYSV68_PARTITION is not set
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 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 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++# CONFIG_ENABLE_WARN_DEPRECATED is not set
++# CONFIG_ENABLE_MUST_CHECK is not set
++CONFIG_FRAME_WARN=1024
++# CONFIG_MAGIC_SYSRQ is not set
++CONFIG_STRIP_ASM_SYMS=y
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_HARDLOCKUP_DETECTOR is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_MEMORY_INIT is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_SYSCTL_SYSCALL_CHECK is not set
++CONFIG_HAVE_FUNCTION_TRACER=y
++CONFIG_TRACING_SUPPORT=y
++# CONFIG_FTRACE is not set
++# CONFIG_ATOMIC64_SELFTEST is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_DEBUG_USER is not set
++# CONFIG_OC_ETM is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++CONFIG_DEFAULT_SECURITY_DAC=y
++CONFIG_DEFAULT_SECURITY=""
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++# CONFIG_CRYPTO_FIPS is not set
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++CONFIG_CRYPTO_AEAD2=y
++CONFIG_CRYPTO_BLKCIPHER=y
++CONFIG_CRYPTO_BLKCIPHER2=y
++CONFIG_CRYPTO_HASH=m
++CONFIG_CRYPTO_HASH2=y
++CONFIG_CRYPTO_RNG=m
++CONFIG_CRYPTO_RNG2=y
++CONFIG_CRYPTO_PCOMP2=y
++CONFIG_CRYPTO_MANAGER=y
++CONFIG_CRYPTO_MANAGER2=y
++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_NULL is not set
++CONFIG_CRYPTO_WORKQUEUE=y
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++CONFIG_CRYPTO_ECB=y
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_VMAC is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_GHASH is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++CONFIG_CRYPTO_MICHAEL_MIC=m
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++CONFIG_CRYPTO_SHA1=m
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
++CONFIG_CRYPTO_AES=m
++# CONFIG_CRYPTO_ANUBIS is not set
++CONFIG_CRYPTO_ARC4=y
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_ZLIB is not set
++# CONFIG_CRYPTO_LZO is not set
++
++#
++# Random Number Generation
++#
++CONFIG_CRYPTO_ANSI_CPRNG=m
++# CONFIG_CRYPTO_HW is not set
++# CONFIG_BINARY_PRINTF is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_GENERIC_FIND_LAST_BIT=y
++CONFIG_CRC_CCITT=m
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_T10DIF is not set
++CONFIG_CRC_ITU_T=m
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_DECOMPRESS_GZIP=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_NLATTR=y
++CONFIG_GENERIC_ATOMIC64=y
+diff -rupN linux-2.6.35.11/arch/arm/include/asm/page.h linux-2.6.35.11-ts7500/arch/arm/include/asm/page.h
+--- linux-2.6.35.11/arch/arm/include/asm/page.h 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/include/asm/page.h 2011-03-14 11:18:24.000000000 -0400
+@@ -84,6 +84,17 @@
+ # endif
+ #endif
+
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++#ifdef CONFIG_CPU_COPY_FA
++# ifdef _USER
++# define MULTI_USER 1
++# else
++# define _USER fa
++# endif
++#endif
++#endif
++
++
+ #ifdef CONFIG_CPU_SA1100
+ # ifdef _USER
+ # define MULTI_USER 1
+diff -rupN linux-2.6.35.11/arch/arm/include/asm/pci.h linux-2.6.35.11-ts7500/arch/arm/include/asm/pci.h
+--- linux-2.6.35.11/arch/arm/include/asm/pci.h 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/include/asm/pci.h 2011-03-14 11:18:24.000000000 -0400
+@@ -75,6 +75,16 @@ static inline int pci_get_legacy_ide_irq
+ return 0;
+ }
+
++
++#if defined(CONFIG_ARCH_STR9100) || defined(CONFIG_ARCH_STR8100)
++#define HAVE_ARCH_PCI_MWI
++static inline int pcibios_prep_mwi(struct pci_dev *dev)
++{
++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x08);
++ return 0;
++}
++#endif
++
+ #endif /* __KERNEL__ */
+
+ #endif
+diff -rupN linux-2.6.35.11/arch/arm/include/asm/tlbflush.h linux-2.6.35.11-ts7500/arch/arm/include/asm/tlbflush.h
+--- linux-2.6.35.11/arch/arm/include/asm/tlbflush.h 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/include/asm/tlbflush.h 2011-03-14 11:18:24.000000000 -0400
+@@ -39,7 +39,7 @@
+ #define TLB_V6_D_ASID (1 << 17)
+ #define TLB_V6_I_ASID (1 << 18)
+
+-#define TLB_BTB (1 << 28)
++//#define TLB_BTB (1 << 28)
+
+ /* Unified Inner Shareable TLB operations (ARMv7 MP extensions) */
+ #define TLB_V7_UIS_PAGE (1 << 19)
+@@ -53,6 +53,12 @@
+ #define TLB_DCLEAN (1 << 30)
+ #define TLB_WB (1 << 31)
+
++
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++#define TLB_DINVAL (1 << 28)
++#define TLB_BTB (1 << 29)
++#endif
++
+ /*
+ * MMU TLB Model
+ * =============
+@@ -100,6 +106,29 @@
+ # define v4_always_flags (-1UL)
+ #endif
+
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++#ifdef CONFIG_CPU_FA_BTB
++#define __TLB_BTB TLB_BTB
++#else
++#define __TLB_BTB 0
++#endif
++
++#ifdef CONFIG_CPU_FA_WB_DISABLE
++#define __TLB_WB 0
++#else
++#define __TLB_WB TLB_WB
++#endif
++
++/* Fix buggy CPU which doesn't invalidate Dcache properly */
++#ifdef CONFIG_CPU_FA520
++#define __TLB_DINVAL TLB_DINVAL
++#elif defined(CONFIG_CPU_FA526)
++//#define __TLB_DINVAL TLB_DINVAL
++#define __TLB_DINVAL 0
++#else
++#define __TLB_DINVAL 0
++#endif
++
+ #define fa_tlb_flags (TLB_WB | TLB_BTB | TLB_DCLEAN | \
+ TLB_V4_U_FULL | TLB_V4_U_PAGE)
+
+@@ -115,6 +144,7 @@
+ # define fa_possible_flags 0
+ # define fa_always_flags (-1UL)
+ #endif
++#endif
+
+ #define v4wbi_tlb_flags (TLB_WB | TLB_DCLEAN | \
+ TLB_V4_I_FULL | TLB_V4_D_FULL | \
+@@ -297,24 +327,36 @@ extern struct cpu_tlb_fns cpu_tlb;
+ * implemented the "%?" method, but this has been discontinued due to too
+ * many people getting it wrong.
+ */
+-#define possible_tlb_flags (v3_possible_flags | \
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++#define possible_tlb_flags (v3_possible_flags | \
+ v4_possible_flags | \
+ v4wbi_possible_flags | \
+- fr_possible_flags | \
+ v4wb_possible_flags | \
+ fa_possible_flags | \
+- v6wbi_possible_flags | \
+- v7wbi_possible_flags)
++ v6wbi_possible_flags)
++#else
++#define possible_tlb_flags (v3_possible_flags | \
++ v4_possible_flags | \
++ v4wbi_possible_flags | \
++ v4wb_possible_flags | \
++ v6wbi_possible_flags)
++#endif
+
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
+ #define always_tlb_flags (v3_always_flags & \
+ v4_always_flags & \
+ v4wbi_always_flags & \
+- fr_always_flags & \
+ v4wb_always_flags & \
+ fa_always_flags & \
+- v6wbi_always_flags & \
+- v7wbi_always_flags)
+-
++ v6wbi_always_flags)
++#else
++#define always_tlb_flags (v3_always_flags & \
++ v4_always_flags & \
++ v4wbi_always_flags & \
++ v4wb_always_flags & \
++ v6wbi_always_flags)
++#endif
++
+ #define tlb_flag(f) ((always_tlb_flags & (f)) || (__tlb_flag & possible_tlb_flags & (f)))
+
+ static inline void local_flush_tlb_all(void)
+@@ -322,6 +364,11 @@ static inline void local_flush_tlb_all(v
+ const int zero = 0;
+ const unsigned int __tlb_flag = __cpu_tlb_flags;
+
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++ if (tlb_flag(TLB_DINVAL))
++ asm("mcr%? p15, 0, %0, c7, c14, 0" : : "r" (zero) : "cc");
++#endif
++
+ if (tlb_flag(TLB_WB))
+ dsb();
+
+@@ -333,9 +380,28 @@ static inline void local_flush_tlb_all(v
+ asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
+ if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL))
+ asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
+- if (tlb_flag(TLB_V7_UIS_FULL))
+- asm("mcr p15, 0, %0, c8, c3, 0" : : "r" (zero) : "cc");
+
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++ if (tlb_flag(TLB_BTB)) {
++ asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
++ asm("mov r0, r0" : : );
++ asm("mov r0, r0" : : );
++ }
++#endif
++
++// if (tlb_flag(TLB_V7_UIS_FULL))
++ // asm("mcr p15, 0, %0, c8, c3, 0" : : "r" (zero) : "cc");
++
++ if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
++ TLB_V6_I_PAGE | TLB_V6_D_PAGE |
++ TLB_V6_I_ASID | TLB_V6_D_ASID)) {
++ /* flush the branch target cache */
++ asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
++ dsb();
++ isb();
++ }
++
++#if (0)
+ if (tlb_flag(TLB_BTB)) {
+ /* flush the branch target cache */
+ asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
+@@ -348,6 +414,7 @@ static inline void local_flush_tlb_all(v
+ dsb();
+ isb();
+ }
++#endif
+ }
+
+ static inline void local_flush_tlb_mm(struct mm_struct *mm)
+@@ -356,6 +423,11 @@ static inline void local_flush_tlb_mm(st
+ const int asid = ASID(mm);
+ const unsigned int __tlb_flag = __cpu_tlb_flags;
+
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++ if (tlb_flag(TLB_DINVAL))
++ asm("mcr%? p15, 0, %0, c7, c14, 0" : : "r" (zero) : "cc");
++#endif
++
+ if (tlb_flag(TLB_WB))
+ dsb();
+
+@@ -395,6 +467,7 @@ static inline void local_flush_tlb_mm(st
+ dsb();
+ isb();
+ }
++
+ }
+
+ static inline void
+@@ -404,7 +477,12 @@ local_flush_tlb_page(struct vm_area_stru
+ const unsigned int __tlb_flag = __cpu_tlb_flags;
+
+ uaddr = (uaddr & PAGE_MASK) | ASID(vma->vm_mm);
+-
++
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++ if (tlb_flag(TLB_DINVAL))
++ asm("mcr%? p15, 0, %0, c7, c14, 0" : : "r" (zero) : "cc"); // clean & invalidate data cache all
++#endif
++
+ if (tlb_flag(TLB_WB))
+ dsb();
+
+@@ -445,6 +523,7 @@ local_flush_tlb_page(struct vm_area_stru
+ dsb();
+ isb();
+ }
++
+ }
+
+ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
+@@ -454,6 +533,11 @@ static inline void local_flush_tlb_kerne
+
+ kaddr &= PAGE_MASK;
+
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++ if (tlb_flag(TLB_DINVAL))
++ asm("mcr%? p15, 0, %0, c7, c14, 0" : : "r" (zero) : "cc");
++#endif
++
+ if (tlb_flag(TLB_WB))
+ dsb();
+
+@@ -474,9 +558,28 @@ static inline void local_flush_tlb_kerne
+ asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc");
+ if (tlb_flag(TLB_V6_I_PAGE))
+ asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
+- if (tlb_flag(TLB_V7_UIS_PAGE))
+- asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (kaddr) : "cc");
++
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++ if (tlb_flag(TLB_BTB)) {
++ asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
++ asm("mov r0, r0" : : );
++ asm("mov r0, r0" : : );
++ }
++#endif
+
++ //if (tlb_flag(TLB_V7_UIS_PAGE))
++ //asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (kaddr) : "cc");
++
++ if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
++ TLB_V6_I_PAGE | TLB_V6_D_PAGE |
++ TLB_V6_I_ASID | TLB_V6_D_ASID)) {
++ /* flush the branch target cache */
++ asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
++ dsb();
++ isb();
++ }
++
++#if (0)
+ if (tlb_flag(TLB_BTB)) {
+ /* flush the branch target cache */
+ asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
+@@ -489,6 +592,7 @@ static inline void local_flush_tlb_kerne
+ dsb();
+ isb();
+ }
++#endif
+ }
+
+ /*
+@@ -507,30 +611,53 @@ static inline void local_flush_tlb_kerne
+ static inline void flush_pmd_entry(pmd_t *pmd)
+ {
+ const unsigned int __tlb_flag = __cpu_tlb_flags;
++ const int zero = 0;
+
+ if (tlb_flag(TLB_DCLEAN))
+ asm("mcr p15, 0, %0, c7, c10, 1 @ flush_pmd"
+ : : "r" (pmd) : "cc");
+
++/*
+ if (tlb_flag(TLB_L2CLEAN_FR))
+ asm("mcr p15, 1, %0, c15, c9, 1 @ L2 flush_pmd"
+ : : "r" (pmd) : "cc");
+-
++*/
+ if (tlb_flag(TLB_WB))
+ dsb();
++
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++ if (tlb_flag(TLB_BTB)) {
++ asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
++ asm("mov r0, r0" : : );
++ asm("mov r0, r0" : : );
++ }
++#endif
++
+ }
+
+ static inline void clean_pmd_entry(pmd_t *pmd)
+ {
+ const unsigned int __tlb_flag = __cpu_tlb_flags;
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++ const unsigned int zero = 0;
++#endif
+
+ if (tlb_flag(TLB_DCLEAN))
+ asm("mcr p15, 0, %0, c7, c10, 1 @ flush_pmd"
+ : : "r" (pmd) : "cc");
+-
++/*
+ if (tlb_flag(TLB_L2CLEAN_FR))
+ asm("mcr p15, 1, %0, c15, c9, 1 @ L2 flush_pmd"
+ : : "r" (pmd) : "cc");
++*/
++
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++ if (tlb_flag(TLB_BTB)) {
++ asm("mcr%? p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
++ asm("mov r0, r0" : : );
++ asm("mov r0, r0" : : );
++ }
++#endif
+ }
+
+ #undef tlb_flag
+@@ -571,4 +698,5 @@ extern void update_mmu_cache(struct vm_a
+
+ #endif /* CONFIG_MMU */
+
+-#endif
++#endif /* _ASMARM_TLBFLUSH_H */
++
+diff -rupN linux-2.6.35.11/arch/arm/Kconfig linux-2.6.35.11-ts7500/arch/arm/Kconfig
+--- linux-2.6.35.11/arch/arm/Kconfig 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/Kconfig 2011-03-14 11:18:24.000000000 -0400
+@@ -160,7 +160,8 @@ config ARCH_MAY_HAVE_PC_FDC
+
+ config ZONE_DMA
+ bool
+-
++ default y if !ARCH_STR8100
++
+ config NEED_DMA_MAP_STATE
+ def_bool y
+
+@@ -210,6 +211,20 @@ choice
+ prompt "ARM system type"
+ default ARCH_VERSATILE
+
++config ARCH_STR9100
++ bool "Star-STR9100"
++ select PCI
++ help
++ Star STR9100 is a platform based on Faraday's ARM9 compatible processor
++ architecture.
++
++config ARCH_STR8100
++ bool "Star-STR8100"
++ select PCI
++ help
++ Star STR8100 is a platform based on Faraday's ARM9 compatible processor
++ architecture.
++
+ config ARCH_AAEC2000
+ bool "Agilent AAEC-2000 based"
+ select CPU_ARM920T
+@@ -901,6 +916,14 @@ source "arch/arm/mach-s5p6442/Kconfig"
+
+ source "arch/arm/mach-s5pc100/Kconfig"
+
++if ARCH_STR9100
++source "arch/arm/mach-str9100/Kconfig"
++endif
++
++if ARCH_STR8100
++source "arch/arm/mach-str8100/Kconfig"
++endif
++
+ source "arch/arm/mach-s5pv210/Kconfig"
+
+ source "arch/arm/mach-shmobile/Kconfig"
+diff -rupN linux-2.6.35.11/arch/arm/Kconfig.orig linux-2.6.35.11-ts7500/arch/arm/Kconfig.orig
+--- linux-2.6.35.11/arch/arm/Kconfig.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/Kconfig.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,1691 @@
++#
++# For a description of the syntax of this configuration file,
++# see Documentation/kbuild/kconfig-language.txt.
++#
++
++mainmenu "Linux Kernel Configuration"
++
++config ARM
++ bool
++ default y
++ select HAVE_AOUT
++ select HAVE_IDE
++ select RTC_LIB
++ select SYS_SUPPORTS_APM_EMULATION
++ select GENERIC_ATOMIC64 if (!CPU_32v6K)
++ select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
++ select HAVE_ARCH_KGDB
++ select HAVE_KPROBES if (!XIP_KERNEL)
++ select HAVE_KRETPROBES if (HAVE_KPROBES)
++ select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
++ select HAVE_GENERIC_DMA_COHERENT
++ select HAVE_KERNEL_GZIP
++ select HAVE_KERNEL_LZO
++ select HAVE_KERNEL_LZMA
++ select HAVE_PERF_EVENTS
++ select PERF_USE_VMALLOC
++ help
++ The ARM series is a line of low-power-consumption RISC chip designs
++ licensed by ARM Ltd and targeted at embedded applications and
++ handhelds such as the Compaq IPAQ. ARM-based PCs are no longer
++ manufactured, but legacy ARM-based PC hardware remains popular in
++ Europe. There is an ARM Linux project with a web page at
++ <http://www.arm.linux.org.uk/>.
++
++config HAVE_PWM
++ bool
++
++config SYS_SUPPORTS_APM_EMULATION
++ bool
++
++config GENERIC_GPIO
++ bool
++
++config GENERIC_TIME
++ bool
++ default y
++
++config ARCH_USES_GETTIMEOFFSET
++ bool
++ default n
++
++config GENERIC_CLOCKEVENTS
++ bool
++
++config GENERIC_CLOCKEVENTS_BROADCAST
++ bool
++ depends on GENERIC_CLOCKEVENTS
++ default y if SMP && !LOCAL_TIMERS
++
++config HAVE_TCM
++ bool
++ select GENERIC_ALLOCATOR
++
++config HAVE_PROC_CPU
++ bool
++
++config NO_IOPORT
++ bool
++
++config EISA
++ bool
++ ---help---
++ The Extended Industry Standard Architecture (EISA) bus was
++ developed as an open alternative to the IBM MicroChannel bus.
++
++ The EISA bus provided some of the features of the IBM MicroChannel
++ bus while maintaining backward compatibility with cards made for
++ the older ISA bus. The EISA bus saw limited use between 1988 and
++ 1995 when it was made obsolete by the PCI bus.
++
++ Say Y here if you are building a kernel for an EISA-based machine.
++
++ Otherwise, say N.
++
++config SBUS
++ bool
++
++config MCA
++ bool
++ help
++ MicroChannel Architecture is found in some IBM PS/2 machines and
++ laptops. It is a bus system similar to PCI or ISA. See
++ <file:Documentation/mca.txt> (and especially the web page given
++ there) before attempting to build an MCA bus kernel.
++
++config GENERIC_HARDIRQS
++ bool
++ default y
++
++config STACKTRACE_SUPPORT
++ bool
++ default y
++
++config HAVE_LATENCYTOP_SUPPORT
++ bool
++ depends on !SMP
++ default y
++
++config LOCKDEP_SUPPORT
++ bool
++ default y
++
++config TRACE_IRQFLAGS_SUPPORT
++ bool
++ default y
++
++config HARDIRQS_SW_RESEND
++ bool
++ default y
++
++config GENERIC_IRQ_PROBE
++ bool
++ default y
++
++config GENERIC_LOCKBREAK
++ bool
++ default y
++ depends on SMP && PREEMPT
++
++config RWSEM_GENERIC_SPINLOCK
++ bool
++ default y
++
++config RWSEM_XCHGADD_ALGORITHM
++ bool
++
++config ARCH_HAS_ILOG2_U32
++ bool
++
++config ARCH_HAS_ILOG2_U64
++ bool
++
++config ARCH_HAS_CPUFREQ
++ bool
++ help
++ Internal node to signify that the ARCH has CPUFREQ support
++ and that the relevant menu configurations are displayed for
++ it.
++
++config GENERIC_HWEIGHT
++ bool
++ default y
++
++config GENERIC_CALIBRATE_DELAY
++ bool
++ default y
++
++config ARCH_MAY_HAVE_PC_FDC
++ bool
++
++config ZONE_DMA
++ bool
++
++config NEED_DMA_MAP_STATE
++ def_bool y
++
++config GENERIC_ISA_DMA
++ bool
++
++config FIQ
++ bool
++
++config ARCH_MTD_XIP
++ bool
++
++config GENERIC_HARDIRQS_NO__DO_IRQ
++ def_bool y
++
++config ARM_L1_CACHE_SHIFT_6
++ bool
++ help
++ Setting ARM L1 cache line size to 64 Bytes.
++
++config VECTORS_BASE
++ hex
++ default 0xffff0000 if MMU || CPU_HIGH_VECTOR
++ default DRAM_BASE if REMAP_VECTORS_TO_RAM
++ default 0x00000000
++ help
++ The base address of exception vectors.
++
++source "init/Kconfig"
++
++source "kernel/Kconfig.freezer"
++
++menu "System Type"
++
++config MMU
++ bool "MMU-based Paged Memory Management Support"
++ default y
++ help
++ Select if you want MMU-based virtualised addressing space
++ support by paged memory management. If unsure, say 'Y'.
++
++#
++# The "ARM system type" choice list is ordered alphabetically by option
++# text. Please add new entries in the option alphabetic order.
++#
++choice
++ prompt "ARM system type"
++ default ARCH_VERSATILE
++
++config ARCH_AAEC2000
++ bool "Agilent AAEC-2000 based"
++ select CPU_ARM920T
++ select ARM_AMBA
++ select HAVE_CLK
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ This enables support for systems based on the Agilent AAEC-2000
++
++config ARCH_INTEGRATOR
++ bool "ARM Ltd. Integrator family"
++ select ARM_AMBA
++ select ARCH_HAS_CPUFREQ
++ select COMMON_CLKDEV
++ select ICST
++ select GENERIC_CLOCKEVENTS
++ select PLAT_VERSATILE
++ help
++ Support for ARM's Integrator platform.
++
++config ARCH_REALVIEW
++ bool "ARM Ltd. RealView family"
++ select ARM_AMBA
++ select COMMON_CLKDEV
++ select ICST
++ select GENERIC_CLOCKEVENTS
++ select ARCH_WANT_OPTIONAL_GPIOLIB
++ select PLAT_VERSATILE
++ select ARM_TIMER_SP804
++ select GPIO_PL061 if GPIOLIB
++ help
++ This enables support for ARM Ltd RealView boards.
++
++config ARCH_VERSATILE
++ bool "ARM Ltd. Versatile family"
++ select ARM_AMBA
++ select ARM_VIC
++ select COMMON_CLKDEV
++ select ICST
++ select GENERIC_CLOCKEVENTS
++ select ARCH_WANT_OPTIONAL_GPIOLIB
++ select PLAT_VERSATILE
++ select ARM_TIMER_SP804
++ help
++ This enables support for ARM Ltd Versatile board.
++
++config ARCH_VEXPRESS
++ bool "ARM Ltd. Versatile Express family"
++ select ARCH_WANT_OPTIONAL_GPIOLIB
++ select ARM_AMBA
++ select ARM_TIMER_SP804
++ select COMMON_CLKDEV
++ select GENERIC_CLOCKEVENTS
++ select HAVE_CLK
++ select ICST
++ select PLAT_VERSATILE
++ help
++ This enables support for the ARM Ltd Versatile Express boards.
++
++config ARCH_AT91
++ bool "Atmel AT91"
++ select ARCH_REQUIRE_GPIOLIB
++ select HAVE_CLK
++ help
++ This enables support for systems based on the Atmel AT91RM9200,
++ AT91SAM9 and AT91CAP9 processors.
++
++config ARCH_BCMRING
++ bool "Broadcom BCMRING"
++ depends on MMU
++ select CPU_V6
++ select ARM_AMBA
++ select COMMON_CLKDEV
++ select GENERIC_CLOCKEVENTS
++ select ARCH_WANT_OPTIONAL_GPIOLIB
++ help
++ Support for Broadcom's BCMRing platform.
++
++config ARCH_CLPS711X
++ bool "Cirrus Logic CLPS711x/EP721x-based"
++ select CPU_ARM720T
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ Support for Cirrus Logic 711x/721x based boards.
++
++config ARCH_CNS3XXX
++ bool "Cavium Networks CNS3XXX family"
++ select CPU_V6
++ select GENERIC_CLOCKEVENTS
++ select ARM_GIC
++ help
++ Support for Cavium Networks CNS3XXX platform.
++
++config ARCH_GEMINI
++ bool "Cortina Systems Gemini"
++ select CPU_FA526
++ select ARCH_REQUIRE_GPIOLIB
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ Support for the Cortina Systems Gemini family SoCs
++
++config ARCH_EBSA110
++ bool "EBSA-110"
++ select CPU_SA110
++ select ISA
++ select NO_IOPORT
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ This is an evaluation board for the StrongARM processor available
++ from Digital. It has limited hardware on-board, including an
++ Ethernet interface, two PCMCIA sockets, two serial ports and a
++ parallel port.
++
++config ARCH_EP93XX
++ bool "EP93xx-based"
++ select CPU_ARM920T
++ select ARM_AMBA
++ select ARM_VIC
++ select COMMON_CLKDEV
++ select ARCH_REQUIRE_GPIOLIB
++ select ARCH_HAS_HOLES_MEMORYMODEL
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ This enables support for the Cirrus EP93xx series of CPUs.
++
++config ARCH_FOOTBRIDGE
++ bool "FootBridge"
++ select CPU_SA110
++ select FOOTBRIDGE
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ Support for systems based on the DC21285 companion chip
++ ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
++
++config ARCH_MXC
++ bool "Freescale MXC/iMX-based"
++ select GENERIC_CLOCKEVENTS
++ select ARCH_REQUIRE_GPIOLIB
++ select COMMON_CLKDEV
++ help
++ Support for Freescale MXC/iMX-based family of processors
++
++config ARCH_STMP3XXX
++ bool "Freescale STMP3xxx"
++ select CPU_ARM926T
++ select COMMON_CLKDEV
++ select ARCH_REQUIRE_GPIOLIB
++ select GENERIC_CLOCKEVENTS
++ select USB_ARCH_HAS_EHCI
++ help
++ Support for systems based on the Freescale 3xxx CPUs.
++
++config ARCH_NETX
++ bool "Hilscher NetX based"
++ select CPU_ARM926T
++ select ARM_VIC
++ select GENERIC_CLOCKEVENTS
++ help
++ This enables support for systems based on the Hilscher NetX Soc
++
++config ARCH_H720X
++ bool "Hynix HMS720x-based"
++ select CPU_ARM720T
++ select ISA_DMA_API
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ This enables support for systems based on the Hynix HMS720x
++
++config ARCH_IOP13XX
++ bool "IOP13xx-based"
++ depends on MMU
++ select CPU_XSC3
++ select PLAT_IOP
++ select PCI
++ select ARCH_SUPPORTS_MSI
++ select VMSPLIT_1G
++ help
++ Support for Intel's IOP13XX (XScale) family of processors.
++
++config ARCH_IOP32X
++ bool "IOP32x-based"
++ depends on MMU
++ select CPU_XSCALE
++ select PLAT_IOP
++ select PCI
++ select ARCH_REQUIRE_GPIOLIB
++ help
++ Support for Intel's 80219 and IOP32X (XScale) family of
++ processors.
++
++config ARCH_IOP33X
++ bool "IOP33x-based"
++ depends on MMU
++ select CPU_XSCALE
++ select PLAT_IOP
++ select PCI
++ select ARCH_REQUIRE_GPIOLIB
++ help
++ Support for Intel's IOP33X (XScale) family of processors.
++
++config ARCH_IXP23XX
++ bool "IXP23XX-based"
++ depends on MMU
++ select CPU_XSC3
++ select PCI
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ Support for Intel's IXP23xx (XScale) family of processors.
++
++config ARCH_IXP2000
++ bool "IXP2400/2800-based"
++ depends on MMU
++ select CPU_XSCALE
++ select PCI
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ Support for Intel's IXP2400/2800 (XScale) family of processors.
++
++config ARCH_IXP4XX
++ bool "IXP4xx-based"
++ depends on MMU
++ select CPU_XSCALE
++ select GENERIC_GPIO
++ select GENERIC_CLOCKEVENTS
++ select DMABOUNCE if PCI
++ help
++ Support for Intel's IXP4XX (XScale) family of processors.
++
++config ARCH_L7200
++ bool "LinkUp-L7200"
++ select CPU_ARM720T
++ select FIQ
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ Say Y here if you intend to run this kernel on a LinkUp Systems
++ L7200 Software Development Board which uses an ARM720T processor.
++ Information on this board can be obtained at:
++
++ <http://www.linkupsys.com/>
++
++ If you have any questions or comments about the Linux kernel port
++ to this board, send e-mail to <sjhill at cotw.com>.
++
++config ARCH_DOVE
++ bool "Marvell Dove"
++ select PCI
++ select ARCH_REQUIRE_GPIOLIB
++ select GENERIC_CLOCKEVENTS
++ select PLAT_ORION
++ help
++ Support for the Marvell Dove SoC 88AP510
++
++config ARCH_KIRKWOOD
++ bool "Marvell Kirkwood"
++ select CPU_FEROCEON
++ select PCI
++ select ARCH_REQUIRE_GPIOLIB
++ select GENERIC_CLOCKEVENTS
++ select PLAT_ORION
++ help
++ Support for the following Marvell Kirkwood series SoCs:
++ 88F6180, 88F6192 and 88F6281.
++
++config ARCH_LOKI
++ bool "Marvell Loki (88RC8480)"
++ select CPU_FEROCEON
++ select GENERIC_CLOCKEVENTS
++ select PLAT_ORION
++ help
++ Support for the Marvell Loki (88RC8480) SoC.
++
++config ARCH_MV78XX0
++ bool "Marvell MV78xx0"
++ select CPU_FEROCEON
++ select PCI
++ select ARCH_REQUIRE_GPIOLIB
++ select GENERIC_CLOCKEVENTS
++ select PLAT_ORION
++ help
++ Support for the following Marvell MV78xx0 series SoCs:
++ MV781x0, MV782x0.
++
++config ARCH_ORION5X
++ bool "Marvell Orion"
++ depends on MMU
++ select CPU_FEROCEON
++ select PCI
++ select ARCH_REQUIRE_GPIOLIB
++ select GENERIC_CLOCKEVENTS
++ select PLAT_ORION
++ help
++ Support for the following Marvell Orion 5x series SoCs:
++ Orion-1 (5181), Orion-VoIP (5181L), Orion-NAS (5182),
++ Orion-2 (5281), Orion-1-90 (6183).
++
++config ARCH_MMP
++ bool "Marvell PXA168/910/MMP2"
++ depends on MMU
++ select ARCH_REQUIRE_GPIOLIB
++ select COMMON_CLKDEV
++ select GENERIC_CLOCKEVENTS
++ select TICK_ONESHOT
++ select PLAT_PXA
++ help
++ Support for Marvell's PXA168/PXA910(MMP) and MMP2 processor line.
++
++config ARCH_KS8695
++ bool "Micrel/Kendin KS8695"
++ select CPU_ARM922T
++ select ARCH_REQUIRE_GPIOLIB
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based
++ System-on-Chip devices.
++
++config ARCH_NS9XXX
++ bool "NetSilicon NS9xxx"
++ select CPU_ARM926T
++ select GENERIC_GPIO
++ select GENERIC_CLOCKEVENTS
++ select HAVE_CLK
++ help
++ Say Y here if you intend to run this kernel on a NetSilicon NS9xxx
++ System.
++
++ <http://www.digi.com/products/microprocessors/index.jsp>
++
++config ARCH_W90X900
++ bool "Nuvoton W90X900 CPU"
++ select CPU_ARM926T
++ select ARCH_REQUIRE_GPIOLIB
++ select COMMON_CLKDEV
++ select GENERIC_CLOCKEVENTS
++ help
++ Support for Nuvoton (Winbond logic dept.) ARM9 processor,
++ At present, the w90x900 has been renamed nuc900, regarding
++ the ARM series product line, you can login the following
++ link address to know more.
++
++ <http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/
++ ConsumerElectronicsIC/ARMMicrocontroller/ARMMicrocontroller>
++
++config ARCH_NUC93X
++ bool "Nuvoton NUC93X CPU"
++ select CPU_ARM926T
++ select COMMON_CLKDEV
++ help
++ Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a
++ low-power and high performance MPEG-4/JPEG multimedia controller chip.
++
++config ARCH_PNX4008
++ bool "Philips Nexperia PNX4008 Mobile"
++ select CPU_ARM926T
++ select COMMON_CLKDEV
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ This enables support for Philips PNX4008 mobile platform.
++
++config ARCH_PXA
++ bool "PXA2xx/PXA3xx-based"
++ depends on MMU
++ select ARCH_MTD_XIP
++ select ARCH_HAS_CPUFREQ
++ select COMMON_CLKDEV
++ select ARCH_REQUIRE_GPIOLIB
++ select GENERIC_CLOCKEVENTS
++ select TICK_ONESHOT
++ select PLAT_PXA
++ help
++ Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
++
++config ARCH_MSM
++ bool "Qualcomm MSM"
++ select HAVE_CLK
++ select GENERIC_CLOCKEVENTS
++ help
++ Support for Qualcomm MSM/QSD based systems. This runs on the
++ apps processor of the MSM/QSD and depends on a shared memory
++ interface to the modem processor which runs the baseband
++ stack and controls some vital subsystems
++ (clock and power control, etc).
++
++config ARCH_SHMOBILE
++ bool "Renesas SH-Mobile"
++ help
++ Support for Renesas's SH-Mobile ARM platforms
++
++config ARCH_RPC
++ bool "RiscPC"
++ select ARCH_ACORN
++ select FIQ
++ select TIMER_ACORN
++ select ARCH_MAY_HAVE_PC_FDC
++ select HAVE_PATA_PLATFORM
++ select ISA_DMA_API
++ select NO_IOPORT
++ select ARCH_SPARSEMEM_ENABLE
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ On the Acorn Risc-PC, Linux can support the internal IDE disk and
++ CD-ROM interface, serial and parallel port, and the floppy drive.
++
++config ARCH_SA1100
++ bool "SA1100-based"
++ select CPU_SA1100
++ select ISA
++ select ARCH_SPARSEMEM_ENABLE
++ select ARCH_MTD_XIP
++ select ARCH_HAS_CPUFREQ
++ select CPU_FREQ
++ select GENERIC_CLOCKEVENTS
++ select HAVE_CLK
++ select TICK_ONESHOT
++ select ARCH_REQUIRE_GPIOLIB
++ help
++ Support for StrongARM 11x0 based boards.
++
++config ARCH_S3C2410
++ bool "Samsung S3C2410, S3C2412, S3C2413, S3C2416, S3C2440, S3C2442, S3C2443, S3C2450"
++ select GENERIC_GPIO
++ select ARCH_HAS_CPUFREQ
++ select HAVE_CLK
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ Samsung S3C2410X CPU based systems, such as the Simtec Electronics
++ BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
++ the Samsung SMDK2410 development board (and derivatives).
++
++ Note, the S3C2416 and the S3C2450 are so close that they even share
++ the same SoC ID code. This means that there is no seperate machine
++ directory (no arch/arm/mach-s3c2450) as the S3C2416 was first.
++
++config ARCH_S3C64XX
++ bool "Samsung S3C64XX"
++ select PLAT_SAMSUNG
++ select CPU_V6
++ select ARM_VIC
++ select HAVE_CLK
++ select NO_IOPORT
++ select ARCH_USES_GETTIMEOFFSET
++ select ARCH_HAS_CPUFREQ
++ select ARCH_REQUIRE_GPIOLIB
++ select SAMSUNG_CLKSRC
++ select SAMSUNG_IRQ_VIC_TIMER
++ select SAMSUNG_IRQ_UART
++ select S3C_GPIO_TRACK
++ select S3C_GPIO_PULL_UPDOWN
++ select S3C_GPIO_CFG_S3C24XX
++ select S3C_GPIO_CFG_S3C64XX
++ select S3C_DEV_NAND
++ select USB_ARCH_HAS_OHCI
++ select SAMSUNG_GPIOLIB_4BIT
++ help
++ Samsung S3C64XX series based systems
++
++config ARCH_S5P6440
++ bool "Samsung S5P6440"
++ select CPU_V6
++ select GENERIC_GPIO
++ select HAVE_CLK
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ Samsung S5P6440 CPU based systems
++
++config ARCH_S5P6442
++ bool "Samsung S5P6442"
++ select CPU_V6
++ select GENERIC_GPIO
++ select HAVE_CLK
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ Samsung S5P6442 CPU based systems
++
++config ARCH_S5PC100
++ bool "Samsung S5PC100"
++ select GENERIC_GPIO
++ select HAVE_CLK
++ select CPU_V7
++ select ARM_L1_CACHE_SHIFT_6
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ Samsung S5PC100 series based systems
++
++config ARCH_S5PV210
++ bool "Samsung S5PV210/S5PC110"
++ select CPU_V7
++ select GENERIC_GPIO
++ select HAVE_CLK
++ select ARM_L1_CACHE_SHIFT_6
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ Samsung S5PV210/S5PC110 series based systems
++
++config ARCH_SHARK
++ bool "Shark"
++ select CPU_SA110
++ select ISA
++ select ISA_DMA
++ select ZONE_DMA
++ select PCI
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ Support for the StrongARM based Digital DNARD machine, also known
++ as "Shark" (<http://www.shark-linux.de/shark.html>).
++
++config ARCH_LH7A40X
++ bool "Sharp LH7A40X"
++ select CPU_ARM922T
++ select ARCH_DISCONTIGMEM_ENABLE if !LH7A40X_CONTIGMEM
++ select ARCH_SPARSEMEM_ENABLE if !LH7A40X_CONTIGMEM
++ select ARCH_USES_GETTIMEOFFSET
++ help
++ Say Y here for systems based on one of the Sharp LH7A40X
++ System on a Chip processors. These CPUs include an ARM922T
++ core with a wide array of integrated devices for
++ hand-held and low-power applications.
++
++config ARCH_U300
++ bool "ST-Ericsson U300 Series"
++ depends on MMU
++ select CPU_ARM926T
++ select HAVE_TCM
++ select ARM_AMBA
++ select ARM_VIC
++ select GENERIC_CLOCKEVENTS
++ select COMMON_CLKDEV
++ select GENERIC_GPIO
++ help
++ Support for ST-Ericsson U300 series mobile platforms.
++
++config ARCH_U8500
++ bool "ST-Ericsson U8500 Series"
++ select CPU_V7
++ select ARM_AMBA
++ select GENERIC_CLOCKEVENTS
++ select COMMON_CLKDEV
++ select ARCH_REQUIRE_GPIOLIB
++ help
++ Support for ST-Ericsson's Ux500 architecture
++
++config ARCH_NOMADIK
++ bool "STMicroelectronics Nomadik"
++ select ARM_AMBA
++ select ARM_VIC
++ select CPU_ARM926T
++ select COMMON_CLKDEV
++ select GENERIC_CLOCKEVENTS
++ select ARCH_REQUIRE_GPIOLIB
++ help
++ Support for the Nomadik platform by ST-Ericsson
++
++config ARCH_DAVINCI
++ bool "TI DaVinci"
++ select GENERIC_CLOCKEVENTS
++ select ARCH_REQUIRE_GPIOLIB
++ select ZONE_DMA
++ select HAVE_IDE
++ select COMMON_CLKDEV
++ select GENERIC_ALLOCATOR
++ select ARCH_HAS_HOLES_MEMORYMODEL
++ help
++ Support for TI's DaVinci platform.
++
++config ARCH_OMAP
++ bool "TI OMAP"
++ select HAVE_CLK
++ select ARCH_REQUIRE_GPIOLIB
++ select ARCH_HAS_CPUFREQ
++ select GENERIC_CLOCKEVENTS
++ select ARCH_HAS_HOLES_MEMORYMODEL
++ help
++ Support for TI's OMAP platform (OMAP1 and OMAP2).
++
++config PLAT_SPEAR
++ bool "ST SPEAr"
++ select ARM_AMBA
++ select ARCH_REQUIRE_GPIOLIB
++ select COMMON_CLKDEV
++ select GENERIC_CLOCKEVENTS
++ select HAVE_CLK
++ help
++ Support for ST's SPEAr platform (SPEAr3xx, SPEAr6xx and SPEAr13xx).
++
++endchoice
++
++#
++# This is sorted alphabetically by mach-* pathname. However, plat-*
++# Kconfigs may be included either alphabetically (according to the
++# plat- suffix) or along side the corresponding mach-* source.
++#
++source "arch/arm/mach-aaec2000/Kconfig"
++
++source "arch/arm/mach-at91/Kconfig"
++
++source "arch/arm/mach-bcmring/Kconfig"
++
++source "arch/arm/mach-clps711x/Kconfig"
++
++source "arch/arm/mach-cns3xxx/Kconfig"
++
++source "arch/arm/mach-davinci/Kconfig"
++
++source "arch/arm/mach-dove/Kconfig"
++
++source "arch/arm/mach-ep93xx/Kconfig"
++
++source "arch/arm/mach-footbridge/Kconfig"
++
++source "arch/arm/mach-gemini/Kconfig"
++
++source "arch/arm/mach-h720x/Kconfig"
++
++source "arch/arm/mach-integrator/Kconfig"
++
++source "arch/arm/mach-iop32x/Kconfig"
++
++source "arch/arm/mach-iop33x/Kconfig"
++
++source "arch/arm/mach-iop13xx/Kconfig"
++
++source "arch/arm/mach-ixp4xx/Kconfig"
++
++source "arch/arm/mach-ixp2000/Kconfig"
++
++source "arch/arm/mach-ixp23xx/Kconfig"
++
++source "arch/arm/mach-kirkwood/Kconfig"
++
++source "arch/arm/mach-ks8695/Kconfig"
++
++source "arch/arm/mach-lh7a40x/Kconfig"
++
++source "arch/arm/mach-loki/Kconfig"
++
++source "arch/arm/mach-msm/Kconfig"
++
++source "arch/arm/mach-mv78xx0/Kconfig"
++
++source "arch/arm/plat-mxc/Kconfig"
++
++source "arch/arm/mach-netx/Kconfig"
++
++source "arch/arm/mach-nomadik/Kconfig"
++source "arch/arm/plat-nomadik/Kconfig"
++
++source "arch/arm/mach-ns9xxx/Kconfig"
++
++source "arch/arm/mach-nuc93x/Kconfig"
++
++source "arch/arm/plat-omap/Kconfig"
++
++source "arch/arm/mach-omap1/Kconfig"
++
++source "arch/arm/mach-omap2/Kconfig"
++
++source "arch/arm/mach-orion5x/Kconfig"
++
++source "arch/arm/mach-pxa/Kconfig"
++source "arch/arm/plat-pxa/Kconfig"
++
++source "arch/arm/mach-mmp/Kconfig"
++
++source "arch/arm/mach-realview/Kconfig"
++
++source "arch/arm/mach-sa1100/Kconfig"
++
++source "arch/arm/plat-samsung/Kconfig"
++source "arch/arm/plat-s3c24xx/Kconfig"
++source "arch/arm/plat-s5p/Kconfig"
++
++source "arch/arm/plat-spear/Kconfig"
++
++if ARCH_S3C2410
++source "arch/arm/mach-s3c2400/Kconfig"
++source "arch/arm/mach-s3c2410/Kconfig"
++source "arch/arm/mach-s3c2412/Kconfig"
++source "arch/arm/mach-s3c2416/Kconfig"
++source "arch/arm/mach-s3c2440/Kconfig"
++source "arch/arm/mach-s3c2443/Kconfig"
++endif
++
++if ARCH_S3C64XX
++source "arch/arm/mach-s3c64xx/Kconfig"
++endif
++
++source "arch/arm/mach-s5p6440/Kconfig"
++
++source "arch/arm/mach-s5p6442/Kconfig"
++
++source "arch/arm/mach-s5pc100/Kconfig"
++
++source "arch/arm/mach-s5pv210/Kconfig"
++
++source "arch/arm/mach-shmobile/Kconfig"
++
++source "arch/arm/plat-stmp3xxx/Kconfig"
++
++source "arch/arm/mach-u300/Kconfig"
++
++source "arch/arm/mach-ux500/Kconfig"
++
++source "arch/arm/mach-versatile/Kconfig"
++
++source "arch/arm/mach-vexpress/Kconfig"
++
++source "arch/arm/mach-w90x900/Kconfig"
++
++# Definitions to make life easier
++config ARCH_ACORN
++ bool
++
++config PLAT_IOP
++ bool
++ select GENERIC_CLOCKEVENTS
++
++config PLAT_ORION
++ bool
++
++config PLAT_PXA
++ bool
++
++config PLAT_VERSATILE
++ bool
++
++config ARM_TIMER_SP804
++ bool
++
++source arch/arm/mm/Kconfig
++
++config IWMMXT
++ bool "Enable iWMMXt support"
++ depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK
++ default y if PXA27x || PXA3xx || ARCH_MMP
++ help
++ Enable support for iWMMXt context switching at run time if
++ running on a CPU that supports it.
++
++# bool 'Use XScale PMU as timer source' CONFIG_XSCALE_PMU_TIMER
++config XSCALE_PMU
++ bool
++ depends on CPU_XSCALE && !XSCALE_PMU_TIMER
++ default y
++
++config CPU_HAS_PMU
++ depends on (CPU_V6 || CPU_V7 || XSCALE_PMU) && \
++ (!ARCH_OMAP3 || OMAP3_EMU)
++ default y
++ bool
++
++if !MMU
++source "arch/arm/Kconfig-nommu"
++endif
++
++config ARM_ERRATA_411920
++ bool "ARM errata: Invalidation of the Instruction Cache operation can fail"
++ depends on CPU_V6 && !SMP
++ help
++ Invalidation of the Instruction Cache operation can
++ fail. This erratum is present in 1136 (before r1p4), 1156 and 1176.
++ It does not affect the MPCore. This option enables the ARM Ltd.
++ recommended workaround.
++
++config ARM_ERRATA_430973
++ bool "ARM errata: Stale prediction on replaced interworking branch"
++ depends on CPU_V7
++ help
++ This option enables the workaround for the 430973 Cortex-A8
++ (r1p0..r1p2) erratum. If a code sequence containing an ARM/Thumb
++ interworking branch is replaced with another code sequence at the
++ same virtual address, whether due to self-modifying code or virtual
++ to physical address re-mapping, Cortex-A8 does not recover from the
++ stale interworking branch prediction. This results in Cortex-A8
++ executing the new code sequence in the incorrect ARM or Thumb state.
++ The workaround enables the BTB/BTAC operations by setting ACTLR.IBE
++ and also flushes the branch target cache at every context switch.
++ Note that setting specific bits in the ACTLR register may not be
++ available in non-secure mode.
++
++config ARM_ERRATA_458693
++ bool "ARM errata: Processor deadlock when a false hazard is created"
++ depends on CPU_V7
++ help
++ This option enables the workaround for the 458693 Cortex-A8 (r2p0)
++ erratum. For very specific sequences of memory operations, it is
++ possible for a hazard condition intended for a cache line to instead
++ be incorrectly associated with a different cache line. This false
++ hazard might then cause a processor deadlock. The workaround enables
++ the L1 caching of the NEON accesses and disables the PLD instruction
++ in the ACTLR register. Note that setting specific bits in the ACTLR
++ register may not be available in non-secure mode.
++
++config ARM_ERRATA_460075
++ bool "ARM errata: Data written to the L2 cache can be overwritten with stale data"
++ depends on CPU_V7
++ help
++ This option enables the workaround for the 460075 Cortex-A8 (r2p0)
++ erratum. Any asynchronous access to the L2 cache may encounter a
++ situation in which recent store transactions to the L2 cache are lost
++ and overwritten with stale memory contents from external memory. The
++ workaround disables the write-allocate mode for the L2 cache via the
++ ACTLR register. Note that setting specific bits in the ACTLR register
++ may not be available in non-secure mode.
++
++config PL310_ERRATA_588369
++ bool "Clean & Invalidate maintenance operations do not invalidate clean lines"
++ depends on CACHE_L2X0 && ARCH_OMAP4
++ help
++ The PL310 L2 cache controller implements three types of Clean &
++ Invalidate maintenance operations: by Physical Address
++ (offset 0x7F0), by Index/Way (0x7F8) and by Way (0x7FC).
++ They are architecturally defined to behave as the execution of a
++ clean operation followed immediately by an invalidate operation,
++ both performing to the same memory location. This functionality
++ is not correctly implemented in PL310 as clean lines are not
++ invalidated as a result of these operations. Note that this errata
++ uses Texas Instrument's secure monitor api.
++
++config ARM_ERRATA_720789
++ bool "ARM errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID"
++ depends on CPU_V7 && SMP
++ help
++ This option enables the workaround for the 720789 Cortex-A9 (prior to
++ r2p0) erratum. A faulty ASID can be sent to the other CPUs for the
++ broadcasted CP15 TLB maintenance operations TLBIASIDIS and TLBIMVAIS.
++ As a consequence of this erratum, some TLB entries which should be
++ invalidated are not, resulting in an incoherency in the system page
++ tables. The workaround changes the TLB flushing routines to invalidate
++ entries regardless of the ASID.
++endmenu
++
++source "arch/arm/common/Kconfig"
++
++config FORCE_MAX_ZONEORDER
++ int
++ depends on SA1111
++ default "9"
++
++menu "Bus support"
++
++config ARM_AMBA
++ bool
++
++config ISA
++ bool
++ help
++ Find out whether you have ISA slots on your motherboard. ISA is the
++ name of a bus system, i.e. the way the CPU talks to the other stuff
++ inside your box. Other bus systems are PCI, EISA, MicroChannel
++ (MCA) or VESA. ISA is an older system, now being displaced by PCI;
++ newer boards don't support it. If you have ISA, say Y, otherwise N.
++
++# Select ISA DMA controller support
++config ISA_DMA
++ bool
++ select ISA_DMA_API
++
++# Select ISA DMA interface
++config ISA_DMA_API
++ bool
++
++config PCI
++ bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE
++ help
++ Find out whether you have a PCI motherboard. PCI is the name of a
++ bus system, i.e. the way the CPU talks to the other stuff inside
++ your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
++ VESA. If you have PCI, say Y, otherwise N.
++
++config PCI_DOMAINS
++ bool
++ depends on PCI
++
++config PCI_SYSCALL
++ def_bool PCI
++
++# Select the host bridge type
++config PCI_HOST_VIA82C505
++ bool
++ depends on PCI && ARCH_SHARK
++ default y
++
++config PCI_HOST_ITE8152
++ bool
++ depends on PCI && MACH_ARMCORE
++ default y
++ select DMABOUNCE
++
++source "drivers/pci/Kconfig"
++
++source "drivers/pcmcia/Kconfig"
++
++endmenu
++
++menu "Kernel Features"
++
++source "kernel/time/Kconfig"
++
++config SMP
++ bool "Symmetric Multi-Processing (EXPERIMENTAL)"
++ depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP ||\
++ MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\
++ ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
++ depends on GENERIC_CLOCKEVENTS
++ select USE_GENERIC_SMP_HELPERS
++ select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
++ help
++ This enables support for systems with more than one CPU. If you have
++ a system with only one CPU, like most personal computers, say N. If
++ you have a system with more than one CPU, say Y.
++
++ If you say N here, the kernel will run on single and multiprocessor
++ machines, but will use only one CPU of a multiprocessor machine. If
++ you say Y here, the kernel will run on many, but not all, single
++ processor machines. On a single processor machine, the kernel will
++ run faster if you say N here.
++
++ See also <file:Documentation/i386/IO-APIC.txt>,
++ <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
++ <http://www.linuxdoc.org/docs.html#howto>.
++
++ If you don't know what to do here, say N.
++
++config HAVE_ARM_SCU
++ bool
++ depends on SMP
++ help
++ This option enables support for the ARM system coherency unit
++
++config HAVE_ARM_TWD
++ bool
++ depends on SMP
++ help
++ This options enables support for the ARM timer and watchdog unit
++
++choice
++ prompt "Memory split"
++ default VMSPLIT_3G
++ help
++ Select the desired split between kernel and user memory.
++
++ If you are not absolutely sure what you are doing, leave this
++ option alone!
++
++ config VMSPLIT_3G
++ bool "3G/1G user/kernel split"
++ config VMSPLIT_2G
++ bool "2G/2G user/kernel split"
++ config VMSPLIT_1G
++ bool "1G/3G user/kernel split"
++endchoice
++
++config PAGE_OFFSET
++ hex
++ default 0x40000000 if VMSPLIT_1G
++ default 0x80000000 if VMSPLIT_2G
++ default 0xC0000000
++
++config NR_CPUS
++ int "Maximum number of CPUs (2-32)"
++ range 2 32
++ depends on SMP
++ default "4"
++
++config HOTPLUG_CPU
++ bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
++ depends on SMP && HOTPLUG && EXPERIMENTAL
++ help
++ Say Y here to experiment with turning CPUs off and on. CPUs
++ can be controlled through /sys/devices/system/cpu.
++
++config LOCAL_TIMERS
++ bool "Use local timer interrupts"
++ depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \
++ REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || ARCH_U8500)
++ default y
++ select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500)
++ help
++ Enable support for local timers on SMP platforms, rather then the
++ legacy IPI broadcast method. Local timers allows the system
++ accounting to be spread across the timer interval, preventing a
++ "thundering herd" at every timer tick.
++
++source kernel/Kconfig.preempt
++
++config HZ
++ int
++ default 128 if ARCH_L7200
++ default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PV210
++ default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER
++ default AT91_TIMER_HZ if ARCH_AT91
++ default 100
++
++config THUMB2_KERNEL
++ bool "Compile the kernel in Thumb-2 mode"
++ depends on CPU_V7 && EXPERIMENTAL
++ select AEABI
++ select ARM_ASM_UNIFIED
++ help
++ By enabling this option, the kernel will be compiled in
++ Thumb-2 mode. A compiler/assembler that understand the unified
++ ARM-Thumb syntax is needed.
++
++ If unsure, say N.
++
++config ARM_ASM_UNIFIED
++ bool
++
++config AEABI
++ bool "Use the ARM EABI to compile the kernel"
++ help
++ This option allows for the kernel to be compiled using the latest
++ ARM ABI (aka EABI). This is only useful if you are using a user
++ space environment that is also compiled with EABI.
++
++ Since there are major incompatibilities between the legacy ABI and
++ EABI, especially with regard to structure member alignment, this
++ option also changes the kernel syscall calling convention to
++ disambiguate both ABIs and allow for backward compatibility support
++ (selected with CONFIG_OABI_COMPAT).
++
++ To use this you need GCC version 4.0.0 or later.
++
++config OABI_COMPAT
++ bool "Allow old ABI binaries to run with this kernel (EXPERIMENTAL)"
++ depends on AEABI && EXPERIMENTAL
++ default y
++ help
++ This option preserves the old syscall interface along with the
++ new (ARM EABI) one. It also provides a compatibility layer to
++ intercept syscalls that have structure arguments which layout
++ in memory differs between the legacy ABI and the new ARM EABI
++ (only for non "thumb" binaries). This option adds a tiny
++ overhead to all syscalls and produces a slightly larger kernel.
++ If you know you'll be using only pure EABI user space then you
++ can say N here. If this option is not selected and you attempt
++ to execute a legacy ABI binary then the result will be
++ UNPREDICTABLE (in fact it can be predicted that it won't work
++ at all). If in doubt say Y.
++
++config ARCH_HAS_HOLES_MEMORYMODEL
++ bool
++
++# Discontigmem is deprecated
++config ARCH_DISCONTIGMEM_ENABLE
++ bool
++
++config ARCH_SPARSEMEM_ENABLE
++ bool
++
++config ARCH_SPARSEMEM_DEFAULT
++ def_bool ARCH_SPARSEMEM_ENABLE
++
++config ARCH_SELECT_MEMORY_MODEL
++ def_bool ARCH_DISCONTIGMEM_ENABLE && ARCH_SPARSEMEM_ENABLE
++
++config NODES_SHIFT
++ int
++ default "4" if ARCH_LH7A40X
++ default "2"
++ depends on NEED_MULTIPLE_NODES
++
++config HIGHMEM
++ bool "High Memory Support (EXPERIMENTAL)"
++ depends on MMU && EXPERIMENTAL
++ help
++ The address space of ARM processors is only 4 Gigabytes large
++ and it has to accommodate user address space, kernel address
++ space as well as some memory mapped IO. That means that, if you
++ have a large amount of physical memory and/or IO, not all of the
++ memory can be "permanently mapped" by the kernel. The physical
++ memory that is not permanently mapped is called "high memory".
++
++ Depending on the selected kernel/user memory split, minimum
++ vmalloc space and actual amount of RAM, you may not need this
++ option which should result in a slightly faster kernel.
++
++ If unsure, say n.
++
++config HIGHPTE
++ bool "Allocate 2nd-level pagetables from highmem"
++ depends on HIGHMEM
++ depends on !OUTER_CACHE
++
++config HW_PERF_EVENTS
++ bool "Enable hardware performance counter support for perf events"
++ depends on PERF_EVENTS && CPU_HAS_PMU
++ default y
++ help
++ Enable hardware performance counter support for perf events. If
++ disabled, perf events will use software events only.
++
++source "mm/Kconfig"
++
++config LEDS
++ bool "Timer and CPU usage LEDs"
++ depends on ARCH_CDB89712 || ARCH_EBSA110 || \
++ ARCH_EBSA285 || ARCH_INTEGRATOR || \
++ ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \
++ ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \
++ ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \
++ ARCH_AT91 || ARCH_DAVINCI || \
++ ARCH_KS8695 || MACH_RD88F5182 || ARCH_REALVIEW
++ help
++ If you say Y here, the LEDs on your machine will be used
++ to provide useful information about your current system status.
++
++ If you are compiling a kernel for a NetWinder or EBSA-285, you will
++ be able to select which LEDs are active using the options below. If
++ you are compiling a kernel for the EBSA-110 or the LART however, the
++ red LED will simply flash regularly to indicate that the system is
++ still functional. It is safe to say Y here if you have a CATS
++ system, but the driver will do nothing.
++
++config LEDS_TIMER
++ bool "Timer LED" if (!ARCH_CDB89712 && !ARCH_OMAP) || \
++ OMAP_OSK_MISTRAL || MACH_OMAP_H2 \
++ || MACH_OMAP_PERSEUS2
++ depends on LEDS
++ depends on !GENERIC_CLOCKEVENTS
++ default y if ARCH_EBSA110
++ help
++ If you say Y here, one of the system LEDs (the green one on the
++ NetWinder, the amber one on the EBSA285, or the red one on the LART)
++ will flash regularly to indicate that the system is still
++ operational. This is mainly useful to kernel hackers who are
++ debugging unstable kernels.
++
++ The LART uses the same LED for both Timer LED and CPU usage LED
++ functions. You may choose to use both, but the Timer LED function
++ will overrule the CPU usage LED.
++
++config LEDS_CPU
++ bool "CPU usage LED" if (!ARCH_CDB89712 && !ARCH_EBSA110 && \
++ !ARCH_OMAP) \
++ || OMAP_OSK_MISTRAL || MACH_OMAP_H2 \
++ || MACH_OMAP_PERSEUS2
++ depends on LEDS
++ help
++ If you say Y here, the red LED will be used to give a good real
++ time indication of CPU usage, by lighting whenever the idle task
++ is not currently executing.
++
++ The LART uses the same LED for both Timer LED and CPU usage LED
++ functions. You may choose to use both, but the Timer LED function
++ will overrule the CPU usage LED.
++
++config ALIGNMENT_TRAP
++ bool
++ depends on CPU_CP15_MMU
++ default y if !ARCH_EBSA110
++ select HAVE_PROC_CPU if PROC_FS
++ help
++ ARM processors cannot fetch/store information which is not
++ naturally aligned on the bus, i.e., a 4 byte fetch must start at an
++ address divisible by 4. On 32-bit ARM processors, these non-aligned
++ fetch/store instructions will be emulated in software if you say
++ here, which has a severe performance impact. This is necessary for
++ correct operation of some network protocols. With an IP-only
++ configuration it is safe to say N, otherwise say Y.
++
++config UACCESS_WITH_MEMCPY
++ bool "Use kernel mem{cpy,set}() for {copy_to,clear}_user() (EXPERIMENTAL)"
++ depends on MMU && EXPERIMENTAL
++ default y if CPU_FEROCEON
++ help
++ Implement faster copy_to_user and clear_user methods for CPU
++ cores where a 8-word STM instruction give significantly higher
++ memory write throughput than a sequence of individual 32bit stores.
++
++ A possible side effect is a slight increase in scheduling latency
++ between threads sharing the same address space if they invoke
++ such copy operations with large buffers.
++
++ However, if the CPU data cache is using a write-allocate mode,
++ this option is unlikely to provide any performance gain.
++
++endmenu
++
++menu "Boot options"
++
++# Compressed boot loader in ROM. Yes, we really want to ask about
++# TEXT and BSS so we preserve their values in the config files.
++config ZBOOT_ROM_TEXT
++ hex "Compressed ROM boot loader base address"
++ default "0"
++ help
++ The physical address at which the ROM-able zImage is to be
++ placed in the target. Platforms which normally make use of
++ ROM-able zImage formats normally set this to a suitable
++ value in their defconfig file.
++
++ If ZBOOT_ROM is not enabled, this has no effect.
++
++config ZBOOT_ROM_BSS
++ hex "Compressed ROM boot loader BSS address"
++ default "0"
++ help
++ The base address of an area of read/write memory in the target
++ for the ROM-able zImage which must be available while the
++ decompressor is running. It must be large enough to hold the
++ entire decompressed kernel plus an additional 128 KiB.
++ Platforms which normally make use of ROM-able zImage formats
++ normally set this to a suitable value in their defconfig file.
++
++ If ZBOOT_ROM is not enabled, this has no effect.
++
++config ZBOOT_ROM
++ bool "Compressed boot loader in ROM/flash"
++ depends on ZBOOT_ROM_TEXT != ZBOOT_ROM_BSS
++ help
++ Say Y here if you intend to execute your compressed kernel image
++ (zImage) directly from ROM or flash. If unsure, say N.
++
++config CMDLINE
++ string "Default kernel command string"
++ default ""
++ help
++ On some architectures (EBSA110 and CATS), there is currently no way
++ for the boot loader to pass arguments to the kernel. For these
++ architectures, you should supply some command-line options at build
++ time by entering them here. As a minimum, you should specify the
++ memory size and the root device (e.g., mem=64M root=/dev/nfs).
++
++config CMDLINE_FORCE
++ bool "Always use the default kernel command string"
++ depends on CMDLINE != ""
++ help
++ Always use the default kernel command string, even if the boot
++ loader passes other arguments to the kernel.
++ This is useful if you cannot or don't want to change the
++ command-line options your boot loader passes to the kernel.
++
++ If unsure, say N.
++
++config XIP_KERNEL
++ bool "Kernel Execute-In-Place from ROM"
++ depends on !ZBOOT_ROM
++ help
++ Execute-In-Place allows the kernel to run from non-volatile storage
++ directly addressable by the CPU, such as NOR flash. This saves RAM
++ space since the text section of the kernel is not loaded from flash
++ to RAM. Read-write sections, such as the data section and stack,
++ are still copied to RAM. The XIP kernel is not compressed since
++ it has to run directly from flash, so it will take more space to
++ store it. The flash address used to link the kernel object files,
++ and for storing it, is configuration dependent. Therefore, if you
++ say Y here, you must know the proper physical address where to
++ store the kernel image depending on your own flash memory usage.
++
++ Also note that the make target becomes "make xipImage" rather than
++ "make zImage" or "make Image". The final kernel binary to put in
++ ROM memory will be arch/arm/boot/xipImage.
++
++ If unsure, say N.
++
++config XIP_PHYS_ADDR
++ hex "XIP Kernel Physical Location"
++ depends on XIP_KERNEL
++ default "0x00080000"
++ help
++ This is the physical address in your flash memory the kernel will
++ be linked for and stored to. This address is dependent on your
++ own flash usage.
++
++config KEXEC
++ bool "Kexec system call (EXPERIMENTAL)"
++ depends on EXPERIMENTAL
++ help
++ kexec is a system call that implements the ability to shutdown your
++ current kernel, and to start another kernel. It is like a reboot
++ but it is independent of the system firmware. And like a reboot
++ you can start any kernel with it, not just Linux.
++
++ It is an ongoing process to be certain the hardware in a machine
++ is properly shutdown, so do not be surprised if this code does not
++ initially work for you. It may help to enable device hotplugging
++ support.
++
++config ATAGS_PROC
++ bool "Export atags in procfs"
++ depends on KEXEC
++ default y
++ help
++ Should the atags used to boot the kernel be exported in an "atags"
++ file in procfs. Useful with kexec.
++
++endmenu
++
++menu "CPU Power Management"
++
++if ARCH_HAS_CPUFREQ
++
++source "drivers/cpufreq/Kconfig"
++
++config CPU_FREQ_SA1100
++ bool
++
++config CPU_FREQ_SA1110
++ bool
++
++config CPU_FREQ_INTEGRATOR
++ tristate "CPUfreq driver for ARM Integrator CPUs"
++ depends on ARCH_INTEGRATOR && CPU_FREQ
++ default y
++ help
++ This enables the CPUfreq driver for ARM Integrator CPUs.
++
++ For details, take a look at <file:Documentation/cpu-freq>.
++
++ If in doubt, say Y.
++
++config CPU_FREQ_PXA
++ bool
++ depends on CPU_FREQ && ARCH_PXA && PXA25x
++ default y
++ select CPU_FREQ_DEFAULT_GOV_USERSPACE
++
++config CPU_FREQ_S3C64XX
++ bool "CPUfreq support for Samsung S3C64XX CPUs"
++ depends on CPU_FREQ && CPU_S3C6410
++
++config CPU_FREQ_S3C
++ bool
++ help
++ Internal configuration node for common cpufreq on Samsung SoC
++
++config CPU_FREQ_S3C24XX
++ bool "CPUfreq driver for Samsung S3C24XX series CPUs"
++ depends on ARCH_S3C2410 && CPU_FREQ && EXPERIMENTAL
++ select CPU_FREQ_S3C
++ help
++ This enables the CPUfreq driver for the Samsung S3C24XX family
++ of CPUs.
++
++ For details, take a look at <file:Documentation/cpu-freq>.
++
++ If in doubt, say N.
++
++config CPU_FREQ_S3C24XX_PLL
++ bool "Support CPUfreq changing of PLL frequency"
++ depends on CPU_FREQ_S3C24XX && EXPERIMENTAL
++ help
++ Compile in support for changing the PLL frequency from the
++ S3C24XX series CPUfreq driver. The PLL takes time to settle
++ after a frequency change, so by default it is not enabled.
++
++ This also means that the PLL tables for the selected CPU(s) will
++ be built which may increase the size of the kernel image.
++
++config CPU_FREQ_S3C24XX_DEBUG
++ bool "Debug CPUfreq Samsung driver core"
++ depends on CPU_FREQ_S3C24XX
++ help
++ Enable s3c_freq_dbg for the Samsung S3C CPUfreq core
++
++config CPU_FREQ_S3C24XX_IODEBUG
++ bool "Debug CPUfreq Samsung driver IO timing"
++ depends on CPU_FREQ_S3C24XX
++ help
++ Enable s3c_freq_iodbg for the Samsung S3C CPUfreq core
++
++config CPU_FREQ_S3C24XX_DEBUGFS
++ bool "Export debugfs for CPUFreq"
++ depends on CPU_FREQ_S3C24XX && DEBUG_FS
++ help
++ Export status information via debugfs.
++
++endif
++
++source "drivers/cpuidle/Kconfig"
++
++endmenu
++
++menu "Floating point emulation"
++
++comment "At least one emulation must be selected"
++
++config FPE_NWFPE
++ bool "NWFPE math emulation"
++ depends on !AEABI || OABI_COMPAT
++ ---help---
++ Say Y to include the NWFPE floating point emulator in the kernel.
++ This is necessary to run most binaries. Linux does not currently
++ support floating point hardware so you need to say Y here even if
++ your machine has an FPA or floating point co-processor podule.
++
++ You may say N here if you are going to load the Acorn FPEmulator
++ early in the bootup.
++
++config FPE_NWFPE_XP
++ bool "Support extended precision"
++ depends on FPE_NWFPE
++ help
++ Say Y to include 80-bit support in the kernel floating-point
++ emulator. Otherwise, only 32 and 64-bit support is compiled in.
++ Note that gcc does not generate 80-bit operations by default,
++ so in most cases this option only enlarges the size of the
++ floating point emulator without any good reason.
++
++ You almost surely want to say N here.
++
++config FPE_FASTFPE
++ bool "FastFPE math emulation (EXPERIMENTAL)"
++ depends on (!AEABI || OABI_COMPAT) && !CPU_32v3 && EXPERIMENTAL
++ ---help---
++ Say Y here to include the FAST floating point emulator in the kernel.
++ This is an experimental much faster emulator which now also has full
++ precision for the mantissa. It does not support any exceptions.
++ It is very simple, and approximately 3-6 times faster than NWFPE.
++
++ It should be sufficient for most programs. It may be not suitable
++ for scientific calculations, but you have to check this for yourself.
++ If you do not feel you need a faster FP emulation you should better
++ choose NWFPE.
++
++config VFP
++ bool "VFP-format floating point maths"
++ depends on CPU_V6 || CPU_ARM926T || CPU_V7 || CPU_FEROCEON
++ help
++ Say Y to include VFP support code in the kernel. This is needed
++ if your hardware includes a VFP unit.
++
++ Please see <file:Documentation/arm/VFP/release-notes.txt> for
++ release notes and additional status information.
++
++ Say N if your target does not have VFP hardware.
++
++config VFPv3
++ bool
++ depends on VFP
++ default y if CPU_V7
++
++config NEON
++ bool "Advanced SIMD (NEON) Extension support"
++ depends on VFPv3 && CPU_V7
++ help
++ Say Y to include support code for NEON, the ARMv7 Advanced SIMD
++ Extension.
++
++endmenu
++
++menu "Userspace binary formats"
++
++source "fs/Kconfig.binfmt"
++
++config ARTHUR
++ tristate "RISC OS personality"
++ depends on !AEABI
++ help
++ Say Y here to include the kernel code necessary if you want to run
++ Acorn RISC OS/Arthur binaries under Linux. This code is still very
++ experimental; if this sounds frightening, say N and sleep in peace.
++ You can also say M here to compile this support as a module (which
++ will be called arthur).
++
++endmenu
++
++menu "Power management options"
++
++source "kernel/power/Kconfig"
++
++config ARCH_SUSPEND_POSSIBLE
++ def_bool y
++
++endmenu
++
++source "net/Kconfig"
++
++source "drivers/Kconfig"
++
++source "fs/Kconfig"
++
++source "arch/arm/Kconfig.debug"
++
++source "security/Kconfig"
++
++source "crypto/Kconfig"
++
++source "lib/Kconfig"
+diff -rupN linux-2.6.35.11/arch/arm/kernel/bios32.c linux-2.6.35.11-ts7500/arch/arm/kernel/bios32.c
+--- linux-2.6.35.11/arch/arm/kernel/bios32.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/kernel/bios32.c 2011-03-14 11:18:24.000000000 -0400
+@@ -360,7 +360,7 @@ pbus_assign_bus_resources(struct pci_bus
+ * pcibios_fixup_bus - Called after each bus is probed,
+ * but before its children are examined.
+ */
+-void pcibios_fixup_bus(struct pci_bus *bus)
++void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+ {
+ struct pci_sys_data *root = bus->sysdata;
+ struct pci_dev *dev;
+diff -rupN linux-2.6.35.11/arch/arm/kernel/entry-armv.S linux-2.6.35.11-ts7500/arch/arm/kernel/entry-armv.S
+--- linux-2.6.35.11/arch/arm/kernel/entry-armv.S 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/kernel/entry-armv.S 2011-03-14 11:18:24.000000000 -0400
+@@ -30,6 +30,11 @@
+ */
+ .macro irq_handler
+ get_irqnr_preamble r5, lr
++#ifdef CONFIG_VIC_INTERRUPT
++ get_irqnr_and_base r0, r6, r5, lr
++ mov r1, sp
++ bl asm_do_IRQ
++#else
+ 1: get_irqnr_and_base r0, r6, r5, lr
+ movne r1, sp
+ @
+@@ -37,6 +42,7 @@
+ @
+ adrne lr, BSYM(1b)
+ bne asm_do_IRQ
++#endif
+
+ #ifdef CONFIG_SMP
+ /*
+diff -rupN linux-2.6.35.11/arch/arm/kernel/entry-armv.S.orig linux-2.6.35.11-ts7500/arch/arm/kernel/entry-armv.S.orig
+--- linux-2.6.35.11/arch/arm/kernel/entry-armv.S.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/kernel/entry-armv.S.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,1249 @@
++/*
++ * linux/arch/arm/kernel/entry-armv.S
++ *
++ * Copyright (C) 1996,1997,1998 Russell King.
++ * ARM700 fix by Matthew Godbolt (linux-user at willothewisp.demon.co.uk)
++ * nommu support by Hyok S. Choi (hyok.choi at samsung.com)
++ *
++ * 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.
++ *
++ * Low-level vector interface routines
++ *
++ * Note: there is a StrongARM bug in the STMIA rn, {regs}^ instruction
++ * that causes it to save wrong values... Be aware!
++ */
++
++#include <asm/memory.h>
++#include <asm/glue.h>
++#include <asm/vfpmacros.h>
++#include <mach/entry-macro.S>
++#include <asm/thread_notify.h>
++#include <asm/unwind.h>
++#include <asm/unistd.h>
++
++#include "entry-header.S"
++
++/*
++ * Interrupt handling. Preserves r7, r8, r9
++ */
++ .macro irq_handler
++ get_irqnr_preamble r5, lr
++1: get_irqnr_and_base r0, r6, r5, lr
++ movne r1, sp
++ @
++ @ routine called with r0 = irq number, r1 = struct pt_regs *
++ @
++ adrne lr, BSYM(1b)
++ bne asm_do_IRQ
++
++#ifdef CONFIG_SMP
++ /*
++ * XXX
++ *
++ * this macro assumes that irqstat (r6) and base (r5) are
++ * preserved from get_irqnr_and_base above
++ */
++ test_for_ipi r0, r6, r5, lr
++ movne r0, sp
++ adrne lr, BSYM(1b)
++ bne do_IPI
++
++#ifdef CONFIG_LOCAL_TIMERS
++ test_for_ltirq r0, r6, r5, lr
++ movne r0, sp
++ adrne lr, BSYM(1b)
++ bne do_local_timer
++#endif
++#endif
++
++ .endm
++
++#ifdef CONFIG_KPROBES
++ .section .kprobes.text,"ax",%progbits
++#else
++ .text
++#endif
++
++/*
++ * Invalid mode handlers
++ */
++ .macro inv_entry, reason
++ sub sp, sp, #S_FRAME_SIZE
++ ARM( stmib sp, {r1 - lr} )
++ THUMB( stmia sp, {r0 - r12} )
++ THUMB( str sp, [sp, #S_SP] )
++ THUMB( str lr, [sp, #S_LR] )
++ mov r1, #\reason
++ .endm
++
++__pabt_invalid:
++ inv_entry BAD_PREFETCH
++ b common_invalid
++ENDPROC(__pabt_invalid)
++
++__dabt_invalid:
++ inv_entry BAD_DATA
++ b common_invalid
++ENDPROC(__dabt_invalid)
++
++__irq_invalid:
++ inv_entry BAD_IRQ
++ b common_invalid
++ENDPROC(__irq_invalid)
++
++__und_invalid:
++ inv_entry BAD_UNDEFINSTR
++
++ @
++ @ XXX fall through to common_invalid
++ @
++
++@
++@ common_invalid - generic code for failed exception (re-entrant version of handlers)
++@
++common_invalid:
++ zero_fp
++
++ ldmia r0, {r4 - r6}
++ add r0, sp, #S_PC @ here for interlock avoidance
++ mov r7, #-1 @ "" "" "" ""
++ str r4, [sp] @ save preserved r0
++ stmia r0, {r5 - r7} @ lr_<exception>,
++ @ cpsr_<exception>, "old_r0"
++
++ mov r0, sp
++ b bad_mode
++ENDPROC(__und_invalid)
++
++/*
++ * SVC mode handlers
++ */
++
++#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5)
++#define SPFIX(code...) code
++#else
++#define SPFIX(code...)
++#endif
++
++ .macro svc_entry, stack_hole=0
++ UNWIND(.fnstart )
++ UNWIND(.save {r0 - pc} )
++ sub sp, sp, #(S_FRAME_SIZE + \stack_hole - 4)
++#ifdef CONFIG_THUMB2_KERNEL
++ SPFIX( str r0, [sp] ) @ temporarily saved
++ SPFIX( mov r0, sp )
++ SPFIX( tst r0, #4 ) @ test original stack alignment
++ SPFIX( ldr r0, [sp] ) @ restored
++#else
++ SPFIX( tst sp, #4 )
++#endif
++ SPFIX( subeq sp, sp, #4 )
++ stmia sp, {r1 - r12}
++
++ ldmia r0, {r1 - r3}
++ add r5, sp, #S_SP - 4 @ here for interlock avoidance
++ mov r4, #-1 @ "" "" "" ""
++ add r0, sp, #(S_FRAME_SIZE + \stack_hole - 4)
++ SPFIX( addeq r0, r0, #4 )
++ str r1, [sp, #-4]! @ save the "real" r0 copied
++ @ from the exception stack
++
++ mov r1, lr
++
++ @
++ @ We are now ready to fill in the remaining blanks on the stack:
++ @
++ @ r0 - sp_svc
++ @ r1 - lr_svc
++ @ r2 - lr_<exception>, already fixed up for correct return/restart
++ @ r3 - spsr_<exception>
++ @ r4 - orig_r0 (see pt_regs definition in ptrace.h)
++ @
++ stmia r5, {r0 - r4}
++ .endm
++
++ .align 5
++__dabt_svc:
++ svc_entry
++
++ @
++ @ get ready to re-enable interrupts if appropriate
++ @
++ mrs r9, cpsr
++ tst r3, #PSR_I_BIT
++ biceq r9, r9, #PSR_I_BIT
++
++ @
++ @ Call the processor-specific abort handler:
++ @
++ @ r2 - aborted context pc
++ @ r3 - aborted context cpsr
++ @
++ @ The abort handler must return the aborted address in r0, and
++ @ the fault status register in r1. r9 must be preserved.
++ @
++#ifdef MULTI_DABORT
++ ldr r4, .LCprocfns
++ mov lr, pc
++ ldr pc, [r4, #PROCESSOR_DABT_FUNC]
++#else
++ bl CPU_DABORT_HANDLER
++#endif
++
++ @
++ @ set desired IRQ state, then call main handler
++ @
++ msr cpsr_c, r9
++ mov r2, sp
++ bl do_DataAbort
++
++ @
++ @ IRQs off again before pulling preserved data off the stack
++ @
++ disable_irq_notrace
++
++ @
++ @ restore SPSR and restart the instruction
++ @
++ ldr r2, [sp, #S_PSR]
++ svc_exit r2 @ return from exception
++ UNWIND(.fnend )
++ENDPROC(__dabt_svc)
++
++ .align 5
++__irq_svc:
++ svc_entry
++
++#ifdef CONFIG_TRACE_IRQFLAGS
++ bl trace_hardirqs_off
++#endif
++#ifdef CONFIG_PREEMPT
++ get_thread_info tsk
++ ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
++ add r7, r8, #1 @ increment it
++ str r7, [tsk, #TI_PREEMPT]
++#endif
++
++ irq_handler
++#ifdef CONFIG_PREEMPT
++ str r8, [tsk, #TI_PREEMPT] @ restore preempt count
++ ldr r0, [tsk, #TI_FLAGS] @ get flags
++ teq r8, #0 @ if preempt count != 0
++ movne r0, #0 @ force flags to 0
++ tst r0, #_TIF_NEED_RESCHED
++ blne svc_preempt
++#endif
++ ldr r4, [sp, #S_PSR] @ irqs are already disabled
++#ifdef CONFIG_TRACE_IRQFLAGS
++ tst r4, #PSR_I_BIT
++ bleq trace_hardirqs_on
++#endif
++ svc_exit r4 @ return from exception
++ UNWIND(.fnend )
++ENDPROC(__irq_svc)
++
++ .ltorg
++
++#ifdef CONFIG_PREEMPT
++svc_preempt:
++ mov r8, lr
++1: bl preempt_schedule_irq @ irq en/disable is done inside
++ ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS
++ tst r0, #_TIF_NEED_RESCHED
++ moveq pc, r8 @ go again
++ b 1b
++#endif
++
++ .align 5
++__und_svc:
++#ifdef CONFIG_KPROBES
++ @ If a kprobe is about to simulate a "stmdb sp..." instruction,
++ @ it obviously needs free stack space which then will belong to
++ @ the saved context.
++ svc_entry 64
++#else
++ svc_entry
++#endif
++
++ @
++ @ call emulation code, which returns using r9 if it has emulated
++ @ the instruction, or the more conventional lr if we are to treat
++ @ this as a real undefined instruction
++ @
++ @ r0 - instruction
++ @
++#ifndef CONFIG_THUMB2_KERNEL
++ ldr r0, [r2, #-4]
++#else
++ ldrh r0, [r2, #-2] @ Thumb instruction at LR - 2
++ and r9, r0, #0xf800
++ cmp r9, #0xe800 @ 32-bit instruction if xx >= 0
++ ldrhhs r9, [r2] @ bottom 16 bits
++ orrhs r0, r9, r0, lsl #16
++#endif
++ adr r9, BSYM(1f)
++ bl call_fpe
++
++ mov r0, sp @ struct pt_regs *regs
++ bl do_undefinstr
++
++ @
++ @ IRQs off again before pulling preserved data off the stack
++ @
++1: disable_irq_notrace
++
++ @
++ @ restore SPSR and restart the instruction
++ @
++ ldr r2, [sp, #S_PSR] @ Get SVC cpsr
++ svc_exit r2 @ return from exception
++ UNWIND(.fnend )
++ENDPROC(__und_svc)
++
++ .align 5
++__pabt_svc:
++ svc_entry
++
++ @
++ @ re-enable interrupts if appropriate
++ @
++ mrs r9, cpsr
++ tst r3, #PSR_I_BIT
++ biceq r9, r9, #PSR_I_BIT
++
++ mov r0, r2 @ pass address of aborted instruction.
++#ifdef MULTI_PABORT
++ ldr r4, .LCprocfns
++ mov lr, pc
++ ldr pc, [r4, #PROCESSOR_PABT_FUNC]
++#else
++ bl CPU_PABORT_HANDLER
++#endif
++ msr cpsr_c, r9 @ Maybe enable interrupts
++ mov r2, sp @ regs
++ bl do_PrefetchAbort @ call abort handler
++
++ @
++ @ IRQs off again before pulling preserved data off the stack
++ @
++ disable_irq_notrace
++
++ @
++ @ restore SPSR and restart the instruction
++ @
++ ldr r2, [sp, #S_PSR]
++ svc_exit r2 @ return from exception
++ UNWIND(.fnend )
++ENDPROC(__pabt_svc)
++
++ .align 5
++.LCcralign:
++ .word cr_alignment
++#ifdef MULTI_DABORT
++.LCprocfns:
++ .word processor
++#endif
++.LCfp:
++ .word fp_enter
++
++/*
++ * User mode handlers
++ *
++ * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE
++ */
++
++#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7)
++#error "sizeof(struct pt_regs) must be a multiple of 8"
++#endif
++
++ .macro usr_entry
++ UNWIND(.fnstart )
++ UNWIND(.cantunwind ) @ don't unwind the user space
++ sub sp, sp, #S_FRAME_SIZE
++ ARM( stmib sp, {r1 - r12} )
++ THUMB( stmia sp, {r0 - r12} )
++
++ ldmia r0, {r1 - r3}
++ add r0, sp, #S_PC @ here for interlock avoidance
++ mov r4, #-1 @ "" "" "" ""
++
++ str r1, [sp] @ save the "real" r0 copied
++ @ from the exception stack
++
++ @
++ @ We are now ready to fill in the remaining blanks on the stack:
++ @
++ @ r2 - lr_<exception>, already fixed up for correct return/restart
++ @ r3 - spsr_<exception>
++ @ r4 - orig_r0 (see pt_regs definition in ptrace.h)
++ @
++ @ Also, separately save sp_usr and lr_usr
++ @
++ stmia r0, {r2 - r4}
++ ARM( stmdb r0, {sp, lr}^ )
++ THUMB( store_user_sp_lr r0, r1, S_SP - S_PC )
++
++ @
++ @ Enable the alignment trap while in kernel mode
++ @
++ alignment_trap r0
++
++ @
++ @ Clear FP to mark the first stack frame
++ @
++ zero_fp
++ .endm
++
++ .macro kuser_cmpxchg_check
++#if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
++#ifndef CONFIG_MMU
++#warning "NPTL on non MMU needs fixing"
++#else
++ @ Make sure our user space atomic helper is restarted
++ @ if it was interrupted in a critical region. Here we
++ @ perform a quick test inline since it should be false
++ @ 99.9999% of the time. The rest is done out of line.
++ cmp r2, #TASK_SIZE
++ blhs kuser_cmpxchg_fixup
++#endif
++#endif
++ .endm
++
++ .align 5
++__dabt_usr:
++ usr_entry
++ kuser_cmpxchg_check
++
++ @
++ @ Call the processor-specific abort handler:
++ @
++ @ r2 - aborted context pc
++ @ r3 - aborted context cpsr
++ @
++ @ The abort handler must return the aborted address in r0, and
++ @ the fault status register in r1.
++ @
++#ifdef MULTI_DABORT
++ ldr r4, .LCprocfns
++ mov lr, pc
++ ldr pc, [r4, #PROCESSOR_DABT_FUNC]
++#else
++ bl CPU_DABORT_HANDLER
++#endif
++
++ @
++ @ IRQs on, then call the main handler
++ @
++ enable_irq
++ mov r2, sp
++ adr lr, BSYM(ret_from_exception)
++ b do_DataAbort
++ UNWIND(.fnend )
++ENDPROC(__dabt_usr)
++
++ .align 5
++__irq_usr:
++ usr_entry
++ kuser_cmpxchg_check
++
++ get_thread_info tsk
++#ifdef CONFIG_PREEMPT
++ ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
++ add r7, r8, #1 @ increment it
++ str r7, [tsk, #TI_PREEMPT]
++#endif
++
++ irq_handler
++#ifdef CONFIG_PREEMPT
++ ldr r0, [tsk, #TI_PREEMPT]
++ str r8, [tsk, #TI_PREEMPT]
++ teq r0, r7
++ ARM( strne r0, [r0, -r0] )
++ THUMB( movne r0, #0 )
++ THUMB( strne r0, [r0] )
++#endif
++
++ mov why, #0
++ b ret_to_user
++ UNWIND(.fnend )
++ENDPROC(__irq_usr)
++
++ .ltorg
++
++ .align 5
++__und_usr:
++ usr_entry
++
++ @
++ @ fall through to the emulation code, which returns using r9 if
++ @ it has emulated the instruction, or the more conventional lr
++ @ if we are to treat this as a real undefined instruction
++ @
++ @ r0 - instruction
++ @
++ adr r9, BSYM(ret_from_exception)
++ adr lr, BSYM(__und_usr_unknown)
++ tst r3, #PSR_T_BIT @ Thumb mode?
++ itet eq @ explicit IT needed for the 1f label
++ subeq r4, r2, #4 @ ARM instr at LR - 4
++ subne r4, r2, #2 @ Thumb instr at LR - 2
++1: ldreqt r0, [r4]
++#ifdef CONFIG_CPU_ENDIAN_BE8
++ reveq r0, r0 @ little endian instruction
++#endif
++ beq call_fpe
++ @ Thumb instruction
++#if __LINUX_ARM_ARCH__ >= 7
++2:
++ ARM( ldrht r5, [r4], #2 )
++ THUMB( ldrht r5, [r4] )
++ THUMB( add r4, r4, #2 )
++ and r0, r5, #0xf800 @ mask bits 111x x... .... ....
++ cmp r0, #0xe800 @ 32bit instruction if xx != 0
++ blo __und_usr_unknown
++3: ldrht r0, [r4]
++ add r2, r2, #2 @ r2 is PC + 2, make it PC + 4
++ orr r0, r0, r5, lsl #16
++#else
++ b __und_usr_unknown
++#endif
++ UNWIND(.fnend )
++ENDPROC(__und_usr)
++
++ @
++ @ fallthrough to call_fpe
++ @
++
++/*
++ * The out of line fixup for the ldrt above.
++ */
++ .pushsection .fixup, "ax"
++4: mov pc, r9
++ .popsection
++ .pushsection __ex_table,"a"
++ .long 1b, 4b
++#if __LINUX_ARM_ARCH__ >= 7
++ .long 2b, 4b
++ .long 3b, 4b
++#endif
++ .popsection
++
++/*
++ * Check whether the instruction is a co-processor instruction.
++ * If yes, we need to call the relevant co-processor handler.
++ *
++ * Note that we don't do a full check here for the co-processor
++ * instructions; all instructions with bit 27 set are well
++ * defined. The only instructions that should fault are the
++ * co-processor instructions. However, we have to watch out
++ * for the ARM6/ARM7 SWI bug.
++ *
++ * NEON is a special case that has to be handled here. Not all
++ * NEON instructions are co-processor instructions, so we have
++ * to make a special case of checking for them. Plus, there's
++ * five groups of them, so we have a table of mask/opcode pairs
++ * to check against, and if any match then we branch off into the
++ * NEON handler code.
++ *
++ * Emulators may wish to make use of the following registers:
++ * r0 = instruction opcode.
++ * r2 = PC+4
++ * r9 = normal "successful" return address
++ * r10 = this threads thread_info structure.
++ * lr = unrecognised instruction return address
++ */
++ @
++ @ Fall-through from Thumb-2 __und_usr
++ @
++#ifdef CONFIG_NEON
++ adr r6, .LCneon_thumb_opcodes
++ b 2f
++#endif
++call_fpe:
++#ifdef CONFIG_NEON
++ adr r6, .LCneon_arm_opcodes
++2:
++ ldr r7, [r6], #4 @ mask value
++ cmp r7, #0 @ end mask?
++ beq 1f
++ and r8, r0, r7
++ ldr r7, [r6], #4 @ opcode bits matching in mask
++ cmp r8, r7 @ NEON instruction?
++ bne 2b
++ get_thread_info r10
++ mov r7, #1
++ strb r7, [r10, #TI_USED_CP + 10] @ mark CP#10 as used
++ strb r7, [r10, #TI_USED_CP + 11] @ mark CP#11 as used
++ b do_vfp @ let VFP handler handle this
++1:
++#endif
++ tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27
++ tstne r0, #0x04000000 @ bit 26 set on both ARM and Thumb-2
++#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
++ and r8, r0, #0x0f000000 @ mask out op-code bits
++ teqne r8, #0x0f000000 @ SWI (ARM6/7 bug)?
++#endif
++ moveq pc, lr
++ get_thread_info r10 @ get current thread
++ and r8, r0, #0x00000f00 @ mask out CP number
++ THUMB( lsr r8, r8, #8 )
++ mov r7, #1
++ add r6, r10, #TI_USED_CP
++ ARM( strb r7, [r6, r8, lsr #8] ) @ set appropriate used_cp[]
++ THUMB( strb r7, [r6, r8] ) @ set appropriate used_cp[]
++#ifdef CONFIG_IWMMXT
++ @ Test if we need to give access to iWMMXt coprocessors
++ ldr r5, [r10, #TI_FLAGS]
++ rsbs r7, r8, #(1 << 8) @ CP 0 or 1 only
++ movcss r7, r5, lsr #(TIF_USING_IWMMXT + 1)
++ bcs iwmmxt_task_enable
++#endif
++ ARM( add pc, pc, r8, lsr #6 )
++ THUMB( lsl r8, r8, #2 )
++ THUMB( add pc, r8 )
++ nop
++
++ movw_pc lr @ CP#0
++ W(b) do_fpe @ CP#1 (FPE)
++ W(b) do_fpe @ CP#2 (FPE)
++ movw_pc lr @ CP#3
++#ifdef CONFIG_CRUNCH
++ b crunch_task_enable @ CP#4 (MaverickCrunch)
++ b crunch_task_enable @ CP#5 (MaverickCrunch)
++ b crunch_task_enable @ CP#6 (MaverickCrunch)
++#else
++ movw_pc lr @ CP#4
++ movw_pc lr @ CP#5
++ movw_pc lr @ CP#6
++#endif
++ movw_pc lr @ CP#7
++ movw_pc lr @ CP#8
++ movw_pc lr @ CP#9
++#ifdef CONFIG_VFP
++ W(b) do_vfp @ CP#10 (VFP)
++ W(b) do_vfp @ CP#11 (VFP)
++#else
++ movw_pc lr @ CP#10 (VFP)
++ movw_pc lr @ CP#11 (VFP)
++#endif
++ movw_pc lr @ CP#12
++ movw_pc lr @ CP#13
++ movw_pc lr @ CP#14 (Debug)
++ movw_pc lr @ CP#15 (Control)
++
++#ifdef CONFIG_NEON
++ .align 6
++
++.LCneon_arm_opcodes:
++ .word 0xfe000000 @ mask
++ .word 0xf2000000 @ opcode
++
++ .word 0xff100000 @ mask
++ .word 0xf4000000 @ opcode
++
++ .word 0x00000000 @ mask
++ .word 0x00000000 @ opcode
++
++.LCneon_thumb_opcodes:
++ .word 0xef000000 @ mask
++ .word 0xef000000 @ opcode
++
++ .word 0xff100000 @ mask
++ .word 0xf9000000 @ opcode
++
++ .word 0x00000000 @ mask
++ .word 0x00000000 @ opcode
++#endif
++
++do_fpe:
++ enable_irq
++ ldr r4, .LCfp
++ add r10, r10, #TI_FPSTATE @ r10 = workspace
++ ldr pc, [r4] @ Call FP module USR entry point
++
++/*
++ * The FP module is called with these registers set:
++ * r0 = instruction
++ * r2 = PC+4
++ * r9 = normal "successful" return address
++ * r10 = FP workspace
++ * lr = unrecognised FP instruction return address
++ */
++
++ .pushsection .data
++ENTRY(fp_enter)
++ .word no_fp
++ .popsection
++
++ENTRY(no_fp)
++ mov pc, lr
++ENDPROC(no_fp)
++
++__und_usr_unknown:
++ enable_irq
++ mov r0, sp
++ adr lr, BSYM(ret_from_exception)
++ b do_undefinstr
++ENDPROC(__und_usr_unknown)
++
++ .align 5
++__pabt_usr:
++ usr_entry
++
++ mov r0, r2 @ pass address of aborted instruction.
++#ifdef MULTI_PABORT
++ ldr r4, .LCprocfns
++ mov lr, pc
++ ldr pc, [r4, #PROCESSOR_PABT_FUNC]
++#else
++ bl CPU_PABORT_HANDLER
++#endif
++ enable_irq @ Enable interrupts
++ mov r2, sp @ regs
++ bl do_PrefetchAbort @ call abort handler
++ UNWIND(.fnend )
++ /* fall through */
++/*
++ * This is the return code to user mode for abort handlers
++ */
++ENTRY(ret_from_exception)
++ UNWIND(.fnstart )
++ UNWIND(.cantunwind )
++ get_thread_info tsk
++ mov why, #0
++ b ret_to_user
++ UNWIND(.fnend )
++ENDPROC(__pabt_usr)
++ENDPROC(ret_from_exception)
++
++/*
++ * Register switch for ARMv3 and ARMv4 processors
++ * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
++ * previous and next are guaranteed not to be the same.
++ */
++ENTRY(__switch_to)
++ UNWIND(.fnstart )
++ UNWIND(.cantunwind )
++ add ip, r1, #TI_CPU_SAVE
++ ldr r3, [r2, #TI_TP_VALUE]
++ ARM( stmia ip!, {r4 - sl, fp, sp, lr} ) @ Store most regs on stack
++ THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack
++ THUMB( str sp, [ip], #4 )
++ THUMB( str lr, [ip], #4 )
++#ifdef CONFIG_MMU
++ ldr r6, [r2, #TI_CPU_DOMAIN]
++#endif
++#if defined(CONFIG_HAS_TLS_REG)
++ mcr p15, 0, r3, c13, c0, 3 @ set TLS register
++#elif !defined(CONFIG_TLS_REG_EMUL)
++ mov r4, #0xffff0fff
++ str r3, [r4, #-15] @ TLS val at 0xffff0ff0
++#endif
++#ifdef CONFIG_MMU
++ mcr p15, 0, r6, c3, c0, 0 @ Set domain register
++#endif
++ mov r5, r0
++ add r4, r2, #TI_CPU_SAVE
++ ldr r0, =thread_notify_head
++ mov r1, #THREAD_NOTIFY_SWITCH
++ bl atomic_notifier_call_chain
++ THUMB( mov ip, r4 )
++ mov r0, r5
++ ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously
++ THUMB( ldmia ip!, {r4 - sl, fp} ) @ Load all regs saved previously
++ THUMB( ldr sp, [ip], #4 )
++ THUMB( ldr pc, [ip] )
++ UNWIND(.fnend )
++ENDPROC(__switch_to)
++
++ __INIT
++
++/*
++ * User helpers.
++ *
++ * These are segment of kernel provided user code reachable from user space
++ * at a fixed address in kernel memory. This is used to provide user space
++ * with some operations which require kernel help because of unimplemented
++ * native feature and/or instructions in many ARM CPUs. The idea is for
++ * this code to be executed directly in user mode for best efficiency but
++ * which is too intimate with the kernel counter part to be left to user
++ * libraries. In fact this code might even differ from one CPU to another
++ * depending on the available instruction set and restrictions like on
++ * SMP systems. In other words, the kernel reserves the right to change
++ * this code as needed without warning. Only the entry points and their
++ * results are guaranteed to be stable.
++ *
++ * Each segment is 32-byte aligned and will be moved to the top of the high
++ * vector page. New segments (if ever needed) must be added in front of
++ * existing ones. This mechanism should be used only for things that are
++ * really small and justified, and not be abused freely.
++ *
++ * User space is expected to implement those things inline when optimizing
++ * for a processor that has the necessary native support, but only if such
++ * resulting binaries are already to be incompatible with earlier ARM
++ * processors due to the use of unsupported instructions other than what
++ * is provided here. In other words don't make binaries unable to run on
++ * earlier processors just for the sake of not using these kernel helpers
++ * if your compiled code is not going to use the new instructions for other
++ * purpose.
++ */
++ THUMB( .arm )
++
++ .macro usr_ret, reg
++#ifdef CONFIG_ARM_THUMB
++ bx \reg
++#else
++ mov pc, \reg
++#endif
++ .endm
++
++ .align 5
++ .globl __kuser_helper_start
++__kuser_helper_start:
++
++/*
++ * Reference prototype:
++ *
++ * void __kernel_memory_barrier(void)
++ *
++ * Input:
++ *
++ * lr = return address
++ *
++ * Output:
++ *
++ * none
++ *
++ * Clobbered:
++ *
++ * none
++ *
++ * Definition and user space usage example:
++ *
++ * typedef void (__kernel_dmb_t)(void);
++ * #define __kernel_dmb (*(__kernel_dmb_t *)0xffff0fa0)
++ *
++ * Apply any needed memory barrier to preserve consistency with data modified
++ * manually and __kuser_cmpxchg usage.
++ *
++ * This could be used as follows:
++ *
++ * #define __kernel_dmb() \
++ * asm volatile ( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #95" \
++ * : : : "r0", "lr","cc" )
++ */
++
++__kuser_memory_barrier: @ 0xffff0fa0
++ smp_dmb
++ usr_ret lr
++
++ .align 5
++
++/*
++ * Reference prototype:
++ *
++ * int __kernel_cmpxchg(int oldval, int newval, int *ptr)
++ *
++ * Input:
++ *
++ * r0 = oldval
++ * r1 = newval
++ * r2 = ptr
++ * lr = return address
++ *
++ * Output:
++ *
++ * r0 = returned value (zero or non-zero)
++ * C flag = set if r0 == 0, clear if r0 != 0
++ *
++ * Clobbered:
++ *
++ * r3, ip, flags
++ *
++ * Definition and user space usage example:
++ *
++ * typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr);
++ * #define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
++ *
++ * Atomically store newval in *ptr if *ptr is equal to oldval for user space.
++ * Return zero if *ptr was changed or non-zero if no exchange happened.
++ * The C flag is also set if *ptr was changed to allow for assembly
++ * optimization in the calling code.
++ *
++ * Notes:
++ *
++ * - This routine already includes memory barriers as needed.
++ *
++ * For example, a user space atomic_add implementation could look like this:
++ *
++ * #define atomic_add(ptr, val) \
++ * ({ register unsigned int *__ptr asm("r2") = (ptr); \
++ * register unsigned int __result asm("r1"); \
++ * asm volatile ( \
++ * "1: @ atomic_add\n\t" \
++ * "ldr r0, [r2]\n\t" \
++ * "mov r3, #0xffff0fff\n\t" \
++ * "add lr, pc, #4\n\t" \
++ * "add r1, r0, %2\n\t" \
++ * "add pc, r3, #(0xffff0fc0 - 0xffff0fff)\n\t" \
++ * "bcc 1b" \
++ * : "=&r" (__result) \
++ * : "r" (__ptr), "rIL" (val) \
++ * : "r0","r3","ip","lr","cc","memory" ); \
++ * __result; })
++ */
++
++__kuser_cmpxchg: @ 0xffff0fc0
++
++#if defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
++
++ /*
++ * Poor you. No fast solution possible...
++ * The kernel itself must perform the operation.
++ * A special ghost syscall is used for that (see traps.c).
++ */
++ stmfd sp!, {r7, lr}
++ ldr r7, =1f @ it's 20 bits
++ swi __ARM_NR_cmpxchg
++ ldmfd sp!, {r7, pc}
++1: .word __ARM_NR_cmpxchg
++
++#elif __LINUX_ARM_ARCH__ < 6
++
++#ifdef CONFIG_MMU
++
++ /*
++ * The only thing that can break atomicity in this cmpxchg
++ * implementation is either an IRQ or a data abort exception
++ * causing another process/thread to be scheduled in the middle
++ * of the critical sequence. To prevent this, code is added to
++ * the IRQ and data abort exception handlers to set the pc back
++ * to the beginning of the critical section if it is found to be
++ * within that critical section (see kuser_cmpxchg_fixup).
++ */
++1: ldr r3, [r2] @ load current val
++ subs r3, r3, r0 @ compare with oldval
++2: streq r1, [r2] @ store newval if eq
++ rsbs r0, r3, #0 @ set return val and C flag
++ usr_ret lr
++
++ .text
++kuser_cmpxchg_fixup:
++ @ Called from kuser_cmpxchg_check macro.
++ @ r2 = address of interrupted insn (must be preserved).
++ @ sp = saved regs. r7 and r8 are clobbered.
++ @ 1b = first critical insn, 2b = last critical insn.
++ @ If r2 >= 1b and r2 <= 2b then saved pc_usr is set to 1b.
++ mov r7, #0xffff0fff
++ sub r7, r7, #(0xffff0fff - (0xffff0fc0 + (1b - __kuser_cmpxchg)))
++ subs r8, r2, r7
++ rsbcss r8, r8, #(2b - 1b)
++ strcs r7, [sp, #S_PC]
++ mov pc, lr
++ .previous
++
++#else
++#warning "NPTL on non MMU needs fixing"
++ mov r0, #-1
++ adds r0, r0, #0
++ usr_ret lr
++#endif
++
++#else
++
++ smp_dmb
++1: ldrex r3, [r2]
++ subs r3, r3, r0
++ strexeq r3, r1, [r2]
++ teqeq r3, #1
++ beq 1b
++ rsbs r0, r3, #0
++ /* beware -- each __kuser slot must be 8 instructions max */
++#ifdef CONFIG_SMP
++ b __kuser_memory_barrier
++#else
++ usr_ret lr
++#endif
++
++#endif
++
++ .align 5
++
++/*
++ * Reference prototype:
++ *
++ * int __kernel_get_tls(void)
++ *
++ * Input:
++ *
++ * lr = return address
++ *
++ * Output:
++ *
++ * r0 = TLS value
++ *
++ * Clobbered:
++ *
++ * none
++ *
++ * Definition and user space usage example:
++ *
++ * typedef int (__kernel_get_tls_t)(void);
++ * #define __kernel_get_tls (*(__kernel_get_tls_t *)0xffff0fe0)
++ *
++ * Get the TLS value as previously set via the __ARM_NR_set_tls syscall.
++ *
++ * This could be used as follows:
++ *
++ * #define __kernel_get_tls() \
++ * ({ register unsigned int __val asm("r0"); \
++ * asm( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #31" \
++ * : "=r" (__val) : : "lr","cc" ); \
++ * __val; })
++ */
++
++__kuser_get_tls: @ 0xffff0fe0
++
++#if !defined(CONFIG_HAS_TLS_REG) && !defined(CONFIG_TLS_REG_EMUL)
++ ldr r0, [pc, #(16 - 8)] @ TLS stored at 0xffff0ff0
++#else
++ mrc p15, 0, r0, c13, c0, 3 @ read TLS register
++#endif
++ usr_ret lr
++
++ .rep 5
++ .word 0 @ pad up to __kuser_helper_version
++ .endr
++
++/*
++ * Reference declaration:
++ *
++ * extern unsigned int __kernel_helper_version;
++ *
++ * Definition and user space usage example:
++ *
++ * #define __kernel_helper_version (*(unsigned int *)0xffff0ffc)
++ *
++ * User space may read this to determine the curent number of helpers
++ * available.
++ */
++
++__kuser_helper_version: @ 0xffff0ffc
++ .word ((__kuser_helper_end - __kuser_helper_start) >> 5)
++
++ .globl __kuser_helper_end
++__kuser_helper_end:
++
++ THUMB( .thumb )
++
++/*
++ * Vector stubs.
++ *
++ * This code is copied to 0xffff0200 so we can use branches in the
++ * vectors, rather than ldr's. Note that this code must not
++ * exceed 0x300 bytes.
++ *
++ * Common stub entry macro:
++ * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
++ *
++ * SP points to a minimal amount of processor-private memory, the address
++ * of which is copied into r0 for the mode specific abort handler.
++ */
++ .macro vector_stub, name, mode, correction=0
++ .align 5
++
++vector_\name:
++ .if \correction
++ sub lr, lr, #\correction
++ .endif
++
++ @
++ @ Save r0, lr_<exception> (parent PC) and spsr_<exception>
++ @ (parent CPSR)
++ @
++ stmia sp, {r0, lr} @ save r0, lr
++ mrs lr, spsr
++ str lr, [sp, #8] @ save spsr
++
++ @
++ @ Prepare for SVC32 mode. IRQs remain disabled.
++ @
++ mrs r0, cpsr
++ eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
++ msr spsr_cxsf, r0
++
++ @
++ @ the branch table must immediately follow this code
++ @
++ and lr, lr, #0x0f
++ THUMB( adr r0, 1f )
++ THUMB( ldr lr, [r0, lr, lsl #2] )
++ mov r0, sp
++ ARM( ldr lr, [pc, lr, lsl #2] )
++ movs pc, lr @ branch to handler in SVC mode
++ENDPROC(vector_\name)
++
++ .align 2
++ @ handler addresses follow this label
++1:
++ .endm
++
++ .globl __stubs_start
++__stubs_start:
++/*
++ * Interrupt dispatcher
++ */
++ vector_stub irq, IRQ_MODE, 4
++
++ .long __irq_usr @ 0 (USR_26 / USR_32)
++ .long __irq_invalid @ 1 (FIQ_26 / FIQ_32)
++ .long __irq_invalid @ 2 (IRQ_26 / IRQ_32)
++ .long __irq_svc @ 3 (SVC_26 / SVC_32)
++ .long __irq_invalid @ 4
++ .long __irq_invalid @ 5
++ .long __irq_invalid @ 6
++ .long __irq_invalid @ 7
++ .long __irq_invalid @ 8
++ .long __irq_invalid @ 9
++ .long __irq_invalid @ a
++ .long __irq_invalid @ b
++ .long __irq_invalid @ c
++ .long __irq_invalid @ d
++ .long __irq_invalid @ e
++ .long __irq_invalid @ f
++
++/*
++ * Data abort dispatcher
++ * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
++ */
++ vector_stub dabt, ABT_MODE, 8
++
++ .long __dabt_usr @ 0 (USR_26 / USR_32)
++ .long __dabt_invalid @ 1 (FIQ_26 / FIQ_32)
++ .long __dabt_invalid @ 2 (IRQ_26 / IRQ_32)
++ .long __dabt_svc @ 3 (SVC_26 / SVC_32)
++ .long __dabt_invalid @ 4
++ .long __dabt_invalid @ 5
++ .long __dabt_invalid @ 6
++ .long __dabt_invalid @ 7
++ .long __dabt_invalid @ 8
++ .long __dabt_invalid @ 9
++ .long __dabt_invalid @ a
++ .long __dabt_invalid @ b
++ .long __dabt_invalid @ c
++ .long __dabt_invalid @ d
++ .long __dabt_invalid @ e
++ .long __dabt_invalid @ f
++
++/*
++ * Prefetch abort dispatcher
++ * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
++ */
++ vector_stub pabt, ABT_MODE, 4
++
++ .long __pabt_usr @ 0 (USR_26 / USR_32)
++ .long __pabt_invalid @ 1 (FIQ_26 / FIQ_32)
++ .long __pabt_invalid @ 2 (IRQ_26 / IRQ_32)
++ .long __pabt_svc @ 3 (SVC_26 / SVC_32)
++ .long __pabt_invalid @ 4
++ .long __pabt_invalid @ 5
++ .long __pabt_invalid @ 6
++ .long __pabt_invalid @ 7
++ .long __pabt_invalid @ 8
++ .long __pabt_invalid @ 9
++ .long __pabt_invalid @ a
++ .long __pabt_invalid @ b
++ .long __pabt_invalid @ c
++ .long __pabt_invalid @ d
++ .long __pabt_invalid @ e
++ .long __pabt_invalid @ f
++
++/*
++ * Undef instr entry dispatcher
++ * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
++ */
++ vector_stub und, UND_MODE
++
++ .long __und_usr @ 0 (USR_26 / USR_32)
++ .long __und_invalid @ 1 (FIQ_26 / FIQ_32)
++ .long __und_invalid @ 2 (IRQ_26 / IRQ_32)
++ .long __und_svc @ 3 (SVC_26 / SVC_32)
++ .long __und_invalid @ 4
++ .long __und_invalid @ 5
++ .long __und_invalid @ 6
++ .long __und_invalid @ 7
++ .long __und_invalid @ 8
++ .long __und_invalid @ 9
++ .long __und_invalid @ a
++ .long __und_invalid @ b
++ .long __und_invalid @ c
++ .long __und_invalid @ d
++ .long __und_invalid @ e
++ .long __und_invalid @ f
++
++ .align 5
++
++/*=============================================================================
++ * Undefined FIQs
++ *-----------------------------------------------------------------------------
++ * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC
++ * MUST PRESERVE SVC SPSR, but need to switch to SVC mode to show our msg.
++ * Basically to switch modes, we *HAVE* to clobber one register... brain
++ * damage alert! I don't think that we can execute any code in here in any
++ * other mode than FIQ... Ok you can switch to another mode, but you can't
++ * get out of that mode without clobbering one register.
++ */
++vector_fiq:
++ disable_fiq
++ subs pc, lr, #4
++
++/*=============================================================================
++ * Address exception handler
++ *-----------------------------------------------------------------------------
++ * These aren't too critical.
++ * (they're not supposed to happen, and won't happen in 32-bit data mode).
++ */
++
++vector_addrexcptn:
++ b vector_addrexcptn
++
++/*
++ * We group all the following data together to optimise
++ * for CPUs with separate I & D caches.
++ */
++ .align 5
++
++.LCvswi:
++ .word vector_swi
++
++ .globl __stubs_end
++__stubs_end:
++
++ .equ stubs_offset, __vectors_start + 0x200 - __stubs_start
++
++ .globl __vectors_start
++__vectors_start:
++ ARM( swi SYS_ERROR0 )
++ THUMB( svc #0 )
++ THUMB( nop )
++ W(b) vector_und + stubs_offset
++ W(ldr) pc, .LCvswi + stubs_offset
++ W(b) vector_pabt + stubs_offset
++ W(b) vector_dabt + stubs_offset
++ W(b) vector_addrexcptn + stubs_offset
++ W(b) vector_irq + stubs_offset
++ W(b) vector_fiq + stubs_offset
++
++ .globl __vectors_end
++__vectors_end:
++
++ .data
++
++ .globl cr_alignment
++ .globl cr_no_alignment
++cr_alignment:
++ .space 4
++cr_no_alignment:
++ .space 4
+diff -rupN linux-2.6.35.11/arch/arm/kernel/head-common.S linux-2.6.35.11-ts7500/arch/arm/kernel/head-common.S
+--- linux-2.6.35.11/arch/arm/kernel/head-common.S 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/kernel/head-common.S 2011-03-14 11:18:24.000000000 -0400
+@@ -39,6 +39,16 @@ __switch_data:
+ * r9 = processor ID
+ */
+ __mmap_switched:
++
++# We come here right after the MMU is enabled
++
++#ifdef CONFIG_DEBUG_LL
++@ stmfd sp!, {r0, r1, r2, r3, r9, lr}
++@ adr r0, str_mmap_switched
++@ bl printascii
++@ ldmfd sp!, {r0, r1, r2, r3, r9, lr}
++#endif
++
+ adr r3, __switch_data + 4
+
+ ldmia r3!, {r4, r5, r6, r7}
+@@ -53,6 +63,7 @@ __mmap_switched:
+ strcc fp, [r6],#4
+ bcc 1b
+
++
+ ARM( ldmia r3, {r4, r5, r6, r7, sp})
+ THUMB( ldmia r3, {r4, r5, r6, r7} )
+ THUMB( ldr sp, [r3, #16] )
+@@ -61,7 +72,23 @@ __mmap_switched:
+ str r2, [r6] @ Save atags pointer
+ bic r4, r0, #CR_A @ Clear 'A' bit
+ stmia r7, {r0, r4} @ Save control register values
++
++#ifdef CONFIG_DEBUG_LL
++ stmfd sp!, {r0, r1, r2, r3, r9, lr}
++ adr r0, str_mmap_switched_done
++ bl printascii
++ ldmfd sp!, {r0, r1, r2, r3, r9, lr}
++#endif
++
++
+ b start_kernel
++
++#ifdef CONFIG_DEBUG_LL
++str_mmap_switched: .asciz "str_mmap_switched\n"
++str_mmap_switched_done: .asciz "str_mmap_switched_done\n"
++.align 4
++#endif
++
+ ENDPROC(__mmap_switched)
+
+ /*
+@@ -74,7 +101,7 @@ ENDPROC(__mmap_switched)
+ * machine ID for example).
+ */
+ __error_p:
+-#ifdef CONFIG_DEBUG_LL
++#ifdef CONFIG_DEBUG_LL
+ adr r0, str_p1
+ bl printascii
+ mov r0, r9
+diff -rupN linux-2.6.35.11/arch/arm/kernel/head.S linux-2.6.35.11-ts7500/arch/arm/kernel/head.S
+--- linux-2.6.35.11/arch/arm/kernel/head.S 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/kernel/head.S 2011-03-14 11:18:24.000000000 -0400
+@@ -22,6 +22,10 @@
+ #include <asm/thread_info.h>
+ #include <asm/system.h>
+
++#if defined(CONFIG_ARCH_STR9100) || defined(CONFIG_ARCH_STR8100)
++//#define PROCINFO_INITFUNC 12
++#endif
++
+ #if (PHYS_OFFSET & 0x001fffff)
+ #error "PHYS_OFFSET must be at an even 2MiB boundary!"
+ #endif
+@@ -78,16 +82,75 @@
+ ENTRY(stext)
+ setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
+ @ and irqs disabled
++
++
++#ifdef CONFIG_DEBUG_LL
++ stmfd sp!, {r0, r1, r2}
++ mov r6, r1
++ adr r0, str_kernel_start
++ bl printascii
++ adr r0, str_machine_id
++ bl printascii
++ mov r0, r6
++ bl printhex8
++ mov r0, #'\n'
++ bl printch
++ ldmfd sp!, {r0, r1, r2}
++#endif
++
+ mrc p15, 0, r9, c0, c0 @ get processor id
++
++#ifdef CONFIG_DEBUG_LL
++ stmfd sp!, {r0, r1, r2}
++ adr r0, str_processor_id
++ bl printascii
++ mov r0, r9
++ bl printhex8
++ mov r0, #'\n'
++ bl printch
++ ldmfd sp!, {r0, r1, r2}
++#endif
++
+ bl __lookup_processor_type @ r5=procinfo r9=cpuid
+ movs r10, r5 @ invalid processor (r5=0)?
+ beq __error_p @ yes, error 'p'
+ bl __lookup_machine_type @ r5=machinfo
+ movs r8, r5 @ invalid machine (r5=0)?
+- beq __error_a @ yes, error 'a'
++ beq __error_a @ yes, error 'a'
+ bl __vet_atags
+ bl __create_page_tables
+
++
++###########################
++
++ mov ip, #0
++ mcr p15, 0, ip, c7,c14, 2 @ clean/flush D-cache
++ mcr p15, 0, ip, c7, c10, 4 @ drain write buffer
++ mcr p15, 0, ip, c7, c5, 6 @ invalidate BTB
++ nop
++ nop
++ nop
++ nop
++
++#################################
++
++#ifdef CONFIG_DEBUG_LL
++ stmfd sp!, {r0, r1, r2}
++ adr r0, str_procinfo_at
++ bl printascii
++ mov r0, r10
++ bl printhex8
++ mov r0, #'\n'
++ bl printch
++ adr r0, str_initfunc_offset
++ bl printascii
++ mov r0, #PROCINFO_INITFUNC
++ bl printhex8
++ mov r0, #'\n'
++ bl printch
++ ldmfd sp!, {r0, r1, r2}
++#endif
++
+ /*
+ * The following calls CPU specific code in a position independent
+ * manner. See arch/arm/mm/proc-*.S for details. r10 = base of
+@@ -101,6 +164,15 @@ ENTRY(stext)
+ ARM( add pc, r10, #PROCINFO_INITFUNC )
+ THUMB( add r12, r10, #PROCINFO_INITFUNC )
+ THUMB( mov pc, r12 )
++
++#ifdef CONFIG_DEBUG_LL
++str_kernel_start: .asciz "kernel_start\n"
++str_machine_id: .asciz "machine ID: 0x"
++str_processor_id: .asciz "processor ID: 0x"
++str_procinfo_at: .asciz "procinfo at: 0x"
++str_initfunc_offset: .asciz "PROCINFO_INITFUNC: 0x"
++.align 4
++#endif
+ ENDPROC(stext)
+
+ #if defined(CONFIG_SMP)
+@@ -158,6 +230,13 @@ __secondary_data:
+ * registers.
+ */
+ __enable_mmu:
++#ifdef CONFIG_DEBUG_LL
++@ stmfd sp!, {r0, r1, r2, r3, r6, r13, lr}
++@ adr r0, str_enable_mmu
++@ bl printascii
++@ ldmfd sp!, {r0, r1, r2, r3, r6, r13, lr}
++#endif
++
+ #ifdef CONFIG_ALIGNMENT_TRAP
+ orr r0, r0, #CR_A
+ #else
+@@ -179,6 +258,12 @@ __enable_mmu:
+ mcr p15, 0, r5, c3, c0, 0 @ load domain access register
+ mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
+ b __turn_mmu_on
++
++#ifdef CONFIG_DEBUG_LL
++str_enable_mmu: .asciz "__enable_mmu\n"
++str_enable_mmu_done: .asciz "__enable_mmu done\n"
++.align 4
++#endif
+ ENDPROC(__enable_mmu)
+
+ /*
+@@ -196,10 +281,19 @@ ENDPROC(__enable_mmu)
+ __turn_mmu_on:
+ mov r0, r0
+ mcr p15, 0, r0, c1, c0, 0 @ write control reg
++#if defined(CONFIG_CPU_FA520) || defined(CONFIG_CPU_FA526) || defined(CONFIG_CPU_FA626)
++ nop
++ nop
++ nop
++ nop
++#endif
+ mrc p15, 0, r3, c0, c0, 0 @ read id reg
++
+ mov r3, r3
+- mov r3, r13
++ mov r3, r3
++ mov r3, r13
+ mov pc, r3
++
+ ENDPROC(__turn_mmu_on)
+
+
+@@ -217,6 +311,12 @@ ENDPROC(__turn_mmu_on)
+ * r4 = physical page table address
+ */
+ __create_page_tables:
++#ifdef CONFIG_DEBUG_LL
++ mov r6, lr
++ adr r0, str_create_page_tables
++ bl printascii
++ mov lr, r6
++#endif
+ pgtbl r4 @ page table address
+
+ /*
+@@ -281,14 +381,15 @@ __create_page_tables:
+ /*
+ * Then map first 1MB of ram in case it contains our boot params.
+ */
+- add r0, r4, #PAGE_OFFSET >> 18
++ add r0, r4, #PAGE_OFFSET >> 18
+ orr r6, r7, #(PHYS_OFFSET & 0xff000000)
+ .if (PHYS_OFFSET & 0x00f00000)
+ orr r6, r6, #(PHYS_OFFSET & 0x00f00000)
+ .endif
+ str r6, [r0]
+
+-#ifdef CONFIG_DEBUG_LL
++@#if defined(CONFIG_DEBUG_LL) || defined(CONFIG_ARCH_STR9100) || defined(CONFIG_ARCH_STR8100)
++#if defined(CONFIG_DEBUG_LL)
+ ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
+ /*
+ * Map in IO space for serial debugging.
+@@ -329,7 +430,20 @@ __create_page_tables:
+ str r3, [r0]
+ #endif
+ #endif
++
++#ifdef CONFIG_DEBUG_LL
++ mov r6, lr
++ adr r0, str_create_page_tables_done
++ bl printascii
++ mov lr, r6
++#endif
++
+ mov pc, lr
++#ifdef CONFIG_DEBUG_LL
++str_create_page_tables: .asciz "create_page_tables\n"
++str_create_page_tables_done: .asciz "create_page_tables_done\n"
++.align 4
++#endif
+ ENDPROC(__create_page_tables)
+ .ltorg
+
+diff -rupN linux-2.6.35.11/arch/arm/kernel/process.c linux-2.6.35.11-ts7500/arch/arm/kernel/process.c
+--- linux-2.6.35.11/arch/arm/kernel/process.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/kernel/process.c 2011-03-14 11:18:24.000000000 -0400
+@@ -126,9 +126,17 @@ EXPORT_SYMBOL_GPL(arm_pm_restart);
+ */
+ static void default_idle(void)
+ {
++#ifndef CONFIG_CPU_FA_IDLE
++ local_irq_disable();
++#endif
++
+ if (!need_resched())
+ arch_idle();
+- local_irq_enable();
++// local_irq_enable();
++#ifndef CONFIG_CPU_FA_IDLE
++ local_irq_enable();
++#endif
++
+ }
+
+ void (*pm_idle)(void) = default_idle;
+diff -rupN linux-2.6.35.11/arch/arm/kernel/process.c.orig linux-2.6.35.11-ts7500/arch/arm/kernel/process.c.orig
+--- linux-2.6.35.11/arch/arm/kernel/process.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/kernel/process.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,428 @@
++/*
++ * linux/arch/arm/kernel/process.c
++ *
++ * Copyright (C) 1996-2000 Russell King - Converted to ARM.
++ * Original Copyright (C) 1995 Linus Torvalds
++ *
++ * 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.
++ */
++#include <stdarg.h>
++
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/stddef.h>
++#include <linux/unistd.h>
++#include <linux/user.h>
++#include <linux/delay.h>
++#include <linux/reboot.h>
++#include <linux/interrupt.h>
++#include <linux/kallsyms.h>
++#include <linux/init.h>
++#include <linux/cpu.h>
++#include <linux/elfcore.h>
++#include <linux/pm.h>
++#include <linux/tick.h>
++#include <linux/utsname.h>
++#include <linux/uaccess.h>
++
++#include <asm/leds.h>
++#include <asm/processor.h>
++#include <asm/system.h>
++#include <asm/thread_notify.h>
++#include <asm/stacktrace.h>
++#include <asm/mach/time.h>
++
++static const char *processor_modes[] = {
++ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
++ "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26",
++ "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" ,
++ "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
++};
++
++static const char *isa_modes[] = {
++ "ARM" , "Thumb" , "Jazelle", "ThumbEE"
++};
++
++extern void setup_mm_for_reboot(char mode);
++
++static volatile int hlt_counter;
++
++#include <mach/system.h>
++
++void disable_hlt(void)
++{
++ hlt_counter++;
++}
++
++EXPORT_SYMBOL(disable_hlt);
++
++void enable_hlt(void)
++{
++ hlt_counter--;
++}
++
++EXPORT_SYMBOL(enable_hlt);
++
++static int __init nohlt_setup(char *__unused)
++{
++ hlt_counter = 1;
++ return 1;
++}
++
++static int __init hlt_setup(char *__unused)
++{
++ hlt_counter = 0;
++ return 1;
++}
++
++__setup("nohlt", nohlt_setup);
++__setup("hlt", hlt_setup);
++
++void arm_machine_restart(char mode, const char *cmd)
++{
++ /*
++ * Clean and disable cache, and turn off interrupts
++ */
++ cpu_proc_fin();
++
++ /*
++ * Tell the mm system that we are going to reboot -
++ * we may need it to insert some 1:1 mappings so that
++ * soft boot works.
++ */
++ setup_mm_for_reboot(mode);
++
++ /*
++ * Now call the architecture specific reboot code.
++ */
++ arch_reset(mode, cmd);
++
++ /*
++ * Whoops - the architecture was unable to reboot.
++ * Tell the user!
++ */
++ mdelay(1000);
++ printk("Reboot failed -- System halted\n");
++ while (1);
++}
++
++/*
++ * Function pointers to optional machine specific functions
++ */
++void (*pm_power_off)(void);
++EXPORT_SYMBOL(pm_power_off);
++
++void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart;
++EXPORT_SYMBOL_GPL(arm_pm_restart);
++
++
++/*
++ * This is our default idle handler. We need to disable
++ * interrupts here to ensure we don't miss a wakeup call.
++ */
++static void default_idle(void)
++{
++ if (!need_resched())
++ arch_idle();
++ local_irq_enable();
++}
++
++void (*pm_idle)(void) = default_idle;
++EXPORT_SYMBOL(pm_idle);
++
++/*
++ * The idle thread, has rather strange semantics for calling pm_idle,
++ * but this is what x86 does and we need to do the same, so that
++ * things like cpuidle get called in the same way. The only difference
++ * is that we always respect 'hlt_counter' to prevent low power idle.
++ */
++void cpu_idle(void)
++{
++ local_fiq_enable();
++
++ /* endless idle loop with no priority at all */
++ while (1) {
++ tick_nohz_stop_sched_tick(1);
++ leds_event(led_idle_start);
++ while (!need_resched()) {
++#ifdef CONFIG_HOTPLUG_CPU
++ if (cpu_is_offline(smp_processor_id()))
++ cpu_die();
++#endif
++
++ local_irq_disable();
++ if (hlt_counter) {
++ local_irq_enable();
++ cpu_relax();
++ } else {
++ stop_critical_timings();
++ pm_idle();
++ start_critical_timings();
++ /*
++ * This will eventually be removed - pm_idle
++ * functions should always return with IRQs
++ * enabled.
++ */
++ WARN_ON(irqs_disabled());
++ local_irq_enable();
++ }
++ }
++ leds_event(led_idle_end);
++ tick_nohz_restart_sched_tick();
++ preempt_enable_no_resched();
++ schedule();
++ preempt_disable();
++ }
++}
++
++static char reboot_mode = 'h';
++
++int __init reboot_setup(char *str)
++{
++ reboot_mode = str[0];
++ return 1;
++}
++
++__setup("reboot=", reboot_setup);
++
++void machine_halt(void)
++{
++}
++
++
++void machine_power_off(void)
++{
++ if (pm_power_off)
++ pm_power_off();
++}
++
++void machine_restart(char *cmd)
++{
++ arm_pm_restart(reboot_mode, cmd);
++}
++
++void __show_regs(struct pt_regs *regs)
++{
++ unsigned long flags;
++ char buf[64];
++
++ printk("CPU: %d %s (%s %.*s)\n",
++ raw_smp_processor_id(), print_tainted(),
++ init_utsname()->release,
++ (int)strcspn(init_utsname()->version, " "),
++ init_utsname()->version);
++ print_symbol("PC is at %s\n", instruction_pointer(regs));
++ print_symbol("LR is at %s\n", regs->ARM_lr);
++ printk("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n"
++ "sp : %08lx ip : %08lx fp : %08lx\n",
++ regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr,
++ regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
++ printk("r10: %08lx r9 : %08lx r8 : %08lx\n",
++ regs->ARM_r10, regs->ARM_r9,
++ regs->ARM_r8);
++ printk("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n",
++ regs->ARM_r7, regs->ARM_r6,
++ regs->ARM_r5, regs->ARM_r4);
++ printk("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
++ regs->ARM_r3, regs->ARM_r2,
++ regs->ARM_r1, regs->ARM_r0);
++
++ flags = regs->ARM_cpsr;
++ buf[0] = flags & PSR_N_BIT ? 'N' : 'n';
++ buf[1] = flags & PSR_Z_BIT ? 'Z' : 'z';
++ buf[2] = flags & PSR_C_BIT ? 'C' : 'c';
++ buf[3] = flags & PSR_V_BIT ? 'V' : 'v';
++ buf[4] = '\0';
++
++ printk("Flags: %s IRQs o%s FIQs o%s Mode %s ISA %s Segment %s\n",
++ buf, interrupts_enabled(regs) ? "n" : "ff",
++ fast_interrupts_enabled(regs) ? "n" : "ff",
++ processor_modes[processor_mode(regs)],
++ isa_modes[isa_mode(regs)],
++ get_fs() == get_ds() ? "kernel" : "user");
++#ifdef CONFIG_CPU_CP15
++ {
++ unsigned int ctrl;
++
++ buf[0] = '\0';
++#ifdef CONFIG_CPU_CP15_MMU
++ {
++ unsigned int transbase, dac;
++ asm("mrc p15, 0, %0, c2, c0\n\t"
++ "mrc p15, 0, %1, c3, c0\n"
++ : "=r" (transbase), "=r" (dac));
++ snprintf(buf, sizeof(buf), " Table: %08x DAC: %08x",
++ transbase, dac);
++ }
++#endif
++ asm("mrc p15, 0, %0, c1, c0\n" : "=r" (ctrl));
++
++ printk("Control: %08x%s\n", ctrl, buf);
++ }
++#endif
++}
++
++void show_regs(struct pt_regs * regs)
++{
++ printk("\n");
++ printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm);
++ __show_regs(regs);
++ __backtrace();
++}
++
++ATOMIC_NOTIFIER_HEAD(thread_notify_head);
++
++EXPORT_SYMBOL_GPL(thread_notify_head);
++
++/*
++ * Free current thread data structures etc..
++ */
++void exit_thread(void)
++{
++ thread_notify(THREAD_NOTIFY_EXIT, current_thread_info());
++}
++
++void flush_thread(void)
++{
++ struct thread_info *thread = current_thread_info();
++ struct task_struct *tsk = current;
++
++ memset(thread->used_cp, 0, sizeof(thread->used_cp));
++ memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
++ memset(&thread->fpstate, 0, sizeof(union fp_state));
++
++ thread_notify(THREAD_NOTIFY_FLUSH, thread);
++}
++
++void release_thread(struct task_struct *dead_task)
++{
++}
++
++asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
++
++int
++copy_thread(unsigned long clone_flags, unsigned long stack_start,
++ unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs)
++{
++ struct thread_info *thread = task_thread_info(p);
++ struct pt_regs *childregs = task_pt_regs(p);
++
++ *childregs = *regs;
++ childregs->ARM_r0 = 0;
++ childregs->ARM_sp = stack_start;
++
++ memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
++ thread->cpu_context.sp = (unsigned long)childregs;
++ thread->cpu_context.pc = (unsigned long)ret_from_fork;
++
++ if (clone_flags & CLONE_SETTLS)
++ thread->tp_value = regs->ARM_r3;
++
++ return 0;
++}
++
++/*
++ * Fill in the task's elfregs structure for a core dump.
++ */
++int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs)
++{
++ elf_core_copy_regs(elfregs, task_pt_regs(t));
++ return 1;
++}
++
++/*
++ * fill in the fpe structure for a core dump...
++ */
++int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
++{
++ struct thread_info *thread = current_thread_info();
++ int used_math = thread->used_cp[1] | thread->used_cp[2];
++
++ if (used_math)
++ memcpy(fp, &thread->fpstate.soft, sizeof (*fp));
++
++ return used_math != 0;
++}
++EXPORT_SYMBOL(dump_fpu);
++
++/*
++ * Shuffle the argument into the correct register before calling the
++ * thread function. r4 is the thread argument, r5 is the pointer to
++ * the thread function, and r6 points to the exit function.
++ */
++extern void kernel_thread_helper(void);
++asm( ".pushsection .text\n"
++" .align\n"
++" .type kernel_thread_helper, #function\n"
++"kernel_thread_helper:\n"
++#ifdef CONFIG_TRACE_IRQFLAGS
++" bl trace_hardirqs_on\n"
++#endif
++" msr cpsr_c, r7\n"
++" mov r0, r4\n"
++" mov lr, r6\n"
++" mov pc, r5\n"
++" .size kernel_thread_helper, . - kernel_thread_helper\n"
++" .popsection");
++
++#ifdef CONFIG_ARM_UNWIND
++extern void kernel_thread_exit(long code);
++asm( ".pushsection .text\n"
++" .align\n"
++" .type kernel_thread_exit, #function\n"
++"kernel_thread_exit:\n"
++" .fnstart\n"
++" .cantunwind\n"
++" bl do_exit\n"
++" nop\n"
++" .fnend\n"
++" .size kernel_thread_exit, . - kernel_thread_exit\n"
++" .popsection");
++#else
++#define kernel_thread_exit do_exit
++#endif
++
++/*
++ * Create a kernel thread.
++ */
++pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
++{
++ struct pt_regs regs;
++
++ memset(®s, 0, sizeof(regs));
++
++ regs.ARM_r4 = (unsigned long)arg;
++ regs.ARM_r5 = (unsigned long)fn;
++ regs.ARM_r6 = (unsigned long)kernel_thread_exit;
++ regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE;
++ regs.ARM_pc = (unsigned long)kernel_thread_helper;
++ regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT;
++
++ return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
++}
++EXPORT_SYMBOL(kernel_thread);
++
++unsigned long get_wchan(struct task_struct *p)
++{
++ struct stackframe frame;
++ int count = 0;
++ if (!p || p == current || p->state == TASK_RUNNING)
++ return 0;
++
++ frame.fp = thread_saved_fp(p);
++ frame.sp = thread_saved_sp(p);
++ frame.lr = 0; /* recovered from the stack */
++ frame.pc = thread_saved_pc(p);
++ do {
++ int ret = unwind_frame(&frame);
++ if (ret < 0)
++ return 0;
++ if (!in_sched_functions(frame.pc))
++ return frame.pc;
++ } while (count ++ < 16);
++ return 0;
++}
+diff -rupN linux-2.6.35.11/arch/arm/kernel/setup.c linux-2.6.35.11-ts7500/arch/arm/kernel/setup.c
+--- linux-2.6.35.11/arch/arm/kernel/setup.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/kernel/setup.c 2011-03-14 11:18:24.000000000 -0400
+@@ -370,6 +370,7 @@ static struct machine_desc * __init setu
+ {
+ struct machine_desc *list;
+
++ //printk("setup_machine()\n");
+ /*
+ * locate machine in the list of supported machines.
+ */
+@@ -656,6 +657,7 @@ static void (*init_machine)(void) __init
+
+ static int __init customize_machine(void)
+ {
++ printk("customize_machine(), calling init_machine()\n");
+ /* customizes platform devices, or adds new ones */
+ if (init_machine)
+ init_machine();
+@@ -667,8 +669,10 @@ void __init setup_arch(char **cmdline_p)
+ {
+ struct tag *tags = (struct tag *)&init_tags;
+ struct machine_desc *mdesc;
+- char *from = default_command_line;
++ char *from = default_command_line;
+
++ //printk("setup_arch()\n");
++
+ unwind_init();
+
+ setup_processor();
+@@ -726,6 +730,22 @@ void __init setup_arch(char **cmdline_p)
+ cpu_init();
+ tcm_init();
+
++#ifdef CONFIG_ARCH_STR9100
++ {
++ extern void __init str9100_early_init(void);
++
++ str9100_early_init();
++ }
++#endif
++
++#ifdef CONFIG_ARCH_STR8100
++ {
++ extern void __init str8100_early_init(void);
++
++ str8100_early_init();
++ }
++#endif
++
+ /*
+ * Set up various architecture-specific pointers
+ */
+@@ -760,9 +780,11 @@ subsys_initcall(topology_init);
+
+ #ifdef CONFIG_HAVE_PROC_CPU
+ static int __init proc_cpu_init(void)
+-{
++{
+ struct proc_dir_entry *res;
+
++ printk("proc_cpu_init()\n");
++
+ res = proc_mkdir("cpu", NULL);
+ if (!res)
+ return -ENOMEM;
+diff -rupN linux-2.6.35.11/arch/arm/kernel/setup.c.orig linux-2.6.35.11-ts7500/arch/arm/kernel/setup.c.orig
+--- linux-2.6.35.11/arch/arm/kernel/setup.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/kernel/setup.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,876 @@
++/*
++ * linux/arch/arm/kernel/setup.c
++ *
++ * Copyright (C) 1995-2001 Russell King
++ *
++ * 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.
++ */
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/stddef.h>
++#include <linux/ioport.h>
++#include <linux/delay.h>
++#include <linux/utsname.h>
++#include <linux/initrd.h>
++#include <linux/console.h>
++#include <linux/bootmem.h>
++#include <linux/seq_file.h>
++#include <linux/screen_info.h>
++#include <linux/init.h>
++#include <linux/root_dev.h>
++#include <linux/cpu.h>
++#include <linux/interrupt.h>
++#include <linux/smp.h>
++#include <linux/fs.h>
++#include <linux/proc_fs.h>
++
++#include <asm/unified.h>
++#include <asm/cpu.h>
++#include <asm/cputype.h>
++#include <asm/elf.h>
++#include <asm/procinfo.h>
++#include <asm/sections.h>
++#include <asm/setup.h>
++#include <asm/mach-types.h>
++#include <asm/cacheflush.h>
++#include <asm/cachetype.h>
++#include <asm/tlbflush.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/irq.h>
++#include <asm/mach/time.h>
++#include <asm/traps.h>
++#include <asm/unwind.h>
++
++#include "compat.h"
++#include "atags.h"
++#include "tcm.h"
++
++#ifndef MEM_SIZE
++#define MEM_SIZE (16*1024*1024)
++#endif
++
++#if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
++char fpe_type[8];
++
++static int __init fpe_setup(char *line)
++{
++ memcpy(fpe_type, line, 8);
++ return 1;
++}
++
++__setup("fpe=", fpe_setup);
++#endif
++
++extern void paging_init(struct machine_desc *desc);
++extern void reboot_setup(char *str);
++
++unsigned int processor_id;
++EXPORT_SYMBOL(processor_id);
++unsigned int __machine_arch_type;
++EXPORT_SYMBOL(__machine_arch_type);
++unsigned int cacheid;
++EXPORT_SYMBOL(cacheid);
++
++unsigned int __atags_pointer __initdata;
++
++unsigned int system_rev;
++EXPORT_SYMBOL(system_rev);
++
++unsigned int system_serial_low;
++EXPORT_SYMBOL(system_serial_low);
++
++unsigned int system_serial_high;
++EXPORT_SYMBOL(system_serial_high);
++
++unsigned int elf_hwcap;
++EXPORT_SYMBOL(elf_hwcap);
++
++
++#ifdef MULTI_CPU
++struct processor processor;
++#endif
++#ifdef MULTI_TLB
++struct cpu_tlb_fns cpu_tlb;
++#endif
++#ifdef MULTI_USER
++struct cpu_user_fns cpu_user;
++#endif
++#ifdef MULTI_CACHE
++struct cpu_cache_fns cpu_cache;
++#endif
++#ifdef CONFIG_OUTER_CACHE
++struct outer_cache_fns outer_cache;
++EXPORT_SYMBOL(outer_cache);
++#endif
++
++struct stack {
++ u32 irq[3];
++ u32 abt[3];
++ u32 und[3];
++} ____cacheline_aligned;
++
++static struct stack stacks[NR_CPUS];
++
++char elf_platform[ELF_PLATFORM_SIZE];
++EXPORT_SYMBOL(elf_platform);
++
++static const char *cpu_name;
++static const char *machine_name;
++static char __initdata cmd_line[COMMAND_LINE_SIZE];
++
++static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
++static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
++#define ENDIANNESS ((char)endian_test.l)
++
++DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data);
++
++/*
++ * Standard memory resources
++ */
++static struct resource mem_res[] = {
++ {
++ .name = "Video RAM",
++ .start = 0,
++ .end = 0,
++ .flags = IORESOURCE_MEM
++ },
++ {
++ .name = "Kernel text",
++ .start = 0,
++ .end = 0,
++ .flags = IORESOURCE_MEM
++ },
++ {
++ .name = "Kernel data",
++ .start = 0,
++ .end = 0,
++ .flags = IORESOURCE_MEM
++ }
++};
++
++#define video_ram mem_res[0]
++#define kernel_code mem_res[1]
++#define kernel_data mem_res[2]
++
++static struct resource io_res[] = {
++ {
++ .name = "reserved",
++ .start = 0x3bc,
++ .end = 0x3be,
++ .flags = IORESOURCE_IO | IORESOURCE_BUSY
++ },
++ {
++ .name = "reserved",
++ .start = 0x378,
++ .end = 0x37f,
++ .flags = IORESOURCE_IO | IORESOURCE_BUSY
++ },
++ {
++ .name = "reserved",
++ .start = 0x278,
++ .end = 0x27f,
++ .flags = IORESOURCE_IO | IORESOURCE_BUSY
++ }
++};
++
++#define lp0 io_res[0]
++#define lp1 io_res[1]
++#define lp2 io_res[2]
++
++static const char *proc_arch[] = {
++ "undefined/unknown",
++ "3",
++ "4",
++ "4T",
++ "5",
++ "5T",
++ "5TE",
++ "5TEJ",
++ "6TEJ",
++ "7",
++ "?(11)",
++ "?(12)",
++ "?(13)",
++ "?(14)",
++ "?(15)",
++ "?(16)",
++ "?(17)",
++};
++
++int cpu_architecture(void)
++{
++ int cpu_arch;
++
++ if ((read_cpuid_id() & 0x0008f000) == 0) {
++ cpu_arch = CPU_ARCH_UNKNOWN;
++ } else if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
++ cpu_arch = (read_cpuid_id() & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
++ } else if ((read_cpuid_id() & 0x00080000) == 0x00000000) {
++ cpu_arch = (read_cpuid_id() >> 16) & 7;
++ if (cpu_arch)
++ cpu_arch += CPU_ARCH_ARMv3;
++ } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
++ unsigned int mmfr0;
++
++ /* Revised CPUID format. Read the Memory Model Feature
++ * Register 0 and check for VMSAv7 or PMSAv7 */
++ asm("mrc p15, 0, %0, c0, c1, 4"
++ : "=r" (mmfr0));
++ if ((mmfr0 & 0x0000000f) == 0x00000003 ||
++ (mmfr0 & 0x000000f0) == 0x00000030)
++ cpu_arch = CPU_ARCH_ARMv7;
++ else if ((mmfr0 & 0x0000000f) == 0x00000002 ||
++ (mmfr0 & 0x000000f0) == 0x00000020)
++ cpu_arch = CPU_ARCH_ARMv6;
++ else
++ cpu_arch = CPU_ARCH_UNKNOWN;
++ } else
++ cpu_arch = CPU_ARCH_UNKNOWN;
++
++ return cpu_arch;
++}
++
++static void __init cacheid_init(void)
++{
++ unsigned int cachetype = read_cpuid_cachetype();
++ unsigned int arch = cpu_architecture();
++
++ if (arch >= CPU_ARCH_ARMv6) {
++ if ((cachetype & (7 << 29)) == 4 << 29) {
++ /* ARMv7 register format */
++ cacheid = CACHEID_VIPT_NONALIASING;
++ if ((cachetype & (3 << 14)) == 1 << 14)
++ cacheid |= CACHEID_ASID_TAGGED;
++ } else if (cachetype & (1 << 23))
++ cacheid = CACHEID_VIPT_ALIASING;
++ else
++ cacheid = CACHEID_VIPT_NONALIASING;
++ } else {
++ cacheid = CACHEID_VIVT;
++ }
++
++ printk("CPU: %s data cache, %s instruction cache\n",
++ cache_is_vivt() ? "VIVT" :
++ cache_is_vipt_aliasing() ? "VIPT aliasing" :
++ cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
++ cache_is_vivt() ? "VIVT" :
++ icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
++ cache_is_vipt_aliasing() ? "VIPT aliasing" :
++ cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
++}
++
++/*
++ * These functions re-use the assembly code in head.S, which
++ * already provide the required functionality.
++ */
++extern struct proc_info_list *lookup_processor_type(unsigned int);
++extern struct machine_desc *lookup_machine_type(unsigned int);
++
++static void __init setup_processor(void)
++{
++ struct proc_info_list *list;
++
++ /*
++ * locate processor in the list of supported processor
++ * types. The linker builds this table for us from the
++ * entries in arch/arm/mm/proc-*.S
++ */
++ list = lookup_processor_type(read_cpuid_id());
++ if (!list) {
++ printk("CPU configuration botched (ID %08x), unable "
++ "to continue.\n", read_cpuid_id());
++ while (1);
++ }
++
++ cpu_name = list->cpu_name;
++
++#ifdef MULTI_CPU
++ processor = *list->proc;
++#endif
++#ifdef MULTI_TLB
++ cpu_tlb = *list->tlb;
++#endif
++#ifdef MULTI_USER
++ cpu_user = *list->user;
++#endif
++#ifdef MULTI_CACHE
++ cpu_cache = *list->cache;
++#endif
++
++ printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
++ cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
++ proc_arch[cpu_architecture()], cr_alignment);
++
++ sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
++ sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
++ elf_hwcap = list->elf_hwcap;
++#ifndef CONFIG_ARM_THUMB
++ elf_hwcap &= ~HWCAP_THUMB;
++#endif
++
++ cacheid_init();
++ cpu_proc_init();
++}
++
++/*
++ * cpu_init - initialise one CPU.
++ *
++ * cpu_init sets up the per-CPU stacks.
++ */
++void cpu_init(void)
++{
++ unsigned int cpu = smp_processor_id();
++ struct stack *stk = &stacks[cpu];
++
++ if (cpu >= NR_CPUS) {
++ printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
++ BUG();
++ }
++
++ /*
++ * Define the placement constraint for the inline asm directive below.
++ * In Thumb-2, msr with an immediate value is not allowed.
++ */
++#ifdef CONFIG_THUMB2_KERNEL
++#define PLC "r"
++#else
++#define PLC "I"
++#endif
++
++ /*
++ * setup stacks for re-entrant exception handlers
++ */
++ __asm__ (
++ "msr cpsr_c, %1\n\t"
++ "add r14, %0, %2\n\t"
++ "mov sp, r14\n\t"
++ "msr cpsr_c, %3\n\t"
++ "add r14, %0, %4\n\t"
++ "mov sp, r14\n\t"
++ "msr cpsr_c, %5\n\t"
++ "add r14, %0, %6\n\t"
++ "mov sp, r14\n\t"
++ "msr cpsr_c, %7"
++ :
++ : "r" (stk),
++ PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
++ "I" (offsetof(struct stack, irq[0])),
++ PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
++ "I" (offsetof(struct stack, abt[0])),
++ PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE),
++ "I" (offsetof(struct stack, und[0])),
++ PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
++ : "r14");
++}
++
++static struct machine_desc * __init setup_machine(unsigned int nr)
++{
++ struct machine_desc *list;
++
++ /*
++ * locate machine in the list of supported machines.
++ */
++ list = lookup_machine_type(nr);
++ if (!list) {
++ printk("Machine configuration botched (nr %d), unable "
++ "to continue.\n", nr);
++ while (1);
++ }
++
++ printk("Machine: %s\n", list->name);
++
++ return list;
++}
++
++static int __init arm_add_memory(unsigned long start, unsigned long size)
++{
++ struct membank *bank = &meminfo.bank[meminfo.nr_banks];
++
++ if (meminfo.nr_banks >= NR_BANKS) {
++ printk(KERN_CRIT "NR_BANKS too low, "
++ "ignoring memory at %#lx\n", start);
++ return -EINVAL;
++ }
++
++ /*
++ * Ensure that start/size are aligned to a page boundary.
++ * Size is appropriately rounded down, start is rounded up.
++ */
++ size -= start & ~PAGE_MASK;
++ bank->start = PAGE_ALIGN(start);
++ bank->size = size & PAGE_MASK;
++ bank->node = PHYS_TO_NID(start);
++
++ /*
++ * Check whether this memory region has non-zero size or
++ * invalid node number.
++ */
++ if (bank->size == 0 || bank->node >= MAX_NUMNODES)
++ return -EINVAL;
++
++ meminfo.nr_banks++;
++ return 0;
++}
++
++/*
++ * Pick out the memory size. We look for mem=size at start,
++ * where start and size are "size[KkMm]"
++ */
++static int __init early_mem(char *p)
++{
++ static int usermem __initdata = 0;
++ unsigned long size, start;
++ char *endp;
++
++ /*
++ * If the user specifies memory size, we
++ * blow away any automatically generated
++ * size.
++ */
++ if (usermem == 0) {
++ usermem = 1;
++ meminfo.nr_banks = 0;
++ }
++
++ start = PHYS_OFFSET;
++ size = memparse(p, &endp);
++ if (*endp == '@')
++ start = memparse(endp + 1, NULL);
++
++ arm_add_memory(start, size);
++
++ return 0;
++}
++early_param("mem", early_mem);
++
++static void __init
++setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
++{
++#ifdef CONFIG_BLK_DEV_RAM
++ extern int rd_size, rd_image_start, rd_prompt, rd_doload;
++
++ rd_image_start = image_start;
++ rd_prompt = prompt;
++ rd_doload = doload;
++
++ if (rd_sz)
++ rd_size = rd_sz;
++#endif
++}
++
++static void __init
++request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
++{
++ struct resource *res;
++ int i;
++
++ kernel_code.start = virt_to_phys(_text);
++ kernel_code.end = virt_to_phys(_etext - 1);
++ kernel_data.start = virt_to_phys(_data);
++ kernel_data.end = virt_to_phys(_end - 1);
++
++ for (i = 0; i < mi->nr_banks; i++) {
++ if (mi->bank[i].size == 0)
++ continue;
++
++ res = alloc_bootmem_low(sizeof(*res));
++ res->name = "System RAM";
++ res->start = mi->bank[i].start;
++ res->end = mi->bank[i].start + mi->bank[i].size - 1;
++ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
++
++ request_resource(&iomem_resource, res);
++
++ if (kernel_code.start >= res->start &&
++ kernel_code.end <= res->end)
++ request_resource(res, &kernel_code);
++ if (kernel_data.start >= res->start &&
++ kernel_data.end <= res->end)
++ request_resource(res, &kernel_data);
++ }
++
++ if (mdesc->video_start) {
++ video_ram.start = mdesc->video_start;
++ video_ram.end = mdesc->video_end;
++ request_resource(&iomem_resource, &video_ram);
++ }
++
++ /*
++ * Some machines don't have the possibility of ever
++ * possessing lp0, lp1 or lp2
++ */
++ if (mdesc->reserve_lp0)
++ request_resource(&ioport_resource, &lp0);
++ if (mdesc->reserve_lp1)
++ request_resource(&ioport_resource, &lp1);
++ if (mdesc->reserve_lp2)
++ request_resource(&ioport_resource, &lp2);
++}
++
++/*
++ * Tag parsing.
++ *
++ * This is the new way of passing data to the kernel at boot time. Rather
++ * than passing a fixed inflexible structure to the kernel, we pass a list
++ * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE
++ * tag for the list to be recognised (to distinguish the tagged list from
++ * a param_struct). The list is terminated with a zero-length tag (this tag
++ * is not parsed in any way).
++ */
++static int __init parse_tag_core(const struct tag *tag)
++{
++ if (tag->hdr.size > 2) {
++ if ((tag->u.core.flags & 1) == 0)
++ root_mountflags &= ~MS_RDONLY;
++ ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
++ }
++ return 0;
++}
++
++__tagtable(ATAG_CORE, parse_tag_core);
++
++static int __init parse_tag_mem32(const struct tag *tag)
++{
++ return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
++}
++
++__tagtable(ATAG_MEM, parse_tag_mem32);
++
++#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
++struct screen_info screen_info = {
++ .orig_video_lines = 30,
++ .orig_video_cols = 80,
++ .orig_video_mode = 0,
++ .orig_video_ega_bx = 0,
++ .orig_video_isVGA = 1,
++ .orig_video_points = 8
++};
++
++static int __init parse_tag_videotext(const struct tag *tag)
++{
++ screen_info.orig_x = tag->u.videotext.x;
++ screen_info.orig_y = tag->u.videotext.y;
++ screen_info.orig_video_page = tag->u.videotext.video_page;
++ screen_info.orig_video_mode = tag->u.videotext.video_mode;
++ screen_info.orig_video_cols = tag->u.videotext.video_cols;
++ screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
++ screen_info.orig_video_lines = tag->u.videotext.video_lines;
++ screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
++ screen_info.orig_video_points = tag->u.videotext.video_points;
++ return 0;
++}
++
++__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
++#endif
++
++static int __init parse_tag_ramdisk(const struct tag *tag)
++{
++ setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
++ (tag->u.ramdisk.flags & 2) == 0,
++ tag->u.ramdisk.start, tag->u.ramdisk.size);
++ return 0;
++}
++
++__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
++
++static int __init parse_tag_serialnr(const struct tag *tag)
++{
++ system_serial_low = tag->u.serialnr.low;
++ system_serial_high = tag->u.serialnr.high;
++ return 0;
++}
++
++__tagtable(ATAG_SERIAL, parse_tag_serialnr);
++
++static int __init parse_tag_revision(const struct tag *tag)
++{
++ system_rev = tag->u.revision.rev;
++ return 0;
++}
++
++__tagtable(ATAG_REVISION, parse_tag_revision);
++
++#ifndef CONFIG_CMDLINE_FORCE
++static int __init parse_tag_cmdline(const struct tag *tag)
++{
++ strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
++ return 0;
++}
++
++__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
++#endif /* CONFIG_CMDLINE_FORCE */
++
++/*
++ * Scan the tag table for this tag, and call its parse function.
++ * The tag table is built by the linker from all the __tagtable
++ * declarations.
++ */
++static int __init parse_tag(const struct tag *tag)
++{
++ extern struct tagtable __tagtable_begin, __tagtable_end;
++ struct tagtable *t;
++
++ for (t = &__tagtable_begin; t < &__tagtable_end; t++)
++ if (tag->hdr.tag == t->tag) {
++ t->parse(tag);
++ break;
++ }
++
++ return t < &__tagtable_end;
++}
++
++/*
++ * Parse all tags in the list, checking both the global and architecture
++ * specific tag tables.
++ */
++static void __init parse_tags(const struct tag *t)
++{
++ for (; t->hdr.size; t = tag_next(t))
++ if (!parse_tag(t))
++ printk(KERN_WARNING
++ "Ignoring unrecognised tag 0x%08x\n",
++ t->hdr.tag);
++}
++
++/*
++ * This holds our defaults.
++ */
++static struct init_tags {
++ struct tag_header hdr1;
++ struct tag_core core;
++ struct tag_header hdr2;
++ struct tag_mem32 mem;
++ struct tag_header hdr3;
++} init_tags __initdata = {
++ { tag_size(tag_core), ATAG_CORE },
++ { 1, PAGE_SIZE, 0xff },
++ { tag_size(tag_mem32), ATAG_MEM },
++ { MEM_SIZE, PHYS_OFFSET },
++ { 0, ATAG_NONE }
++};
++
++static void (*init_machine)(void) __initdata;
++
++static int __init customize_machine(void)
++{
++ /* customizes platform devices, or adds new ones */
++ if (init_machine)
++ init_machine();
++ return 0;
++}
++arch_initcall(customize_machine);
++
++void __init setup_arch(char **cmdline_p)
++{
++ struct tag *tags = (struct tag *)&init_tags;
++ struct machine_desc *mdesc;
++ char *from = default_command_line;
++
++ unwind_init();
++
++ setup_processor();
++ mdesc = setup_machine(machine_arch_type);
++ machine_name = mdesc->name;
++
++ if (mdesc->soft_reboot)
++ reboot_setup("s");
++
++ if (__atags_pointer)
++ tags = phys_to_virt(__atags_pointer);
++ else if (mdesc->boot_params)
++ tags = phys_to_virt(mdesc->boot_params);
++
++ /*
++ * If we have the old style parameters, convert them to
++ * a tag list.
++ */
++ if (tags->hdr.tag != ATAG_CORE)
++ convert_to_tag_list(tags);
++ if (tags->hdr.tag != ATAG_CORE)
++ tags = (struct tag *)&init_tags;
++
++ if (mdesc->fixup)
++ mdesc->fixup(mdesc, tags, &from, &meminfo);
++
++ if (tags->hdr.tag == ATAG_CORE) {
++ if (meminfo.nr_banks != 0)
++ squash_mem_tags(tags);
++ save_atags(tags);
++ parse_tags(tags);
++ }
++
++ init_mm.start_code = (unsigned long) _text;
++ init_mm.end_code = (unsigned long) _etext;
++ init_mm.end_data = (unsigned long) _edata;
++ init_mm.brk = (unsigned long) _end;
++
++ /* parse_early_param needs a boot_command_line */
++ strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
++
++ /* populate cmd_line too for later use, preserving boot_command_line */
++ strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
++ *cmdline_p = cmd_line;
++
++ parse_early_param();
++
++ paging_init(mdesc);
++ request_standard_resources(&meminfo, mdesc);
++
++#ifdef CONFIG_SMP
++ smp_init_cpus();
++#endif
++
++ cpu_init();
++ tcm_init();
++
++ /*
++ * Set up various architecture-specific pointers
++ */
++ init_arch_irq = mdesc->init_irq;
++ system_timer = mdesc->timer;
++ init_machine = mdesc->init_machine;
++
++#ifdef CONFIG_VT
++#if defined(CONFIG_VGA_CONSOLE)
++ conswitchp = &vga_con;
++#elif defined(CONFIG_DUMMY_CONSOLE)
++ conswitchp = &dummy_con;
++#endif
++#endif
++ early_trap_init();
++}
++
++
++static int __init topology_init(void)
++{
++ int cpu;
++
++ for_each_possible_cpu(cpu) {
++ struct cpuinfo_arm *cpuinfo = &per_cpu(cpu_data, cpu);
++ cpuinfo->cpu.hotpluggable = 1;
++ register_cpu(&cpuinfo->cpu, cpu);
++ }
++
++ return 0;
++}
++subsys_initcall(topology_init);
++
++#ifdef CONFIG_HAVE_PROC_CPU
++static int __init proc_cpu_init(void)
++{
++ struct proc_dir_entry *res;
++
++ res = proc_mkdir("cpu", NULL);
++ if (!res)
++ return -ENOMEM;
++ return 0;
++}
++fs_initcall(proc_cpu_init);
++#endif
++
++static const char *hwcap_str[] = {
++ "swp",
++ "half",
++ "thumb",
++ "26bit",
++ "fastmult",
++ "fpa",
++ "vfp",
++ "edsp",
++ "java",
++ "iwmmxt",
++ "crunch",
++ "thumbee",
++ "neon",
++ "vfpv3",
++ "vfpv3d16",
++ NULL
++};
++
++static int c_show(struct seq_file *m, void *v)
++{
++ int i;
++
++ seq_printf(m, "Processor\t: %s rev %d (%s)\n",
++ cpu_name, read_cpuid_id() & 15, elf_platform);
++
++#if defined(CONFIG_SMP)
++ for_each_online_cpu(i) {
++ /*
++ * glibc reads /proc/cpuinfo to determine the number of
++ * online processors, looking for lines beginning with
++ * "processor". Give glibc what it expects.
++ */
++ seq_printf(m, "processor\t: %d\n", i);
++ seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
++ per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
++ (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
++ }
++#else /* CONFIG_SMP */
++ seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
++ loops_per_jiffy / (500000/HZ),
++ (loops_per_jiffy / (5000/HZ)) % 100);
++#endif
++
++ /* dump out the processor features */
++ seq_puts(m, "Features\t: ");
++
++ for (i = 0; hwcap_str[i]; i++)
++ if (elf_hwcap & (1 << i))
++ seq_printf(m, "%s ", hwcap_str[i]);
++
++ seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
++ seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
++
++ if ((read_cpuid_id() & 0x0008f000) == 0x00000000) {
++ /* pre-ARM7 */
++ seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4);
++ } else {
++ if ((read_cpuid_id() & 0x0008f000) == 0x00007000) {
++ /* ARM7 */
++ seq_printf(m, "CPU variant\t: 0x%02x\n",
++ (read_cpuid_id() >> 16) & 127);
++ } else {
++ /* post-ARM7 */
++ seq_printf(m, "CPU variant\t: 0x%x\n",
++ (read_cpuid_id() >> 20) & 15);
++ }
++ seq_printf(m, "CPU part\t: 0x%03x\n",
++ (read_cpuid_id() >> 4) & 0xfff);
++ }
++ seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
++
++ seq_puts(m, "\n");
++
++ seq_printf(m, "Hardware\t: %s\n", machine_name);
++ seq_printf(m, "Revision\t: %04x\n", system_rev);
++ seq_printf(m, "Serial\t\t: %08x%08x\n",
++ system_serial_high, system_serial_low);
++
++ return 0;
++}
++
++static void *c_start(struct seq_file *m, loff_t *pos)
++{
++ return *pos < 1 ? (void *)1 : NULL;
++}
++
++static void *c_next(struct seq_file *m, void *v, loff_t *pos)
++{
++ ++*pos;
++ return NULL;
++}
++
++static void c_stop(struct seq_file *m, void *v)
++{
++}
++
++const struct seq_operations cpuinfo_op = {
++ .start = c_start,
++ .next = c_next,
++ .stop = c_stop,
++ .show = c_show
++};
+diff -rupN linux-2.6.35.11/arch/arm/kernel/traps.c linux-2.6.35.11-ts7500/arch/arm/kernel/traps.c
+--- linux-2.6.35.11/arch/arm/kernel/traps.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/kernel/traps.c 2011-03-14 11:18:24.000000000 -0400
+@@ -467,7 +467,7 @@ asmlinkage int arm_syscall(int no, struc
+ {
+ struct thread_info *thread = current_thread_info();
+ siginfo_t info;
+-
++
+ if ((no >> 16) != (__ARM_NR_BASE>> 16))
+ return bad_syscall(no, regs);
+
+diff -rupN linux-2.6.35.11/arch/arm/kernel/traps.c.orig linux-2.6.35.11-ts7500/arch/arm/kernel/traps.c.orig
+--- linux-2.6.35.11/arch/arm/kernel/traps.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/kernel/traps.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,774 @@
++/*
++ * linux/arch/arm/kernel/traps.c
++ *
++ * Copyright (C) 1995-2009 Russell King
++ * Fragments that appear the same as linux/arch/i386/kernel/traps.c (C) Linus Torvalds
++ *
++ * 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.
++ *
++ * 'traps.c' handles hardware exceptions after we have saved some state in
++ * 'linux/arch/arm/lib/traps.S'. Mostly a debugging aid, but will probably
++ * kill the offending process.
++ */
++#include <linux/signal.h>
++#include <linux/personality.h>
++#include <linux/kallsyms.h>
++#include <linux/spinlock.h>
++#include <linux/uaccess.h>
++#include <linux/hardirq.h>
++#include <linux/kdebug.h>
++#include <linux/module.h>
++#include <linux/kexec.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++
++#include <asm/atomic.h>
++#include <asm/cacheflush.h>
++#include <asm/system.h>
++#include <asm/unistd.h>
++#include <asm/traps.h>
++#include <asm/unwind.h>
++
++#include "ptrace.h"
++#include "signal.h"
++
++static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
++
++#ifdef CONFIG_DEBUG_USER
++unsigned int user_debug;
++
++static int __init user_debug_setup(char *str)
++{
++ get_option(&str, &user_debug);
++ return 1;
++}
++__setup("user_debug=", user_debug_setup);
++#endif
++
++static void dump_mem(const char *, const char *, unsigned long, unsigned long);
++
++void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)
++{
++#ifdef CONFIG_KALLSYMS
++ char sym1[KSYM_SYMBOL_LEN], sym2[KSYM_SYMBOL_LEN];
++ sprint_symbol(sym1, where);
++ sprint_symbol(sym2, from);
++ printk("[<%08lx>] (%s) from [<%08lx>] (%s)\n", where, sym1, from, sym2);
++#else
++ printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from);
++#endif
++
++ if (in_exception_text(where))
++ dump_mem("", "Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs));
++}
++
++#ifndef CONFIG_ARM_UNWIND
++/*
++ * Stack pointers should always be within the kernels view of
++ * physical memory. If it is not there, then we can't dump
++ * out any information relating to the stack.
++ */
++static int verify_stack(unsigned long sp)
++{
++ if (sp < PAGE_OFFSET ||
++ (sp > (unsigned long)high_memory && high_memory != NULL))
++ return -EFAULT;
++
++ return 0;
++}
++#endif
++
++/*
++ * Dump out the contents of some memory nicely...
++ */
++static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
++ unsigned long top)
++{
++ unsigned long first;
++ mm_segment_t fs;
++ int i;
++
++ /*
++ * We need to switch to kernel mode so that we can use __get_user
++ * to safely read from kernel space. Note that we now dump the
++ * code first, just in case the backtrace kills us.
++ */
++ fs = get_fs();
++ set_fs(KERNEL_DS);
++
++ printk("%s%s(0x%08lx to 0x%08lx)\n", lvl, str, bottom, top);
++
++ for (first = bottom & ~31; first < top; first += 32) {
++ unsigned long p;
++ char str[sizeof(" 12345678") * 8 + 1];
++
++ memset(str, ' ', sizeof(str));
++ str[sizeof(str) - 1] = '\0';
++
++ for (p = first, i = 0; i < 8 && p < top; i++, p += 4) {
++ if (p >= bottom && p < top) {
++ unsigned long val;
++ if (__get_user(val, (unsigned long *)p) == 0)
++ sprintf(str + i * 9, " %08lx", val);
++ else
++ sprintf(str + i * 9, " ????????");
++ }
++ }
++ printk("%s%04lx:%s\n", lvl, first & 0xffff, str);
++ }
++
++ set_fs(fs);
++}
++
++static void dump_instr(const char *lvl, struct pt_regs *regs)
++{
++ unsigned long addr = instruction_pointer(regs);
++ const int thumb = thumb_mode(regs);
++ const int width = thumb ? 4 : 8;
++ mm_segment_t fs;
++ char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str;
++ int i;
++
++ /*
++ * We need to switch to kernel mode so that we can use __get_user
++ * to safely read from kernel space. Note that we now dump the
++ * code first, just in case the backtrace kills us.
++ */
++ fs = get_fs();
++ set_fs(KERNEL_DS);
++
++ for (i = -4; i < 1; i++) {
++ unsigned int val, bad;
++
++ if (thumb)
++ bad = __get_user(val, &((u16 *)addr)[i]);
++ else
++ bad = __get_user(val, &((u32 *)addr)[i]);
++
++ if (!bad)
++ p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ",
++ width, val);
++ else {
++ p += sprintf(p, "bad PC value");
++ break;
++ }
++ }
++ printk("%sCode: %s\n", lvl, str);
++
++ set_fs(fs);
++}
++
++#ifdef CONFIG_ARM_UNWIND
++static inline void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
++{
++ unwind_backtrace(regs, tsk);
++}
++#else
++static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
++{
++ unsigned int fp, mode;
++ int ok = 1;
++
++ printk("Backtrace: ");
++
++ if (!tsk)
++ tsk = current;
++
++ if (regs) {
++ fp = regs->ARM_fp;
++ mode = processor_mode(regs);
++ } else if (tsk != current) {
++ fp = thread_saved_fp(tsk);
++ mode = 0x10;
++ } else {
++ asm("mov %0, fp" : "=r" (fp) : : "cc");
++ mode = 0x10;
++ }
++
++ if (!fp) {
++ printk("no frame pointer");
++ ok = 0;
++ } else if (verify_stack(fp)) {
++ printk("invalid frame pointer 0x%08x", fp);
++ ok = 0;
++ } else if (fp < (unsigned long)end_of_stack(tsk))
++ printk("frame pointer underflow");
++ printk("\n");
++
++ if (ok)
++ c_backtrace(fp, mode);
++}
++#endif
++
++void dump_stack(void)
++{
++ dump_backtrace(NULL, NULL);
++}
++
++EXPORT_SYMBOL(dump_stack);
++
++void show_stack(struct task_struct *tsk, unsigned long *sp)
++{
++ dump_backtrace(NULL, tsk);
++ barrier();
++}
++
++#ifdef CONFIG_PREEMPT
++#define S_PREEMPT " PREEMPT"
++#else
++#define S_PREEMPT ""
++#endif
++#ifdef CONFIG_SMP
++#define S_SMP " SMP"
++#else
++#define S_SMP ""
++#endif
++
++static int __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)
++{
++ struct task_struct *tsk = thread->task;
++ static int die_counter;
++ int ret;
++
++ printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
++ str, err, ++die_counter);
++ sysfs_printk_last_file();
++
++ /* trap and error numbers are mostly meaningless on ARM */
++ ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV);
++ if (ret == NOTIFY_STOP)
++ return ret;
++
++ print_modules();
++ __show_regs(regs);
++ printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n",
++ TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1);
++
++ if (!user_mode(regs) || in_interrupt()) {
++ dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp,
++ THREAD_SIZE + (unsigned long)task_stack_page(tsk));
++ dump_backtrace(regs, tsk);
++ dump_instr(KERN_EMERG, regs);
++ }
++
++ return ret;
++}
++
++DEFINE_SPINLOCK(die_lock);
++
++/*
++ * This function is protected against re-entrancy.
++ */
++void die(const char *str, struct pt_regs *regs, int err)
++{
++ struct thread_info *thread = current_thread_info();
++ int ret;
++
++ oops_enter();
++
++ spin_lock_irq(&die_lock);
++ console_verbose();
++ bust_spinlocks(1);
++ ret = __die(str, err, thread, regs);
++
++ if (regs && kexec_should_crash(thread->task))
++ crash_kexec(regs);
++
++ bust_spinlocks(0);
++ add_taint(TAINT_DIE);
++ spin_unlock_irq(&die_lock);
++ oops_exit();
++
++ if (in_interrupt())
++ panic("Fatal exception in interrupt");
++ if (panic_on_oops)
++ panic("Fatal exception");
++ if (ret != NOTIFY_STOP)
++ do_exit(SIGSEGV);
++}
++
++void arm_notify_die(const char *str, struct pt_regs *regs,
++ struct siginfo *info, unsigned long err, unsigned long trap)
++{
++ if (user_mode(regs)) {
++ current->thread.error_code = err;
++ current->thread.trap_no = trap;
++
++ force_sig_info(info->si_signo, info, current);
++ } else {
++ die(str, regs, err);
++ }
++}
++
++static LIST_HEAD(undef_hook);
++static DEFINE_SPINLOCK(undef_lock);
++
++void register_undef_hook(struct undef_hook *hook)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&undef_lock, flags);
++ list_add(&hook->node, &undef_hook);
++ spin_unlock_irqrestore(&undef_lock, flags);
++}
++
++void unregister_undef_hook(struct undef_hook *hook)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&undef_lock, flags);
++ list_del(&hook->node);
++ spin_unlock_irqrestore(&undef_lock, flags);
++}
++
++static int call_undef_hook(struct pt_regs *regs, unsigned int instr)
++{
++ struct undef_hook *hook;
++ unsigned long flags;
++ int (*fn)(struct pt_regs *regs, unsigned int instr) = NULL;
++
++ spin_lock_irqsave(&undef_lock, flags);
++ list_for_each_entry(hook, &undef_hook, node)
++ if ((instr & hook->instr_mask) == hook->instr_val &&
++ (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val)
++ fn = hook->fn;
++ spin_unlock_irqrestore(&undef_lock, flags);
++
++ return fn ? fn(regs, instr) : 1;
++}
++
++asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
++{
++ unsigned int correction = thumb_mode(regs) ? 2 : 4;
++ unsigned int instr;
++ siginfo_t info;
++ void __user *pc;
++
++ /*
++ * According to the ARM ARM, PC is 2 or 4 bytes ahead,
++ * depending whether we're in Thumb mode or not.
++ * Correct this offset.
++ */
++ regs->ARM_pc -= correction;
++
++ pc = (void __user *)instruction_pointer(regs);
++
++ if (processor_mode(regs) == SVC_MODE) {
++ instr = *(u32 *) pc;
++ } else if (thumb_mode(regs)) {
++ get_user(instr, (u16 __user *)pc);
++ } else {
++ get_user(instr, (u32 __user *)pc);
++ }
++
++ if (call_undef_hook(regs, instr) == 0)
++ return;
++
++#ifdef CONFIG_DEBUG_USER
++ if (user_debug & UDBG_UNDEFINED) {
++ printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n",
++ current->comm, task_pid_nr(current), pc);
++ dump_instr(KERN_INFO, regs);
++ }
++#endif
++
++ info.si_signo = SIGILL;
++ info.si_errno = 0;
++ info.si_code = ILL_ILLOPC;
++ info.si_addr = pc;
++
++ arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6);
++}
++
++asmlinkage void do_unexp_fiq (struct pt_regs *regs)
++{
++ printk("Hmm. Unexpected FIQ received, but trying to continue\n");
++ printk("You may have a hardware problem...\n");
++}
++
++/*
++ * bad_mode handles the impossible case in the vectors. If you see one of
++ * these, then it's extremely serious, and could mean you have buggy hardware.
++ * It never returns, and never tries to sync. We hope that we can at least
++ * dump out some state information...
++ */
++asmlinkage void bad_mode(struct pt_regs *regs, int reason)
++{
++ console_verbose();
++
++ printk(KERN_CRIT "Bad mode in %s handler detected\n", handler[reason]);
++
++ die("Oops - bad mode", regs, 0);
++ local_irq_disable();
++ panic("bad mode");
++}
++
++static int bad_syscall(int n, struct pt_regs *regs)
++{
++ struct thread_info *thread = current_thread_info();
++ siginfo_t info;
++
++ if (current->personality != PER_LINUX &&
++ current->personality != PER_LINUX_32BIT &&
++ thread->exec_domain->handler) {
++ thread->exec_domain->handler(n, regs);
++ return regs->ARM_r0;
++ }
++
++#ifdef CONFIG_DEBUG_USER
++ if (user_debug & UDBG_SYSCALL) {
++ printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n",
++ task_pid_nr(current), current->comm, n);
++ dump_instr(KERN_ERR, regs);
++ }
++#endif
++
++ info.si_signo = SIGILL;
++ info.si_errno = 0;
++ info.si_code = ILL_ILLTRP;
++ info.si_addr = (void __user *)instruction_pointer(regs) -
++ (thumb_mode(regs) ? 2 : 4);
++
++ arm_notify_die("Oops - bad syscall", regs, &info, n, 0);
++
++ return regs->ARM_r0;
++}
++
++static inline void
++do_cache_op(unsigned long start, unsigned long end, int flags)
++{
++ struct mm_struct *mm = current->active_mm;
++ struct vm_area_struct *vma;
++
++ if (end < start || flags)
++ return;
++
++ down_read(&mm->mmap_sem);
++ vma = find_vma(mm, start);
++ if (vma && vma->vm_start < end) {
++ if (start < vma->vm_start)
++ start = vma->vm_start;
++ if (end > vma->vm_end)
++ end = vma->vm_end;
++
++ flush_cache_user_range(vma, start, end);
++ }
++ up_read(&mm->mmap_sem);
++}
++
++/*
++ * Handle all unrecognised system calls.
++ * 0x9f0000 - 0x9fffff are some more esoteric system calls
++ */
++#define NR(x) ((__ARM_NR_##x) - __ARM_NR_BASE)
++asmlinkage int arm_syscall(int no, struct pt_regs *regs)
++{
++ struct thread_info *thread = current_thread_info();
++ siginfo_t info;
++
++ if ((no >> 16) != (__ARM_NR_BASE>> 16))
++ return bad_syscall(no, regs);
++
++ switch (no & 0xffff) {
++ case 0: /* branch through 0 */
++ info.si_signo = SIGSEGV;
++ info.si_errno = 0;
++ info.si_code = SEGV_MAPERR;
++ info.si_addr = NULL;
++
++ arm_notify_die("branch through zero", regs, &info, 0, 0);
++ return 0;
++
++ case NR(breakpoint): /* SWI BREAK_POINT */
++ regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
++ ptrace_break(current, regs);
++ return regs->ARM_r0;
++
++ /*
++ * Flush a region from virtual address 'r0' to virtual address 'r1'
++ * _exclusive_. There is no alignment requirement on either address;
++ * user space does not need to know the hardware cache layout.
++ *
++ * r2 contains flags. It should ALWAYS be passed as ZERO until it
++ * is defined to be something else. For now we ignore it, but may
++ * the fires of hell burn in your belly if you break this rule. ;)
++ *
++ * (at a later date, we may want to allow this call to not flush
++ * various aspects of the cache. Passing '0' will guarantee that
++ * everything necessary gets flushed to maintain consistency in
++ * the specified region).
++ */
++ case NR(cacheflush):
++ do_cache_op(regs->ARM_r0, regs->ARM_r1, regs->ARM_r2);
++ return 0;
++
++ case NR(usr26):
++ if (!(elf_hwcap & HWCAP_26BIT))
++ break;
++ regs->ARM_cpsr &= ~MODE32_BIT;
++ return regs->ARM_r0;
++
++ case NR(usr32):
++ if (!(elf_hwcap & HWCAP_26BIT))
++ break;
++ regs->ARM_cpsr |= MODE32_BIT;
++ return regs->ARM_r0;
++
++ case NR(set_tls):
++ thread->tp_value = regs->ARM_r0;
++#if defined(CONFIG_HAS_TLS_REG)
++ asm ("mcr p15, 0, %0, c13, c0, 3" : : "r" (regs->ARM_r0) );
++#elif !defined(CONFIG_TLS_REG_EMUL)
++ /*
++ * User space must never try to access this directly.
++ * Expect your app to break eventually if you do so.
++ * The user helper at 0xffff0fe0 must be used instead.
++ * (see entry-armv.S for details)
++ */
++ *((unsigned int *)0xffff0ff0) = regs->ARM_r0;
++#endif
++ return 0;
++
++#ifdef CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG
++ /*
++ * Atomically store r1 in *r2 if *r2 is equal to r0 for user space.
++ * Return zero in r0 if *MEM was changed or non-zero if no exchange
++ * happened. Also set the user C flag accordingly.
++ * If access permissions have to be fixed up then non-zero is
++ * returned and the operation has to be re-attempted.
++ *
++ * *NOTE*: This is a ghost syscall private to the kernel. Only the
++ * __kuser_cmpxchg code in entry-armv.S should be aware of its
++ * existence. Don't ever use this from user code.
++ */
++ case NR(cmpxchg):
++ for (;;) {
++ extern void do_DataAbort(unsigned long addr, unsigned int fsr,
++ struct pt_regs *regs);
++ unsigned long val;
++ unsigned long addr = regs->ARM_r2;
++ struct mm_struct *mm = current->mm;
++ pgd_t *pgd; pmd_t *pmd; pte_t *pte;
++ spinlock_t *ptl;
++
++ regs->ARM_cpsr &= ~PSR_C_BIT;
++ down_read(&mm->mmap_sem);
++ pgd = pgd_offset(mm, addr);
++ if (!pgd_present(*pgd))
++ goto bad_access;
++ pmd = pmd_offset(pgd, addr);
++ if (!pmd_present(*pmd))
++ goto bad_access;
++ pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
++ if (!pte_present(*pte) || !pte_dirty(*pte)) {
++ pte_unmap_unlock(pte, ptl);
++ goto bad_access;
++ }
++ val = *(unsigned long *)addr;
++ val -= regs->ARM_r0;
++ if (val == 0) {
++ *(unsigned long *)addr = regs->ARM_r1;
++ regs->ARM_cpsr |= PSR_C_BIT;
++ }
++ pte_unmap_unlock(pte, ptl);
++ up_read(&mm->mmap_sem);
++ return val;
++
++ bad_access:
++ up_read(&mm->mmap_sem);
++ /* simulate a write access fault */
++ do_DataAbort(addr, 15 + (1 << 11), regs);
++ }
++#endif
++
++ default:
++ /* Calls 9f00xx..9f07ff are defined to return -ENOSYS
++ if not implemented, rather than raising SIGILL. This
++ way the calling program can gracefully determine whether
++ a feature is supported. */
++ if ((no & 0xffff) <= 0x7ff)
++ return -ENOSYS;
++ break;
++ }
++#ifdef CONFIG_DEBUG_USER
++ /*
++ * experience shows that these seem to indicate that
++ * something catastrophic has happened
++ */
++ if (user_debug & UDBG_SYSCALL) {
++ printk("[%d] %s: arm syscall %d\n",
++ task_pid_nr(current), current->comm, no);
++ dump_instr("", regs);
++ if (user_mode(regs)) {
++ __show_regs(regs);
++ c_backtrace(regs->ARM_fp, processor_mode(regs));
++ }
++ }
++#endif
++ info.si_signo = SIGILL;
++ info.si_errno = 0;
++ info.si_code = ILL_ILLTRP;
++ info.si_addr = (void __user *)instruction_pointer(regs) -
++ (thumb_mode(regs) ? 2 : 4);
++
++ arm_notify_die("Oops - bad syscall(2)", regs, &info, no, 0);
++ return 0;
++}
++
++#ifdef CONFIG_TLS_REG_EMUL
++
++/*
++ * We might be running on an ARMv6+ processor which should have the TLS
++ * register but for some reason we can't use it, or maybe an SMP system
++ * using a pre-ARMv6 processor (there are apparently a few prototypes like
++ * that in existence) and therefore access to that register must be
++ * emulated.
++ */
++
++static int get_tp_trap(struct pt_regs *regs, unsigned int instr)
++{
++ int reg = (instr >> 12) & 15;
++ if (reg == 15)
++ return 1;
++ regs->uregs[reg] = current_thread_info()->tp_value;
++ regs->ARM_pc += 4;
++ return 0;
++}
++
++static struct undef_hook arm_mrc_hook = {
++ .instr_mask = 0x0fff0fff,
++ .instr_val = 0x0e1d0f70,
++ .cpsr_mask = PSR_T_BIT,
++ .cpsr_val = 0,
++ .fn = get_tp_trap,
++};
++
++static int __init arm_mrc_hook_init(void)
++{
++ register_undef_hook(&arm_mrc_hook);
++ return 0;
++}
++
++late_initcall(arm_mrc_hook_init);
++
++#endif
++
++void __bad_xchg(volatile void *ptr, int size)
++{
++ printk("xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n",
++ __builtin_return_address(0), ptr, size);
++ BUG();
++}
++EXPORT_SYMBOL(__bad_xchg);
++
++/*
++ * A data abort trap was taken, but we did not handle the instruction.
++ * Try to abort the user program, or panic if it was the kernel.
++ */
++asmlinkage void
++baddataabort(int code, unsigned long instr, struct pt_regs *regs)
++{
++ unsigned long addr = instruction_pointer(regs);
++ siginfo_t info;
++
++#ifdef CONFIG_DEBUG_USER
++ if (user_debug & UDBG_BADABORT) {
++ printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n",
++ task_pid_nr(current), current->comm, code, instr);
++ dump_instr(KERN_ERR, regs);
++ show_pte(current->mm, addr);
++ }
++#endif
++
++ info.si_signo = SIGILL;
++ info.si_errno = 0;
++ info.si_code = ILL_ILLOPC;
++ info.si_addr = (void __user *)addr;
++
++ arm_notify_die("unknown data abort code", regs, &info, instr, 0);
++}
++
++void __attribute__((noreturn)) __bug(const char *file, int line)
++{
++ printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line);
++ *(int *)0 = 0;
++
++ /* Avoid "noreturn function does return" */
++ for (;;);
++}
++EXPORT_SYMBOL(__bug);
++
++void __readwrite_bug(const char *fn)
++{
++ printk("%s called, but not implemented\n", fn);
++ BUG();
++}
++EXPORT_SYMBOL(__readwrite_bug);
++
++void __pte_error(const char *file, int line, unsigned long val)
++{
++ printk("%s:%d: bad pte %08lx.\n", file, line, val);
++}
++
++void __pmd_error(const char *file, int line, unsigned long val)
++{
++ printk("%s:%d: bad pmd %08lx.\n", file, line, val);
++}
++
++void __pgd_error(const char *file, int line, unsigned long val)
++{
++ printk("%s:%d: bad pgd %08lx.\n", file, line, val);
++}
++
++asmlinkage void __div0(void)
++{
++ printk("Division by zero in kernel.\n");
++ dump_stack();
++}
++EXPORT_SYMBOL(__div0);
++
++void abort(void)
++{
++ BUG();
++
++ /* if that doesn't kill us, halt */
++ panic("Oops failed to kill thread");
++}
++EXPORT_SYMBOL(abort);
++
++void __init trap_init(void)
++{
++ return;
++}
++
++void __init early_trap_init(void)
++{
++ unsigned long vectors = CONFIG_VECTORS_BASE;
++ extern char __stubs_start[], __stubs_end[];
++ extern char __vectors_start[], __vectors_end[];
++ extern char __kuser_helper_start[], __kuser_helper_end[];
++ int kuser_sz = __kuser_helper_end - __kuser_helper_start;
++
++ /*
++ * Copy the vectors, stubs and kuser helpers (in entry-armv.S)
++ * into the vector page, mapped at 0xffff0000, and ensure these
++ * are visible to the instruction stream.
++ */
++ memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
++ memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);
++ memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
++
++ /*
++ * Copy signal return handlers into the vector page, and
++ * set sigreturn to be a pointer to these.
++ */
++ memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
++ sizeof(sigreturn_codes));
++ memcpy((void *)KERN_RESTART_CODE, syscall_restart_code,
++ sizeof(syscall_restart_code));
++
++ flush_icache_range(vectors, vectors + PAGE_SIZE);
++ modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
++}
+diff -rupN linux-2.6.35.11/arch/arm/kernel/vmlinux.lds.S linux-2.6.35.11-ts7500/arch/arm/kernel/vmlinux.lds.S
+--- linux-2.6.35.11/arch/arm/kernel/vmlinux.lds.S 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/kernel/vmlinux.lds.S 2011-03-14 11:18:24.000000000 -0400
+@@ -84,6 +84,12 @@ SECTIONS
+
+ .text : { /* Real text segment */
+ _text = .; /* Text and read-only data */
++#ifdef CONFIG_CPU_ISPAD_ENABLE
++ . = ALIGN(1024);
++ __ispad_begin = .;
++ *(.ispad)
++ __ispad_end = .;
++#endif
+ __exception_text_start = .;
+ *(.exception.text)
+ __exception_text_end = .;
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/debug-macro.S linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/debug-macro.S
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/debug-macro.S 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/debug-macro.S 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,54 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++//#include <linux/config.h>
++#include <linux/linkage.h>
++#include <mach/hardware.h>
++
++ .macro addruart,rx,tmp
++ mrc p15, 0, \rx, c1, c0
++ tst \rx, #1 @ MMU enabled ?
++ moveq \rx, #(SYSPA_UART0_BASE_ADDR) @ physical base address of UART0
++ movne \rx, #(SYSVA_UART0_BASE_ADDR & 0xFF000000) @ virtual base address of UART0
++ orrne \rx, \rx, #(SYSVA_UART0_BASE_ADDR & 0x00FF0000)
++ orrne \rx, \rx, #(SYSVA_UART0_BASE_ADDR & 0x0000FF00)
++ orrne \rx, \rx, #(SYSVA_UART0_BASE_ADDR & 0x000000FF)
++ .endm
++
++ .macro senduart,rd,rx
++ strb \rd, [\rx, #0x00]
++ .endm
++
++ .macro waituart,rd,rx
++ mov \rd, #0xf000
++1001: subs \rd, \rd, #1
++ bne 1001b
++ .endm
++
++ .macro busyuart,rd,rx
++ nop
++ mov \rd, #0xf000
++1010: subs \rd, \rd, #1
++ bne 1010b
++ .endm
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/dma.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/dma.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/dma.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/dma.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,27 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef __ASM_ARCH_DMA_H__
++#define __ASM_ARCH_DMA_H__
++
++#endif
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/entry-macro.S linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/entry-macro.S
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/entry-macro.S 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/entry-macro.S 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,79 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++//#include <mach/star_intc.h>
++#include <mach/star_intc.h>
++
++ .macro disable_fiq
++ .endm
++
++ .macro get_irqnr_preamble, base, tmp
++ .endm
++
++ .macro arch_ret_to_user, tmp1, tmp2
++ .endm
++
++
++#ifdef CONFIG_VIC_INTERRUPT
++ .macro get_fiqnr_and_base, irqnr, irqstat, base, tmp
++ ldr \base, =(SYSVA_VIC_BASE_ADDR + 0x140)
++ ldr \irqnr, [\base]
++ .endm
++
++ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
++ ldr \base, =(SYSVA_VIC_BASE_ADDR + 0x140)
++ ldr \irqnr, [\base]
++ .endm
++#else
++ .macro get_fiqnr_and_base, irqnr, irqstat, base, tmp
++ ldr \base, =(SYSVA_VIC_BASE_ADDR + 0x20)
++ ldr \irqstat, [\base]
++ mov \irqnr, #0
++9001:
++ tst \irqstat, #1
++ bne 9002f
++ add \irqnr, \irqnr, #1
++ mov \irqstat, \irqstat, lsr #1
++ cmp \irqnr, #32
++ bcc 9001b
++9002:
++ .endm
++
++ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
++ ldr \base, =(SYSVA_VIC_BASE_ADDR + 0x1C)
++ ldr \irqstat, [\base]
++ mov \irqnr, #0
++9003:
++ tst \irqstat, #1
++ bne 9004f
++ add \irqnr, \irqnr, #1
++ mov \irqstat, \irqstat, lsr #1
++ cmp \irqnr, #32
++ bcc 9003b
++9004:
++ .endm
++#endif
++
++ .macro irq_prio_table
++ .endm
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/hardware.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/hardware.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/hardware.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/hardware.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,71 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef __ASM_ARCH_HARDWARE_H__
++#define __ASM_ARCH_HARDWARE_H__
++
++//#include <linux/config.h>
++#include <mach/param.h>
++
++#include <mach/star_sys_memory_map.h>
++#include <mach/star_intc.h>
++#include <mach/star_timer.h>
++#include <mach/star_uart.h>
++#include <mach/star_gpio.h>
++#include <mach/star_pci_bridge.h>
++#include <mach/star_misc.h>
++#include <mach/star_powermgt.h>
++#include <mach/star_rtc.h>
++#include <mach/star_wdtimer.h>
++#include <mach/star_smc.h>
++#include <mach/star_nic.h>
++#include <mach/star_ide.h>
++
++#if 1 // on ASIC
++#define SYS_CLK (87500000) // 87.5MHz
++#define UART_CLK (24000000) // 24MHz
++#define AHB_CLK (SYS_CLK)
++#define APB_CLK (AHB_CLK >> 1)
++#define TIMER_COUNTER (APB_CLK / HZ)
++#else // on FPGA
++#define SYS_CLK (13000000) // 13MHz
++#define UART_CLK (13000000) // 13Mhz
++#define AHB_CLK (SYS_CLK)
++#define APB_CLK (AHB_CLK)
++#define TIMER_COUNTER (APB_CLK / HZ)
++#endif
++
++#define DEBUG_CONSOLE (0)
++
++#define FLASH_BASE_ADDR SYSPA_FLASH_SRAM_BANK0_BASE_ADDR
++#define FLASH_SIZE 0x800000
++
++#define PCIBIOS_MIN_IO 0x00000000
++#define PCIBIOS_MIN_MEM 0x00000000
++#if 1
++#define pcibios_assign_all_busses() 0
++#else
++#define pcibios_assign_all_busses() 1
++#endif
++
++#endif /* __ASM_ARCH_HARDWARE_H__ */
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/io.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/io.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/io.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/io.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,35 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef __ASM_ARCH_IO_H__
++#define __ASM_ARCH_IO_H__
++
++//#include <asm/hardware.h>
++
++#define IO_SPACE_LIMIT 0xffffffff
++
++#define __io(p) ((void __iomem *)(p))
++#define __mem_pci(a) (a)
++#define __mem_isa(a) (a)
++
++#endif
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/irqs.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/irqs.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/irqs.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/irqs.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,36 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef __ASM_ARCH_IRQS_H__
++#define __ASM_ARCH_IRQS_H__
++
++//#include <mach/star_intc.h>
++#include <mach/star_intc.h>
++
++#define NR_IRQS (32)
++
++#ifdef CONFIG_VIC_INTERRUPT
++#define irq_finish(irq) do { INTC_IRQ_VECTOR_ADDRESS_REG = 0; } while (0)
++#endif
++
++#endif /* __ASM_ARCH_IRQS_H__ */
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/memory.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/memory.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/memory.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/memory.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,82 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef __ASM_ARCH_MEMORY_H
++#define __ASM_ARCH_MEMORY_H
++
++#if 0
++#define TASK_SIZE (0xC0000000UL)
++#define TASK_SIZE_26 (0x04000000UL)
++#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
++#endif
++
++#define CONFIG_SYSTEM_DRAM_BASE 0x00000000
++#if defined(CONFIG_STR8100_DRAM_64M)
++#define CONFIG_SYSTEM_DRAM_SIZE 64
++#elif defined(CONFIG_STR8100_DRAM_32M)
++#define CONFIG_SYSTEM_DRAM_SIZE 32
++#elif defined(CONFIG_STR8100_DRAM_16M)
++#define CONFIG_SYSTEM_DRAM_SIZE 16
++#endif
++#define MEM_SIZE (CONFIG_SYSTEM_DRAM_SIZE)
++#define END_MEM (CONFIG_SYSTEM_DRAM_BASE + CONFIG_SYSTEM_DRAM_SIZE)
++#define DMA_SIZE 0xffffffff
++#define PHYS_OFFSET (CONFIG_SYSTEM_DRAM_BASE) // physical start address of memory
++#if 0
++#define PAGE_OFFSET (0xC0000000UL)
++#endif
++
++/*
++#define __virt_to_bus(x) ((x) - PAGE_OFFSET)
++#define __bus_to_virt(x) ((x) + PAGE_OFFSET)
++*/
++#if 0
++#define __virt_to_phys__is_a_macro
++#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET)
++
++#define __phys_to_virt__is_a_macro
++#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET)
++
++#define __virt_to_bus__is_a_macro
++#define __virt_to_bus(x) ((x) - PAGE_OFFSET)
++
++#define __bus_to_virt__is_a_macro
++#define __bus_to_virt(x) ((x) + PAGE_OFFSET)
++#endif
++
++/*
++#define __virt_to_bus(x) __virt_to_phys(x)
++#define __bus_to_virt(x) __phys_to_virt(x)
++
++#define __pfn_to_bus(x) __pfn_to_phys(x)
++#define __bus_to_pfn(x) __phys_to_pfn(x)
++*/
++
++/*
++#define __pfn_to_bus(p) __phys_to_bus(__pfn_to_phys(p))
++#define __bus_to_pfn(b) __phys_to_pfn(__bus_to_phys(b))
++*/
++
++
++
++#endif
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/param.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/param.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/param.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/param.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,32 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef __ASM_ARCH_PARAM_H__
++#define __ASM_ARCH_PARAM_H__
++
++// For timer, there will be HZ ticks per second
++/* scott.patch
++#define HZ 100
++*/
++
++#endif /* __ARCH_ASM_PARAM_H__ */
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_demo_dma.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_demo_dma.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_demo_dma.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_demo_dma.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,189 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef __DEMO_DMA_H__
++#define __DEMO_DMA_H__
++#include <linux/types.h> /* size_t */
++#include <linux/interrupt.h>
++#include <linux/module.h>
++
++#include <mach/star_dmac.h>
++
++/*
++ * defines for each channel
++ */
++#define DMAC_CH_DISABLE 0
++#define DMAC_CH_ENABLE 1
++
++#define DMAC_CH_DST_SEL_M0 0
++#define DMAC_CH_DST_SEL_M1 1
++
++#define DMAC_CH_SRC_SEL_M0 0
++#define DMAC_CH_SRC_SEL_M1 1
++
++#define DMAC_CH_DSTAD_CTL_INC 0
++#define DMAC_CH_DSTAD_CTL_DEC 1
++#define DMAC_CH_DSTAD_CTL_FIX 2
++
++#define DMAC_CH_SRCAD_CTL_INC 0
++#define DMAC_CH_SRCAD_CTL_DEC 1
++#define DMAC_CH_SRCAD_CTL_FIX 2
++
++#define DMAC_CH_MODE_HW_HANDSHAKE 1
++
++#define DMAC_CH_SRC_WIDTH_8_BITS 0
++#define DMAC_CH_SRC_WIDTH_16_BITS 1
++#define DMAC_CH_SRC_WIDTH_32_BITS 2
++
++#define DMAC_CH_DST_WIDTH_8_BITS 0
++#define DMAC_CH_DST_WIDTH_16_BITS 1
++#define DMAC_CH_DST_WIDTH_32_BITS 2
++
++#define DMAC_CH_ABT_TRANSFER 1
++
++#define DMAC_CH_PROT1_PRIVILEGED_MODE 1
++#define DMAC_CH_PROT1_USER_MODE 0
++
++#define DMAC_CH_PROT2_BUFFERABLE 1
++#define DMAC_CH_PROT2_NON_BUFFERABLE 0
++
++#define DMAC_CH_PROT3_CACHEABLE 1
++#define DMAC_CH_PROT3_NON_CACHEABLE 0
++
++#define DMAC_CH_PRI_LEVEL_0 0
++#define DMAC_CH_PRI_LEVEL_1 1
++#define DMAC_CH_PRI_LEVEL_2 2
++#define DMAC_CH_PRI_LEVEL_3 3
++
++#define DMAC_CH_TC_MASK_DISABLE 0
++#define DMAC_CH_TC_MASK_ENABLE 1
++
++#define DMAC_MAX_CHANNEL_NUM (8)
++
++
++#define DMAC_CH0_ID (1 << 0)
++#define DMAC_CH1_ID (1 << 1)
++#define DMAC_CH2_ID (1 << 2)
++#define DMAC_CH3_ID (1 << 3)
++#define DMAC_CH4_ID (1 << 4)
++#define DMAC_CH5_ID (1 << 5)
++#define DMAC_CH6_ID (1 << 6)
++#define DMAC_CH7_ID (1 << 7)
++#define DMAC_CH_ID(idx) (1 << idx)
++
++#define DMAC_LITTLE_ENDIAN (0)
++#define DMAC_BIG_ENDIAN (1)
++
++/*
++ * DMAC LLP Descriptor
++ */
++typedef struct _DMAC_LLP_CONTROL_ DMAC_LLP_CONTROL_T;
++
++struct _DMAC_LLP_CONTROL_
++{
++//#if (ENDIAN_MODE == LITTLE_ENDIAN)
++#if 1
++ unsigned int tot_size : 12;//b11-0
++ unsigned int reserved_1 : 4; //b15-12
++ unsigned int dst_sel : 1; //b16
++ unsigned int src_sel : 1; //b17
++ unsigned int dstad_ctl : 2; //b19-18
++ unsigned int srcad_ctl : 2; //b21-20
++ unsigned int dst_width : 3; //b24-22
++ unsigned int src_width : 3; //b27-25
++ unsigned int tc_status_mask : 1; //b28
++ unsigned int reserved_0 : 3; //b31-29
++
++#else
++
++
++ unsigned int reserved_0 : 3; //b31-29
++ unsigned int tc_status_mask : 1; //b28
++ unsigned int src_width : 3; //b27-25
++ unsigned int dst_width : 3; //b24-22
++ unsigned int srcad_ctl : 2; //b21-20
++ unsigned int dstad_ctl : 2; //b19-18
++ unsigned int src_sel : 1; //b17
++ unsigned int dst_sel : 1; //b16
++ unsigned int reserved_1 : 4; //b15-12
++ unsigned int tot_size : 12;//b11-0
++
++
++#endif
++};
++
++
++/*
++ * DMAC LLP Descriptor object
++ */
++typedef struct _DMAC_LLP_ DMAC_LLP_T;
++struct _DMAC_LLP_
++{
++ unsigned int SrcAddr;
++
++ unsigned int DstAddr;
++
++ DMAC_LLP_T *LLP;
++
++ DMAC_LLP_CONTROL_T Ctrl_TotSize;
++};
++
++typedef struct _DMAC_HARDWARE_HANDSHAKE_OBJ_ DMAC_HARDWARE_HANDSHAKE_OBJ_T;
++struct _DMAC_HARDWARE_HANDSHAKE_OBJ_
++{
++ unsigned int src_addr; //Src address
++ unsigned int dst_addr; //Dst address
++ unsigned int src_master; //0:AHB0, 1:AHB1
++ unsigned int dst_master; //0:AHB0, 1:AHB1
++ unsigned int dstad_ctl; //0:Incr, 1:Decr, 2:Fix
++ unsigned int srcad_ctl; //0:Incr, 1:Decr, 2:Fix
++ unsigned int src_width; //0:8bits, 1:16bits, 2:32bits
++ unsigned int dst_width; //0:8bits, 1:16bits, 2:32bits
++ unsigned int transfer_bytes; //Byte Count to be transferred
++ unsigned int channel_id; //0~7 for Channel0-7 selection
++ unsigned int channel_num; //0~7
++ unsigned int target_select; //target ID
++ unsigned int src_burst_size; //number of transfer
++ unsigned int llp_addr; //LLP address
++
++ void * private_data;
++ DMAC_LLP_T* llp_head;
++};
++
++
++extern void Hal_Dmac_Configure_DMA_Handshake(DMAC_HARDWARE_HANDSHAKE_OBJ_T *dmac_obj);
++extern irqreturn_t str8100_dma_err_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs);
++//extern int str8100_i2s_init(int sampling_rate);
++extern int str8100_i2s_init(int sampling_rate,u32 i2s_sdata_width, u32 i2s_mode,
++ u32 i2s_tranfer_timing_ctrl, u32 i2s_sclk_mode);
++extern u32 Hal_Dmac_Get_Channel_Transfer_Unit_Number(u32 byte_size, u32 src_width);
++
++extern u32 I2s_Gpio_SSP_Initialise(void);
++extern void I2s_Gpio_SSP_Write(u16);
++extern void I2s_Gpio_SSP_Switch_To_Record_Data(void);
++extern void I2s_Gpio_SSP_Switcg_To_Playback_Data(void);
++
++
++#endif //#ifndef __DEMO_DMA_H__
++
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_dmac.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_dmac.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_dmac.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_dmac.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,409 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_DMAC_H_
++#define _STAR_DMAC_H_
++
++
++#include "star_sys_memory_map.h"
++
++
++#if defined(__UBOOT__)
++#define DMAC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_GDMAC_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define DMAC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_GDMAC_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define DMAC_INT_STATUS_REG DMAC_MEM_MAP_VALUE(0x000)
++
++#define DMAC_INT_TC_STATUS_REG DMAC_MEM_MAP_VALUE(0x004)
++#define DMAC_INT_TC_STATUS_CLR_REG DMAC_MEM_MAP_VALUE(0x008)
++
++#define DMAC_INT_ERR_STATUS_REG DMAC_MEM_MAP_VALUE(0x00C)
++#define DMAC_INT_ERR_STATUS_CLR_REG DMAC_MEM_MAP_VALUE(0x010)
++
++#define DMAC_TC_STATUS_REG DMAC_MEM_MAP_VALUE(0x014)
++#define DMAC_ERR_STATUS_REG DMAC_MEM_MAP_VALUE(0x018)
++
++#define DMAC_CH_ENABLE_STATUS_REG DMAC_MEM_MAP_VALUE(0x01C)
++#define DMAC_CH_BUSY_STATUS_REG DMAC_MEM_MAP_VALUE(0x020)
++
++#define DMAC_CSR_REG DMAC_MEM_MAP_VALUE(0x024)
++#define DMAC_SYNC_REG DMAC_MEM_MAP_VALUE(0x028)
++
++#define DMAC_CH0_CSR_REG DMAC_MEM_MAP_VALUE(0x100)
++#define DMAC_CH0_CFG_REG DMAC_MEM_MAP_VALUE(0x104)
++#define DMAC_CH0_SRC_ADDR_REG DMAC_MEM_MAP_VALUE(0x108)
++#define DMAC_CH0_DST_ADDR_REG DMAC_MEM_MAP_VALUE(0x10C)
++#define DMAC_CH0_LLP_REG DMAC_MEM_MAP_VALUE(0x110)
++#define DMAC_CH0_SIZE_REG DMAC_MEM_MAP_VALUE(0x114)
++
++#define DMAC_CH1_CSR_REG DMAC_MEM_MAP_VALUE(0x120)
++#define DMAC_CH1_CFG_REG DMAC_MEM_MAP_VALUE(0x124)
++#define DMAC_CH1_SRC_ADDR_REG DMAC_MEM_MAP_VALUE(0x128)
++#define DMAC_CH1_DST_ADDR_REG DMAC_MEM_MAP_VALUE(0x12C)
++#define DMAC_CH1_LLP_REG DMAC_MEM_MAP_VALUE(0x130)
++#define DMAC_CH1_SIZE_REG DMAC_MEM_MAP_VALUE(0x134)
++
++#define DMAC_CH2_CSR_REG DMAC_MEM_MAP_VALUE(0x140)
++#define DMAC_CH2_CFG_REG DMAC_MEM_MAP_VALUE(0x144)
++#define DMAC_CH2_SRC_ADDR_REG DMAC_MEM_MAP_VALUE(0x148)
++#define DMAC_CH2_DST_ADDR_REG DMAC_MEM_MAP_VALUE(0x14C)
++#define DMAC_CH2_LLP_REG DMAC_MEM_MAP_VALUE(0x150)
++#define DMAC_CH2_SIZE_REG DMAC_MEM_MAP_VALUE(0x154)
++
++#define DMAC_CH3_CSR_REG DMAC_MEM_MAP_VALUE(0x160)
++#define DMAC_CH3_CFG_REG DMAC_MEM_MAP_VALUE(0x164)
++#define DMAC_CH3_SRC_ADDR_REG DMAC_MEM_MAP_VALUE(0x168)
++#define DMAC_CH3_DST_ADDR_REG DMAC_MEM_MAP_VALUE(0x16C)
++#define DMAC_CH3_LLP_REG DMAC_MEM_MAP_VALUE(0x170)
++#define DMAC_CH3_SIZE_REG DMAC_MEM_MAP_VALUE(0x174)
++
++#define DMAC_CH4_CSR_REG DMAC_MEM_MAP_VALUE(0x180)
++#define DMAC_CH4_CFG_REG DMAC_MEM_MAP_VALUE(0x184)
++#define DMAC_CH4_SRC_ADDR_REG DMAC_MEM_MAP_VALUE(0x188)
++#define DMAC_CH4_DST_ADDR_REG DMAC_MEM_MAP_VALUE(0x18C)
++#define DMAC_CH4_LLP_REG DMAC_MEM_MAP_VALUE(0x190)
++#define DMAC_CH4_SIZE_REG DMAC_MEM_MAP_VALUE(0x194)
++
++#define DMAC_CH5_CSR_REG DMAC_MEM_MAP_VALUE(0x1A0)
++#define DMAC_CH5_CFG_REG DMAC_MEM_MAP_VALUE(0x1A4)
++#define DMAC_CH5_SRC_ADDR_REG DMAC_MEM_MAP_VALUE(0x1A8)
++#define DMAC_CH5_DST_ADDR_REG DMAC_MEM_MAP_VALUE(0x1AC)
++#define DMAC_CH5_LLP_REG DMAC_MEM_MAP_VALUE(0x1B0)
++#define DMAC_CH5_SIZE_REG DMAC_MEM_MAP_VALUE(0x1B4)
++
++#define DMAC_CH6_CSR_REG DMAC_MEM_MAP_VALUE(0x1C0)
++#define DMAC_CH6_CFG_REG DMAC_MEM_MAP_VALUE(0x1C4)
++#define DMAC_CH6_SRC_ADDR_REG DMAC_MEM_MAP_VALUE(0x1C8)
++#define DMAC_CH6_DST_ADDR_REG DMAC_MEM_MAP_VALUE(0x1CC)
++#define DMAC_CH6_LLP_REG DMAC_MEM_MAP_VALUE(0x1D0)
++#define DMAC_CH6_SIZE_REG DMAC_MEM_MAP_VALUE(0x1D4)
++
++#define DMAC_CH7_CSR_REG DMAC_MEM_MAP_VALUE(0x1E0)
++#define DMAC_CH7_CFG_REG DMAC_MEM_MAP_VALUE(0x1E4)
++#define DMAC_CH7_SRC_ADDR_REG DMAC_MEM_MAP_VALUE(0x1E8)
++#define DMAC_CH7_DST_ADDR_REG DMAC_MEM_MAP_VALUE(0x1EC)
++#define DMAC_CH7_LLP_REG DMAC_MEM_MAP_VALUE(0x1F0)
++#define DMAC_CH7_SIZE_REG DMAC_MEM_MAP_VALUE(0x1F4)
++
++
++#define DMAC_CH0_INT_BIT_INDEX 0
++#define DMAC_CH1_INT_BIT_INDEX 1
++#define DMAC_CH2_INT_BIT_INDEX 2
++#define DMAC_CH3_INT_BIT_INDEX 3
++#define DMAC_CH4_INT_BIT_INDEX 4
++#define DMAC_CH5_INT_BIT_INDEX 5
++#define DMAC_CH6_INT_BIT_INDEX 6
++#define DMAC_CH7_INT_BIT_INDEX 7
++
++#define DMAC_CH0_INT_TC_BIT_INDEX 0
++#define DMAC_CH1_INT_TC_BIT_INDEX 1
++#define DMAC_CH2_INT_TC_BIT_INDEX 2
++#define DMAC_CH3_INT_TC_BIT_INDEX 3
++#define DMAC_CH4_INT_TC_BIT_INDEX 4
++#define DMAC_CH5_INT_TC_BIT_INDEX 5
++#define DMAC_CH6_INT_TC_BIT_INDEX 6
++#define DMAC_CH7_INT_TC_BIT_INDEX 7
++
++#define DMAC_CH0_INT_TC_CLR_BIT_INDEX 0
++#define DMAC_CH1_INT_TC_CLR_BIT_INDEX 1
++#define DMAC_CH2_INT_TC_CLR_BIT_INDEX 2
++#define DMAC_CH3_INT_TC_CLR_BIT_INDEX 3
++#define DMAC_CH4_INT_TC_CLR_BIT_INDEX 4
++#define DMAC_CH5_INT_TC_CLR_BIT_INDEX 5
++#define DMAC_CH6_INT_TC_CLR_BIT_INDEX 6
++#define DMAC_CH7_INT_TC_CLR_BIT_INDEX 7
++
++#define DMAC_CH0_INT_ERR_BIT_INDEX 0
++#define DMAC_CH1_INT_ERR_BIT_INDEX 1
++#define DMAC_CH2_INT_ERR_BIT_INDEX 2
++#define DMAC_CH3_INT_ERR_BIT_INDEX 3
++#define DMAC_CH4_INT_ERR_BIT_INDEX 4
++#define DMAC_CH5_INT_ERR_BIT_INDEX 5
++#define DMAC_CH6_INT_ERR_BIT_INDEX 6
++#define DMAC_CH7_INT_ERR_BIT_INDEX 7
++
++#define DMAC_CH0_INT_ERR_CLR_BIT_INDEX 0
++#define DMAC_CH1_INT_ERR_CLR_BIT_INDEX 1
++#define DMAC_CH2_INT_ERR_CLR_BIT_INDEX 2
++#define DMAC_CH3_INT_ERR_CLR_BIT_INDEX 3
++#define DMAC_CH4_INT_ERR_CLR_BIT_INDEX 4
++#define DMAC_CH5_INT_ERR_CLR_BIT_INDEX 5
++#define DMAC_CH6_INT_ERR_CLR_BIT_INDEX 6
++#define DMAC_CH7_INT_ERR_CLR_BIT_INDEX 7
++
++#define DMAC_CH0_TC_STATUS_BIT_INDEX 0
++#define DMAC_CH1_TC_STATUS_BIT_INDEX 1
++#define DMAC_CH2_TC_STATUS_BIT_INDEX 2
++#define DMAC_CH3_TC_STATUS_BIT_INDEX 3
++#define DMAC_CH4_TC_STATUS_BIT_INDEX 4
++#define DMAC_CH5_TC_STATUS_BIT_INDEX 5
++#define DMAC_CH6_TC_STATUS_BIT_INDEX 6
++#define DMAC_CH7_TC_STATUS_BIT_INDEX 7
++
++#define DMAC_CH0_ERR_STATUS_BIT_INDEX 0
++#define DMAC_CH1_ERR_STATUS_BIT_INDEX 1
++#define DMAC_CH2_ERR_STATUS_BIT_INDEX 2
++#define DMAC_CH3_ERR_STATUS_BIT_INDEX 3
++#define DMAC_CH4_ERR_STATUS_BIT_INDEX 4
++#define DMAC_CH5_ERR_STATUS_BIT_INDEX 5
++#define DMAC_CH6_ERR_STATUS_BIT_INDEX 6
++#define DMAC_CH7_ERR_STATUS_BIT_INDEX 7
++
++#define DMAC_CH0_ENABLE_STATUS_BIT_INDEX 0
++#define DMAC_CH1_ENABLE_STATUS_BIT_INDEX 1
++#define DMAC_CH2_ENABLE_STATUS_BIT_INDEX 2
++#define DMAC_CH3_ENABLE_STATUS_BIT_INDEX 3
++#define DMAC_CH4_ENABLE_STATUS_BIT_INDEX 4
++#define DMAC_CH5_ENABLE_STATUS_BIT_INDEX 5
++#define DMAC_CH6_ENABLE_STATUS_BIT_INDEX 6
++#define DMAC_CH7_ENABLE_STATUS_BIT_INDEX 7
++
++#define DMAC_CH0_BUSY_STATUS_BIT_INDEX 0
++#define DMAC_CH1_BUSY_STATUS_BIT_INDEX 1
++#define DMAC_CH2_BUSY_STATUS_BIT_INDEX 2
++#define DMAC_CH3_BUSY_STATUS_BIT_INDEX 3
++#define DMAC_CH4_BUSY_STATUS_BIT_INDEX 4
++#define DMAC_CH5_BUSY_STATUS_BIT_INDEX 5
++#define DMAC_CH6_BUSY_STATUS_BIT_INDEX 6
++#define DMAC_CH7_BUSY_STATUS_BIT_INDEX 7
++
++#define DMAC_ENABLE_BIT_INDEX 0
++#define DMAC_MASTER0_ENDIAN_BIT_INDEX 1
++#define DMAC_MASTER1_ENDIAN_BIT_INDEX 2
++
++#define DMAC_CH0_SYNC_ENABLE_BIT_INDEX 0
++#define DMAC_CH1_SYNC_ENABLE_BIT_INDEX 1
++#define DMAC_CH2_SYNC_ENABLE_BIT_INDEX 2
++#define DMAC_CH3_SYNC_ENABLE_BIT_INDEX 3
++#define DMAC_CH4_SYNC_ENABLE_BIT_INDEX 4
++#define DMAC_CH5_SYNC_ENABLE_BIT_INDEX 5
++#define DMAC_CH6_SYNC_ENABLE_BIT_INDEX 6
++#define DMAC_CH7_SYNC_ENABLE_BIT_INDEX 7
++
++#define DMAC_CH_INT_TC_MASK_BIT_INDEX 0
++#define DMAC_CH_INT_ERR_MASK_BIT_INDEX 1
++#define DMAC_CH_INT_ABT_MASK_BIT_INDEX 2
++#define DMAC_CH_BUSY_BIT_INDEX 8
++
++#define DMAC_CH_ENABLE_BIT_INDEX 0
++#define DMAC_CH_DST_SEL_BIT_INDEX 1
++#define DMAC_CH_SRC_SEL_BIT_INDEX 2
++#define DMAC_CH_DST_ADDR_CTL_BIT_INDEX 3
++#define DMAC_CH_SRC_ADDR_CTL_BIT_INDEX 5
++#define DMAC_CH_MODE_BIT_INDEX 7
++#define DMAC_CH_DST_WIDTH_BIT_INDEX 8
++#define DMAC_CH_SRC_WIDTH_BIT_INDEX 11
++#define DMAC_CH_ABT_BIT_INDEX 15
++#define DMAC_CH_SRC_BURST_SIZE_BIT_INDEX 16
++#define DMAC_CH_PROTECT_MODE_BIT_INDEX 19
++#define DMAC_CH_PROTECT_BUFFERABLE_BIT_INDEX 20
++#define DMAC_CH_PROTECT_CACHEABLE_BIT_INDEX 21
++#define DMAC_CH_PRIORITY_BIT_INDEX 22
++#define DMAC_CH_HHST_SEL_BIT_INDEX 25
++
++#define DMAC_CH_DST_ADDR_CTL_MASK 0x3
++#define DMAC_CH_DST_ADDR_CTL_INC 0x0
++#define DMAC_CH_DST_ADDR_CTL_DEC 0x1
++#define DMAC_CH_DST_ADDR_CTL_FIXED 0x2
++
++#define DMAC_CH_SRC_ADDR_CTL_MASK 0x3
++#define DMAC_CH_SRC_ADDR_CTL_INC 0x0
++#define DMAC_CH_SRC_ADDR_CTL_DEC 0x1
++#define DMAC_CH_SRC_ADDR_CTL_FIXED 0x2
++
++#define DMAC_CH_MODE_NORMAL 0x0
++#define DMAC_CH_MODE_HANDSHAKE 0x1
++
++#define DMAC_CH_DST_WIDTH_MASK 0x3
++#define DMAC_CH_DST_WIDTH_8BIT 0x0
++#define DMAC_CH_DST_WIDTH_16BIT 0x1
++#define DMAC_CH_DST_WIDTH_32BIT 0x2
++
++#define DMAC_CH_SRC_WIDTH_MASK 0x3
++#define DMAC_CH_SRC_WIDTH_8BIT 0x0
++#define DMAC_CH_SRC_WIDTH_16BIT 0x1
++#define DMAC_CH_SRC_WIDTH_32BIT 0x2
++
++#define DMAC_CH_SRC_BURST_SIZE_MASK 0x8
++#define DMAC_CH_SRC_BURST_SIZE_1 0x0
++#define DMAC_CH_SRC_BURST_SIZE_4 0x1
++#define DMAC_CH_SRC_BURST_SIZE_8 0x2
++#define DMAC_CH_SRC_BURST_SIZE_16 0x3
++#define DMAC_CH_SRC_BURST_SIZE_32 0x4
++#define DMAC_CH_SRC_BURST_SIZE_64 0x5
++#define DMAC_CH_SRC_BURST_SIZE_128 0x6
++#define DMAC_CH_SRC_BURST_SIZE_256 0x7
++
++#define DMAC_CH_PRIORITY_MASK 0x4
++#define DMAC_CH_PRIORITY_0 0x0 /* lowest priority */
++#define DMAC_CH_PRIORITY_1 0x1
++#define DMAC_CH_PRIORITY_2 0x2
++#define DMAC_CH_PRIORITY_3 0x3 /* highest priority */
++
++
++#define DMAC_CH_CSR_REG(idx) DMAC_MEM_MAP_VALUE(0x100+0x20*(idx))
++#define DMAC_CH_CFG_REG(idx) DMAC_MEM_MAP_VALUE(0x104+0x20*(idx))
++#define DMAC_CH_SRC_ADDR_REG(idx) DMAC_MEM_MAP_VALUE(0x108+0x20*(idx))
++#define DMAC_CH_DST_ADDR_REG(idx) DMAC_MEM_MAP_VALUE(0x10C+0x20*(idx))
++#define DMAC_CH_LLP_REG(idx) DMAC_MEM_MAP_VALUE(0x110+0x20*(idx))
++#define DMAC_CH_SIZE_REG(idx) DMAC_MEM_MAP_VALUE(0x114+0x20*(idx))
++
++
++#define HAL_DMAC_ENABLE_CHANNEL(idx) ((DMAC_CH_CSR_REG(idx)) |= (0x1))
++
++#define HAL_DMAC_DISABLE_CHANNEL(idx) ((DMAC_CH_CSR_REG(idx)) &= ~(0x1))
++
++#define HAL_GET_DMAC_CHANNEL_LLP_COUNTER(ch) ((DMAC_CH_CFG_REG(ch) >> 16) & 0xF)
++
++
++/*DMAC HW Hand-shake target ID*/
++#define DMAC_HW_HAND_SHAKE_PCM_TX0_ID 0x0
++#define DMAC_HW_HAND_SHAKE_PCM_RX0_ID 0x1
++
++#define DMAC_HW_HAND_SHAKE_SPI_TX_ID 0x2
++#define DMAC_HW_HAND_SHAKE_SPI_RX_ID 0x3
++
++#define DMAC_HW_HAND_SHAKE_I2S_TX_LEFT_ID 0x4
++#define DMAC_HW_HAND_SHAKE_I2S_TX_RIGHT_ID 0x5
++
++#define DMAC_HW_HAND_SHAKE_UART0_TX_ID 0x6
++#define DMAC_HW_HAND_SHAKE_UART0_RX_ID 0x7
++
++#define DMAC_HW_HAND_SHAKE_UART1_TX_ID 0x8
++#define DMAC_HW_HAND_SHAKE_UART1_RX_ID 0x9
++
++#define DMAC_HW_HAND_SHAKE_USBDEV_ID 0xA
++
++#define DMAC_HW_HAND_SHAKE_I2S_RX_LEFT_ID 0xB
++#define DMAC_HW_HAND_SHAKE_I2S_RX_RIGHT_ID 0xC
++
++#define DMAC_HW_HAND_SHAKE_PCM_TX1_ID 0xD
++#define DMAC_HW_HAND_SHAKE_PCM_RX1_ID 0xE
++
++
++#define MAX_DMA_VEC 32
++
++#define DMAC_DST_SEL_MASTER0 0
++#define DMAC_DST_SEL_MASTER1 1
++#define DMAC_SRC_SEL_MASTER0 0
++#define DMAC_SRC_SEL_MASTER1 1
++
++#define DMAC_RESPONSE_OK 0
++#define DMAC_RESPONSE_ERR -1
++
++struct dma_xfer;
++typedef struct dma_xfer dma_xfer_t;
++typedef void (*dma_end_io_t)(dma_xfer_t *dma_xfer, int err);
++typedef struct
++{
++ u32 src_addr; // virtual addr
++ u32 dst_addr; // virtual addr
++ u32 size; // bytes
++ u8 dst_sel;
++ u8 src_sel;
++ u8 dst_addr_ctl;
++ u8 src_addr_ctl;
++ u8 dst_width;
++ u8 src_width;
++} dma_vec_t;
++
++struct dma_xfer
++{
++ u8 nr_vec;
++ dma_vec_t vec[MAX_DMA_VEC];
++ dma_end_io_t dma_end_io;
++ void *private;
++};
++
++/*
++ * DMAC LLP Descriptor
++ */
++typedef struct
++{
++ u32 src_addr; // physical addr
++ u32 dst_addr; // physical addr
++ u32 llp;
++ u32 tot_size : 12;
++ u32 reserved0 : 4;
++ u32 dst_sel : 1;
++ u32 src_sel : 1;
++ u32 dst_addr_ctl : 2;
++ u32 src_addr_ctl : 2;
++ u32 dst_width : 3;
++ u32 src_width : 3;
++ u32 tc_mask : 1;
++ u32 reserved1 : 3;
++} __attribute__((packed)) dma_llp_descr_t;
++
++#define HAL_DMAC_ENABLE() \
++ ((DMAC_CSR_REG) |= (1<<DMAC_ENABLE_BIT_INDEX))
++
++
++#define HAL_DMAC_DISABLE() \
++ ((DMAC_CSR_REG) &= ~(1<<DMAC_ENABLE_BIT_INDEX))
++
++
++#define HAL_DMAC_SET_MASTER0_BIG_ENDIAN() \
++ ((DMAC_CSR_REG) |= (1<<DMAC_MASTER0_ENDIAN_BIT_INDEX))
++
++
++#define HAL_DMAC_SET_MASTER0_LITTLE_ENDIAN() \
++ ((DMAC_CSR_REG) &= ~(1<<DMAC_MASTER0_ENDIAN_BIT_INDEX))
++
++
++#define HAL_DMAC_SET_MASTER1_BIG_ENDIAN() \
++ ((DMAC_CSR_REG) |= (1<<DMAC_MASTER1_ENDIAN_BIT_INDEX))
++
++
++#define HAL_DMAC_SET_MASTER1_LITTLE_ENDIAN() \
++ ((DMAC_CSR_REG) &= ~(1<<DMAC_MASTER1_ENDIAN_BIT_INDEX))
++
++#define HAL_DMAC_READ_ERROR_ABORT_INTERRUPT_STATUS(err_abt_status) \
++ ((err_abt_status) = (DMAC_INT_ERR_STATUS_REG))
++
++
++#define HAL_DMAC_CLEAR_ERROR_ABORT_INTERRUPT_STATUS(err_abt_status) \
++ ((DMAC_INT_ERR_STATUS_CLR_REG) = (err_abt_status))
++
++
++#define HAL_DMAC_READ_TERMINAL_COUNT_INTERRUPT_STATUS(tc_status) \
++ ((tc_status) = (DMAC_INT_TC_STATUS_REG) & 0xFF)
++
++
++#define HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(tc_status) \
++ ((DMAC_INT_TC_STATUS_CLR_REG) = (tc_status) & 0xFF)
++
++
++
++
++
++
++#endif // end of #ifndef _STAR_DMAC_H_
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_gpio.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_gpio.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_gpio.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_gpio.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,327 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_GPIO_H_
++#define _STAR_GPIO_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define GPIOA_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_GPIOA_BASE_ADDR + reg_offset)))
++#define GPIOB_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_GPIOB_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define GPIOA_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_GPIOA_BASE_ADDR + reg_offset)))
++#define GPIOB_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_GPIOB_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * For GPIO Set A
++ */
++#define GPIOA_DATA_OUTPUT_REG GPIOA_MEM_MAP_VALUE(0x00)
++#define GPIOA_DATA_INPUT_REG GPIOA_MEM_MAP_VALUE(0x04)
++#define GPIOA_DIRECTION_REG GPIOA_MEM_MAP_VALUE(0x08)
++
++#define GPIOA_DATA_BIT_SET_REG GPIOA_MEM_MAP_VALUE(0x10)
++#define GPIOA_DATA_BIT_CLEAR_REG GPIOA_MEM_MAP_VALUE(0x14)
++
++#define GPIOA_INTERRUPT_ENABLE_REG GPIOA_MEM_MAP_VALUE(0x20)
++#define GPIOA_INTERRUPT_RAW_STATUS_REG GPIOA_MEM_MAP_VALUE(0x24)
++#define GPIOA_INTERRUPT_MASKED_STATUS_REG GPIOA_MEM_MAP_VALUE(0x28)
++#define GPIOA_INTERRUPT_MASK_REG GPIOA_MEM_MAP_VALUE(0x2C)
++#define GPIOA_INTERRUPT_CLEAR_REG GPIOA_MEM_MAP_VALUE(0x30)
++#define GPIOA_INTERRUPT_TRIGGER_METHOD_REG GPIOA_MEM_MAP_VALUE(0x34)
++#define GPIOA_INTERRUPT_TRIGGER_BOTH_EDGES_REG GPIOA_MEM_MAP_VALUE(0x38)
++#define GPIOA_INTERRUPT_TRIGGER_TYPE_REG GPIOA_MEM_MAP_VALUE(0x3C)
++
++#define GPIOA_BOUNCE_ENABLE_REG GPIOA_MEM_MAP_VALUE(0x40)
++#define GPIOA_BOUNCE_CLOCK_PRESCALE_REG GPIOA_MEM_MAP_VALUE(0x44)
++
++
++/*
++ * For GPIO Set B
++ */
++#define GPIOB_DATA_OUTPUT_REG GPIOB_MEM_MAP_VALUE(0x00)
++#define GPIOB_DATA_INPUT_REG GPIOB_MEM_MAP_VALUE(0x04)
++#define GPIOB_DIRECTION_REG GPIOB_MEM_MAP_VALUE(0x08)
++
++#define GPIOB_DATA_BIT_SET_REG GPIOB_MEM_MAP_VALUE(0x10)
++#define GPIOB_DATA_BIT_CLEAR_REG GPIOB_MEM_MAP_VALUE(0x14)
++
++#define GPIOB_INTERRUPT_ENABLE_REG GPIOB_MEM_MAP_VALUE(0x20)
++#define GPIOB_INTERRUPT_RAW_STATUS_REG GPIOB_MEM_MAP_VALUE(0x24)
++#define GPIOB_INTERRUPT_MASKED_STATUS_REG GPIOB_MEM_MAP_VALUE(0x28)
++#define GPIOB_INTERRUPT_MASK_REG GPIOB_MEM_MAP_VALUE(0x2C)
++#define GPIOB_INTERRUPT_CLEAR_REG GPIOB_MEM_MAP_VALUE(0x30)
++#define GPIOB_INTERRUPT_TRIGGER_METHOD_REG GPIOB_MEM_MAP_VALUE(0x34)
++#define GPIOB_INTERRUPT_TRIGGER_BOTH_EDGES_REG GPIOB_MEM_MAP_VALUE(0x38)
++#define GPIOB_INTERRUPT_TRIGGER_TYPE_REG GPIOB_MEM_MAP_VALUE(0x3C)
++
++#define GPIOB_BOUNCE_ENABLE_REG GPIOB_MEM_MAP_VALUE(0x40)
++#define GPIOB_BOUNCE_CLOCK_PRESCALE_REG GPIOB_MEM_MAP_VALUE(0x44)
++
++
++/*
++ * define constant macros
++ */
++
++#define MAX_GPIO_PINS (32)
++
++#define GPIO_0_MASK (1 << 0)
++#define GPIO_1_MASK (1 << 1)
++#define GPIO_2_MASK (1 << 2)
++#define GPIO_3_MASK (1 << 3)
++#define GPIO_4_MASK (1 << 4)
++#define GPIO_5_MASK (1 << 5)
++#define GPIO_6_MASK (1 << 6)
++#define GPIO_7_MASK (1 << 7)
++#define GPIO_8_MASK (1 << 8)
++#define GPIO_9_MASK (1 << 9)
++#define GPIO_10_MASK (1 << 10)
++#define GPIO_11_MASK (1 << 11)
++#define GPIO_12_MASK (1 << 12)
++#define GPIO_13_MASK (1 << 13)
++#define GPIO_14_MASK (1 << 14)
++#define GPIO_15_MASK (1 << 15)
++#define GPIO_16_MASK (1 << 16)
++#define GPIO_17_MASK (1 << 17)
++#define GPIO_18_MASK (1 << 18)
++#define GPIO_19_MASK (1 << 19)
++#define GPIO_20_MASK (1 << 20)
++#define GPIO_21_MASK (1 << 21)
++#define GPIO_22_MASK (1 << 22)
++#define GPIO_23_MASK (1 << 23)
++#define GPIO_24_MASK (1 << 24)
++#define GPIO_25_MASK (1 << 25)
++#define GPIO_26_MASK (1 << 26)
++#define GPIO_27_MASK (1 << 27)
++#define GPIO_28_MASK (1 << 28)
++#define GPIO_29_MASK (1 << 29)
++#define GPIO_30_MASK (1 << 30)
++#define GPIO_31_MASK (1 << 31)
++
++
++/*
++ * macro declarations for GPIO Set A
++ */
++#define HAL_GPIOA_READ_DATA_OUT_STATUS(data_out_state) \
++ ((data_out_state) = (GPIOA_DATA_OUTPUT_REG))
++
++#define HAL_GPIOA_READ_DATA_IN_STATUS(data_in_state) \
++ ((data_in_state) = (GPIOA_DATA_INPUT_REG))
++
++#define HAL_GPIOA_SET_DIRECTION_OUTPUT(gpio_index) \
++ ((GPIOA_DIRECTION_REG) |= (gpio_index))
++
++#define HAL_GPIOA_SET_DIRECTION_INPUT(gpio_index) \
++ ((GPIOA_DIRECTION_REG) &= ~(gpio_index))
++
++#define HAL_GPIOA_SET_DATA_OUT_HIGH(gpio_index) \
++ ((GPIOA_DATA_BIT_SET_REG) = (gpio_index))
++
++#define HAL_GPIOA_SET_DATA_OUT_LOW(gpio_index) \
++ ((GPIOA_DATA_BIT_CLEAR_REG) = (gpio_index))
++
++#define HAL_GPIOA_ENABLE_INTERRUPT(gpio_index) \
++ ((GPIOA_INTERRUPT_ENABLE_REG) |= (gpio_index))
++
++#define HAL_GPIOA_DISABLE_INTERRUPT(gpio_index) \
++ ((GPIOA_INTERRUPT_ENABLE_REG) &= ~(gpio_index))
++
++#define HAL_GPIOA_READ_INTERRUPT_RAW_STATUS(raw_state) \
++ ((raw_state) = (GPIOA_INTERRUPT_RAW_STATUS_REG))
++
++#define HAL_GPIOA_READ_INTERRUPT_MASKED_STATUS(masked_raw_state) \
++ ((masked_raw_state) = (GPIOA_INTERRUPT_MASKED_STATUS_REG))
++
++#define HAL_GPIOA_DISABLE_INTERRUPT_MASK(gpio_index) \
++ ((GPIOA_INTERRUPT_MASK_REG) &= ~(gpio_index))
++
++#define HAL_GPIOA_ENABLE_INTERRUPT_MASK(gpio_index) \
++ ((GPIOA_INTERRUPT_MASK_REG) |= (gpio_index))
++
++#define HAL_GPIOA_CLEAR_INTERRUPT(gpio_index) \
++ ((GPIOA_INTERRUPT_CLEAR_REG) = (gpio_index))
++
++#define HAL_GPIOA_SET_INTERRUPT_EDGE_TRIGGER_MODE(gpio_index) \
++ ((GPIOA_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index))
++
++#define HAL_GPIOA_SET_INTERRUPT_LEVEL_TRIGGER_MODE(gpio_index) \
++ ((GPIOA_INTERRUPT_TRIGGER_METHOD_REG) |= (gpio_index))
++
++#define HAL_GPIOA_SET_INTERRUPT_SINGLE_EDGE_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOA_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index)); \
++ ((GPIOA_INTERRUPT_TRIGGER_BOTH_EDGES_REG) &= ~(gpio_index)); \
++}
++
++#define HAL_GPIOA_SET_INTERRUPT_BOTH_EDGE_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOA_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index)); \
++ ((GPIOA_INTERRUPT_TRIGGER_BOTH_EDGES_REG) |= (gpio_index)); \
++}
++
++#define HAL_GPIOA_SET_INTERRUPT_SINGLE_RISING_EDGE_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOA_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index)); \
++ ((GPIOA_INTERRUPT_TRIGGER_BOTH_EDGES_REG) &= ~(gpio_index)); \
++ ((GPIOA_INTERRUPT_TRIGGER_TYPE_REG) &= ~(gpio_index)); \
++}
++
++#define HAL_GPIOA_SET_INTERRUPT_SINGLE_FALLING_EDGE_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOA_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index)); \
++ ((GPIOA_INTERRUPT_TRIGGER_BOTH_EDGES_REG) &= ~(gpio_index)); \
++ ((GPIOA_INTERRUPT_TRIGGER_TYPE_REG) |= (gpio_index)); \
++}
++
++#define HAL_GPIOA_SET_INTERRUPT_HIGH_LEVEL_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOA_INTERRUPT_TRIGGER_METHOD_REG) |= (gpio_index)); \
++ ((GPIOA_INTERRUPT_TRIGGER_TYPE_REG) &= ~(gpio_index)); \
++}
++
++#define HAL_GPIOA_SET_INTERRUPT_LOW_LEVEL_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOA_INTERRUPT_TRIGGER_METHOD_REG) |= (gpio_index)); \
++ ((GPIOA_INTERRUPT_TRIGGER_TYPE_REG) |= (gpio_index)); \
++}
++
++#define HAL_GPIOA_ENABLE_BOUNCE(gpio_index) \
++ ((GPIOA_BOUNCE_ENABLE_REG) |= (gpio_index))
++
++#define HAL_GPIOA_DISABLE_BOUNCE(gpio_index) \
++ ((GPIOA_BOUNCE_ENABLE_REG) &= ~(gpio_index))
++
++#define HAL_GPIOA_READ_BOUNCE_PRESCALE_RATIO(prescale_ratio) \
++ ((prescale_ratio) = ((GPIOA_BOUNCE_CLOCK_PRESCALE_REG) & 0x0000FFFF))
++
++#define HAL_GPIOA_WRITE_BOUNCE_PRESCALE_RATIO(prescale_ratio) \
++ ((GPIOA_BOUNCE_CLOCK_PRESCALE_REG) = (prescale_ratio & 0x0000FFFF))
++
++
++
++/*
++ * macro declarations for GPIO Set B
++ */
++#define HAL_GPIOB_READ_DATA_OUT_STATUS(data_out_state) \
++ ((data_out_state) = (GPIOB_DATA_OUTPUT_REG))
++
++#define HAL_GPIOB_READ_DATA_IN_STATUS(data_in_state) \
++ ((data_in_state) = (GPIOB_DATA_INPUT_REG))
++
++#define HAL_GPIOB_SET_DIRECTION_OUTPUT(gpio_index) \
++ ((GPIOB_DIRECTION_REG) |= (gpio_index))
++
++#define HAL_GPIOB_SET_DIRECTION_INPUT(gpio_index) \
++ ((GPIOB_DIRECTION_REG) &= ~(gpio_index))
++
++#define HAL_GPIOB_SET_DATA_OUT_HIGH(gpio_index) \
++ ((GPIOB_DATA_BIT_SET_REG) = (gpio_index))
++
++#define HAL_GPIOB_SET_DATA_OUT_LOW(gpio_index) \
++ ((GPIOB_DATA_BIT_CLEAR_REG) = (gpio_index))
++
++#define HAL_GPIOB_ENABLE_INTERRUPT(gpio_index) \
++ ((GPIOB_INTERRUPT_ENABLE_REG) |= (gpio_index))
++
++#define HAL_GPIOB_DISABLE_INTERRUPT(gpio_index) \
++ ((GPIOB_INTERRUPT_ENABLE_REG) &= ~(gpio_index))
++
++#define HAL_GPIOB_READ_INTERRUPT_RAW_STATUS(raw_state) \
++ ((raw_state) = (GPIOB_INTERRUPT_RAW_STATUS_REG))
++
++#define HAL_GPIOB_READ_INTERRUPT_MASKED_STATUS(masked_raw_state) \
++ ((masked_raw_state) = (GPIOB_INTERRUPT_MASKED_STATUS_REG))
++
++#define HAL_GPIOB_DISABLE_INTERRUPT_MASK(gpio_index) \
++ ((GPIOB_INTERRUPT_MASK_REG) &= ~(gpio_index))
++
++#define HAL_GPIOB_ENABLE_INTERRUPT_MASK(gpio_index) \
++ ((GPIOB_INTERRUPT_MASK_REG) |= (gpio_index))
++
++#define HAL_GPIOB_CLEAR_INTERRUPT(gpio_index) \
++ ((GPIOB_INTERRUPT_CLEAR_REG) = (gpio_index))
++
++#define HAL_GPIOB_SET_INTERRUPT_EDGE_TRIGGER_MODE(gpio_index) \
++ ((GPIOB_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index))
++
++#define HAL_GPIOB_SET_INTERRUPT_LEVEL_TRIGGER_MODE(gpio_index) \
++ ((GPIOB_INTERRUPT_TRIGGER_METHOD_REG) |= (gpio_index))
++
++#define HAL_GPIOB_SET_INTERRUPT_SINGLE_EDGE_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOB_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index)); \
++ ((GPIOB_INTERRUPT_TRIGGER_BOTH_EDGES_REG) &= ~(gpio_index)); \
++}
++
++#define HAL_GPIOB_SET_INTERRUPT_BOTH_EDGE_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOB_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index)); \
++ ((GPIOB_INTERRUPT_TRIGGER_BOTH_EDGES_REG) |= (gpio_index)); \
++}
++
++#define HAL_GPIOB_SET_INTERRUPT_SINGLE_RISING_EDGE_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOB_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index)); \
++ ((GPIOB_INTERRUPT_TRIGGER_BOTH_EDGES_REG) &= ~(gpio_index)); \
++ ((GPIOB_INTERRUPT_TRIGGER_TYPE_REG) &= ~(gpio_index)); \
++}
++
++#define HAL_GPIOB_SET_INTERRUPT_SINGLE_FALLING_EDGE_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOB_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index)); \
++ ((GPIOB_INTERRUPT_TRIGGER_BOTH_EDGES_REG) &= ~(gpio_index)); \
++ ((GPIOB_INTERRUPT_TRIGGER_TYPE_REG) |= (gpio_index)); \
++}
++
++#define HAL_GPIOB_SET_INTERRUPT_HIGH_LEVEL_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOB_INTERRUPT_TRIGGER_METHOD_REG) |= (gpio_index)); \
++ ((GPIOB_INTERRUPT_TRIGGER_TYPE_REG) &= ~(gpio_index)); \
++}
++
++#define HAL_GPIOB_SET_INTERRUPT_LOW_LEVEL_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOB_INTERRUPT_TRIGGER_METHOD_REG) |= (gpio_index)); \
++ ((GPIOB_INTERRUPT_TRIGGER_TYPE_REG) |= (gpio_index)); \
++}
++
++#define HAL_GPIOB_ENABLE_BOUNCE(gpio_index) \
++ ((GPIOB_BOUNCE_ENABLE_REG) |= (gpio_index))
++
++#define HAL_GPIOB_DISABLE_BOUNCE(gpio_index) \
++ ((GPIOB_BOUNCE_ENABLE_REG) &= ~(gpio_index))
++
++#define HAL_GPIOB_READ_BOUNCE_PRESCALE_RATIO(prescale_ratio) \
++ ((prescale_ratio) = ((GPIOB_BOUNCE_CLOCK_PRESCALE_REG) & 0x0000FFFF))
++
++#define HAL_GPIOB_WRITE_BOUNCE_PRESCALE_RATIO(prescale_ratio) \
++ ((GPIOB_BOUNCE_CLOCK_PRESCALE_REG) = (prescale_ratio & 0x0000FFFF))
++
++
++#endif // end of _STAR_GPIO_H_
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_hsdmac.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_hsdmac.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_hsdmac.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_hsdmac.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,106 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_HSDMAC_H_
++#define _STAR_HSDMAC_H_
++
++
++#include "star_sys_memory_map.h"
++
++
++#if defined(__UBOOT__)
++#define HSDMAC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_MISC_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define HSDMAC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_MISC_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define HSDMAC_CONTROL_STATUS_REG HSDMAC_MEM_MAP_VALUE(0x040)
++
++#define HSDMAC_MASTER0_ADDR_REG HSDMAC_MEM_MAP_VALUE(0x050)
++
++#define HSDMAC_MASTER1_ADDR_REG HSDMAC_MEM_MAP_VALUE(0x054)
++
++#define HSDMAC_LLP_REG HSDMAC_MEM_MAP_VALUE(0x058)
++
++#define HSDMAC_TOT_SIZE_REG HSDMAC_MEM_MAP_VALUE(0x05C)
++
++
++#define HAL_GET_HSDMAC_LLP_COUNTER ((HSDMAC_CONTROL_STATUS_REG >> 8) & 0xF)
++
++#define HAL_HSDMAC_ENABLE() ((HSDMAC_CONTROL_STATUS_REG) |= (0x1))
++
++#define HAL_HSDMAC_DISABLE() ((HSDMAC_CONTROL_STATUS_REG) &= ~(0x1))
++
++
++#define HSDMAC_MASTER0_TO_MASTER1 0
++#define HSDMAC_MASTER1_TO_MASTER0 1
++
++#define HSDMAC_RESPONSE_OK 0
++#define HSDMAC_RESPONSE_ERR -1
++
++#define MAX_HSDMA_VEC 32
++
++#define MAX_HSDMA_XFER_SIZE (0xFFF << 2)
++
++struct hsdma_xfer;
++typedef struct hsdma_xfer hsdma_xfer_t;
++typedef void (*hsdma_end_io_t)(hsdma_xfer_t *hsdma_xfer, int err);
++typedef struct
++{
++ u8 data_direction;
++ u32 src_addr; // virtual
++ u32 dst_addr; // virtual
++ u32 size; // bytes
++} __attribute__((packed)) hsdma_vec_t;
++
++struct hsdma_xfer
++{
++ u8 nr_vec;
++ hsdma_vec_t vec[MAX_HSDMA_VEC];
++ hsdma_end_io_t hsdma_end_io;
++ void *private;
++};
++
++/*
++ * HSDMAC LLP Descriptor object
++ */
++typedef struct
++{
++ u32 src_addr; // physical
++ u32 dst_addr; // physical
++ u32 llp;
++ u32 tot_size : 16;//b15-b0
++ u32 reserved0 : 12;//b27-b16
++ u32 tc_mask : 1; //b28
++ u32 data_direction : 1; //b29
++ u32 reserved1 : 2; //b31-30
++} __attribute__((packed)) hsdma_llp_descr_t;
++
++
++#endif // end of #ifndef _STAR_HSDMAC_H_
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_i2c.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_i2c.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_i2c.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_i2c.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,69 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_I2C_H_
++#define _STAR_I2C_H_
++
++#include <mach/star_sys_memory_map.h>
++
++#define I2C_MEM_MAP_ADDR(reg_offset) (SYSVA_I2C_BASE_ADDR + reg_offset)
++#define I2C_MEM_MAP_VALUE(reg_offset) (*((unsigned int volatile *)I2C_MEM_MAP_ADDR(reg_offset)))
++
++#define I2C_CONTROLLER_REG_ADDR I2C_MEM_MAP_ADDR(0x20)
++#define I2C_TIME_OUT_REG_ADDR I2C_MEM_MAP_ADDR(0x24)
++#define I2C_SLAVE_ADDRESS_REG_ADDR I2C_MEM_MAP_ADDR(0x28)
++#define I2C_WRITE_DATA_REG_ADDR I2C_MEM_MAP_ADDR(0x2C)
++#define I2C_READ_DATA_REG_ADDR I2C_MEM_MAP_ADDR(0x30)
++#define I2C_INTERRUPT_STATUS_REG_ADDR I2C_MEM_MAP_ADDR(0x34)
++#define I2C_INTERRUPT_ENABLE_REG_ADDR I2C_MEM_MAP_ADDR(0x38)
++
++#define I2C_CONTROLLER_REG I2C_MEM_MAP_VALUE(0x20)
++#define I2C_TIME_OUT_REG I2C_MEM_MAP_VALUE(0x24)
++#define I2C_SLAVE_ADDRESS_REG I2C_MEM_MAP_VALUE(0x28)
++#define I2C_WRITE_DATA_REG I2C_MEM_MAP_VALUE(0x2C)
++#define I2C_READ_DATA_REG I2C_MEM_MAP_VALUE(0x30)
++#define I2C_INTERRUPT_STATUS_REG I2C_MEM_MAP_VALUE(0x34)
++#define I2C_INTERRUPT_ENABLE_REG I2C_MEM_MAP_VALUE(0x38)
++
++#define I2C_READ_ONLY_CMD (0)
++#define I2C_WRITE_ONLY_CMD (1)
++#define I2C_WRITE_READ_CMD (2)
++#define I2C_READ_WRITE_CMD (3)
++
++#define I2C_DATA_LEN_1_BYTE (0)
++#define I2C_DATA_LEN_2_BYTE (1)
++#define I2C_DATA_LEN_3_BYTE (2)
++#define I2C_DATA_LEN_4_BYTE (3)
++
++#define I2C_BUS_ERROR_FLAG (0x1)
++#define I2C_ACTION_DONE_FLAG (0x2)
++
++#define HAL_I2C_ENABLE_I2C() (I2C_CONTROLLER_REG) |= ((unsigned int)0x1 << 31);
++#define HAL_I2C_DISABLE_I2C() (I2C_CONTROLLER_REG) &= ~((unsigned int)0x1 << 31);
++#define HAL_I2C_ENABLE_DATA_SWAP() (I2C_CONTROLLER_REG) |= (0x1 << 24);
++#define HAL_I2C_DISABLE_DATA_SWAP() (I2C_CONTROLLER_REG) &= ~(0x1 << 24);
++#define HAL_I2C_START_TRANSFER() (I2C_CONTROLLER_REG) |= (0x1 << 6);
++#define HAL_I2C_STOP_TRANSFER() (I2C_CONTROLLER_REG) &= ~(0x1 << 6);
++
++#endif
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_i2s.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_i2s.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_i2s.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_i2s.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,176 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_I2S_H_
++#define _STAR_I2S_H_
++
++/******************************************************************************
++ * MODULE NAME: star_i2s.h
++ * PROJECT CODE: Orion
++ * DESCRIPTION:
++ * MAINTAINER: MJLIU
++ * DATE: 15 September 2005
++ *
++ * SOURCE CONTROL:
++ *
++ * REVISION HISTORY:
++ * 15 September 2005 - MJLIU - Initial Version v1.0
++ *
++ *
++ * SOURCE:
++ * ISSUES:
++ * NOTES TO USERS:
++ ******************************************************************************/
++
++#include <mach/star_sys_memory_map.h>
++
++#define I2S_MEM_MAP_ADDR(reg_offset) (SYSVA_I2S_BASE_ADDR + reg_offset)
++#define I2S_MEM_MAP_VALUE(reg_offset) (*((unsigned int volatile *)I2S_MEM_MAP_ADDR(reg_offset)))
++
++//#define I2S_BASE_ADDR (SYS_I2S_BASE_ADDR)
++
++
++/*
++ * define access macros
++ */
++#define I2S_CONFIGURATION_REG_ADDR I2S_MEM_MAP_ADDR(0xC0)
++#define I2S_RIGHT_TRANSMIT_DATA_REG_ADDR I2S_MEM_MAP_ADDR(0xC4)
++#define I2S_LEFT_TRANSMIT_DATA_REG_ADDR I2S_MEM_MAP_ADDR(0xC8)
++#define I2S_RIGHT_RECEIVE_DATA_REG_ADDR I2S_MEM_MAP_ADDR(0xCC)
++#define I2S_LEFT_RECEIVE_DATA_REG_ADDR I2S_MEM_MAP_ADDR(0xD0)
++#define I2S_INTERRUPT_STATUS_REG_ADDR I2S_MEM_MAP_ADDR(0xD4)
++#define I2S_INTERRUPT_ENABLE_REG_ADDR I2S_MEM_MAP_ADDR(0xD8)
++
++#define I2S_CONFIGURATION_REG I2S_MEM_MAP_VALUE(0xC0)
++#define I2S_RIGHT_TRANSMIT_DATA_REG I2S_MEM_MAP_VALUE(0xC4)
++#define I2S_LEFT_TRANSMIT_DATA_REG I2S_MEM_MAP_VALUE(0xC8)
++#define I2S_RIGHT_RECEIVE_DATA_REG I2S_MEM_MAP_VALUE(0xCC)
++#define I2S_LEFT_RECEIVE_DATA_REG I2S_MEM_MAP_VALUE(0xD0)
++#define I2S_INTERRUPT_STATUS_REG I2S_MEM_MAP_VALUE(0xD4)
++#define I2S_INTERRUPT_ENABLE_REG I2S_MEM_MAP_VALUE(0xD8)
++
++
++/*
++ * define constants macros
++ */
++#define I2S_DATA_16_BIT (0)
++#define I2S_DATA_32_BIT (1)
++
++#define I2S_RXBF_R_FULL_FLAG (0x01)
++#define I2S_TXBF_R_EMPTY_FLAG (0x02)
++#define I2S_RXBF_L_FULL_FLAG (0x04)
++#define I2S_TXBF_L_EMPTY_FLAG (0x08)
++
++#define I2S_RXBF_R_OR_FLAG (0x10)
++#define I2S_TXBF_R_UR_FLAG (0x20)
++#define I2S_RXBF_L_OR_FLAG (0x40)
++#define I2S_TXBF_L_UR_FLAG (0x80)
++
++
++#define I2S_MASTER_MODE (1)
++#define I2S_SLAVE_MODE (0)
++
++#define I2S_I2S_MODE (1)
++#define I2S_RJF_MODE (2)
++#define I2S_LJF_MODE (3)
++
++#define I2S_CLOCK_CONTINUOUS_MODE (0)
++#define I2S_CLOCK_256S_MODE (1)
++
++
++#define I2S_WS_RATE_32KHZ (1) /* 8.192 MHz */
++#define I2S_WS_RATE_44_1KHZ (2) /* 11.2896 MHz */
++#define I2S_WS_RATE_48KHZ (3) /* 12.288 MHz */
++
++
++/*
++ * define data structure
++ */
++#if 0
++typedef struct _I2S_OBJECT_ I2S_OBJECT_T;
++
++struct _I2S_OBJECT_
++{
++ u_int32 config;
++ u_int32 interrupt_config;
++
++
++ /*
++ * For interrupt setting
++ */
++ INTC_OBJECT_T intc_obj;
++};
++
++
++/*
++ * function declarations
++ */
++void Hal_I2s_Initialize(I2S_OBJECT_T *);
++#endif
++
++
++/*
++ * macro declarations
++ */
++#define HAL_I2S_ENABLE_I2S() \
++{ \
++ (I2S_CONFIGURATION_REG) |= ((u32)0x1 << 31); \
++}
++
++#define HAL_I2S_DISABLE_I2S() \
++{ \
++ (I2S_CONFIGURATION_REG) &= ~((u32)0x1 << 31); \
++}
++
++#define HAL_I2S_ENABLE_DATA_SWAP() \
++{ \
++ (I2S_CONFIGURATION_REG) |= (0x1 << 24); \
++}
++
++#define HAL_I2S_DISABLE_DATA_SWAP() \
++{ \
++ (I2S_CONFIGURATION_REG) &= ~(0x1 << 24); \
++}
++
++#define HAL_I2S_DISABLE_LEFT_CHANNEL_TRANSMIT_BUFFER_UNDERRUN_INTERRUPT() \
++{ \
++ (I2S_INTERRUPT_ENABLE_REG) &= ~(I2S_TXBF_L_UR_FLAG); \
++}
++
++#define HAL_I2S_DISABLE_RIGHT_CHANNEL_TRANSMIT_BUFFER_UNDERRUN_INTERRUPT() \
++{ \
++ (I2S_INTERRUPT_ENABLE_REG) &= ~(I2S_TXBF_R_UR_FLAG); \
++}
++
++#define HAL_I2S_DISABLE_LEFT_CHANNEL_RECEIVE_BUFFER_OVERRUN_INTERRUPT() \
++{ \
++ (I2S_INTERRUPT_ENABLE_REG) &= ~(I2S_RXBF_L_OR_FLAG); \
++}
++
++#define HAL_I2S_DISABLE_RIGHT_CHANNEL_RECEIVE_BUFFER_OVERRUN_INTERRUPT() \
++{ \
++ (I2S_INTERRUPT_ENABLE_REG) &= ~(I2S_RXBF_R_OR_FLAG); \
++}
++
++
++#endif // end of #ifndef _STAR_I2S_H_
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_ide.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_ide.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_ide.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_ide.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,245 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_IDE_H_
++#define _STAR_IDE_H_
++
++
++#include "star_sys_memory_map.h"
++
++
++#if defined(__UBOOT__)
++#define IDE_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_IDE_CONTROLLER_BASE_ADDR + reg_offset)))
++#define IDE_BUS_MEM_MAP_VALUE(reg_offset) (*((u8 volatile *)(SYSPA_IDE_DEVICE_BASE_ADDR + reg_offset)))
++#define IDE_DATA_MEM_MAP_VALUE(reg_offset) (*((u16 volatile *)(SYSPA_IDE_DEVICE_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define IDE_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_IDE_CONTROLLER_BASE_ADDR + reg_offset)))
++#define IDE_BUS_MEM_MAP_VALUE(reg_offset) (*((u8 volatile *)(SYSVA_IDE_DEVICE_BASE_ADDR + reg_offset)))
++#define IDE_DATA_MEM_MAP_VALUE(reg_offset) (*((u16 volatile *)(SYSVA_IDE_DEVICE_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * IDE Controller Registers
++ */
++#define IDE_PIO_CONTROL_REG IDE_MEM_MAP_VALUE(0x00)
++#define IDE_DRIVE0_PIO_TIMING_CONFIG_REG IDE_MEM_MAP_VALUE(0x04)
++#define IDE_DRIVE1_PIO_TIMING_CONFIG_REG IDE_MEM_MAP_VALUE(0x08)
++#define IDE_DRIVE0_DMA_TIMING_CONFIG_REG IDE_MEM_MAP_VALUE(0x0C)
++#define IDE_DRIVE1_DMA_TIMING_CONFIG_REG IDE_MEM_MAP_VALUE(0x10)
++#define IDE_UDMA_TIMING_CONFIG_REG IDE_MEM_MAP_VALUE(0x14)
++#define IDE_DMA_UDMA_CONTROL_REG IDE_MEM_MAP_VALUE(0x18)
++#define IDE_STATUS_CONTROL_REG IDE_MEM_MAP_VALUE(0x1C)
++#define IDE_BUS_MASTER_DTP_REG IDE_MEM_MAP_VALUE(0x20)
++#define IDE_FAST_PATH_ACCESS_WINDOW_REG IDE_MEM_MAP_VALUE(0x24)
++#define IDE_FAST_PATH_DMA_BURST_SIZE_REG IDE_MEM_MAP_VALUE(0x28)
++
++
++/*
++ * IDE Command Block Registers
++ */
++#define _IDE_DATA_REG IDE_DATA_MEM_MAP_VALUE(0x20)
++#define _IDE_ERROR_REG IDE_BUS_MEM_MAP_VALUE(0x24)
++#define _IDE_FEATURES_REG IDE_BUS_MEM_MAP_VALUE(0x24)
++#define _IDE_SECTOR_COUNT_REG IDE_BUS_MEM_MAP_VALUE(0x28)
++#define _IDE_LBA_LOW_REG IDE_BUS_MEM_MAP_VALUE(0x2C)
++#define _IDE_LBA_MID_REG IDE_BUS_MEM_MAP_VALUE(0x30)
++#define _IDE_LBA_HIGH_REG IDE_BUS_MEM_MAP_VALUE(0x34)
++#define _IDE_DEVICE_REG IDE_BUS_MEM_MAP_VALUE(0x38)
++#define _IDE_COMMAND_REG IDE_BUS_MEM_MAP_VALUE(0x3C)
++#define _IDE_STATUS_REG IDE_BUS_MEM_MAP_VALUE(0x3C)
++
++
++/*
++ * IDE Control Block Registers
++ */
++#define IDE_DEVICE_CONTROL_REG IDE_BUS_MEM_MAP_VALUE(0x40)
++#define IDE_ALTERNATE_STATUS_REG IDE_BUS_MEM_MAP_VALUE(0x40)
++
++
++#define IDE_CD (0x01)
++#define IDE_IO (0x02)
++#define IDE_REL (0x04)
++#define IDE_OVL (0x02)
++#define IDE_BSY (0x80)
++#define IDE_DRQ (0x08)
++#define IDE_SERV (0x10)
++#define IDE_DMRD (0x20)
++#define IDE_ERR (0x01)
++#define IDE_SRST (0x04)
++
++/*
++ * macro declarations for IDE Controller
++ */
++#define HAL_IDE_DRIVE0_IORDY_SAMPLE_ENABLE() \
++{ \
++ (IDE_PIO_CONTROL_REG) |= (0x1 << 0); \
++}
++
++#define HAL_IDE_DRIVE0_IORDY_SAMPLE_DISABLE() \
++{ \
++ (IDE_PIO_CONTROL_REG) &= ~(0x1 << 0); \
++}
++
++#define HAL_IDE_DRIVE1_IORDY_SAMPLE_ENABLE() \
++{ \
++ (IDE_PIO_CONTROL_REG) |= (0x1 << 1); \
++}
++
++#define HAL_IDE_DRIVE1_IORDY_SAMPLE_DISABLE() \
++{ \
++ (IDE_PIO_CONTROL_REG) &= ~(0x1 << 1); \
++}
++
++#define HAL_IDE_DRIVE0_UDMA_ENABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) |= (0x1 << 0); \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 2); \
++}
++
++#define HAL_IDE_DRIVE0_UDMA_DISABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 0); \
++}
++
++#define HAL_IDE_DRIVE1_UDMA_ENABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) |= (0x1 << 1); \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 3); \
++}
++
++#define HAL_IDE_DRIVE1_UDMA_DISABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 1); \
++}
++
++#define HAL_IDE_DRIVE0_DMA_ENABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) |= (0x1 << 2); \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 0); \
++}
++
++#define HAL_IDE_DRIVE0_DMA_DISABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 2); \
++}
++
++#define HAL_IDE_DRIVE1_DMA_ENABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) |= (0x1 << 3); \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 1); \
++}
++
++#define HAL_IDE_TO_USB_FAST_PATH_ENABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) |= (0x1 << 4); \
++}
++
++#define HAL_IDE_TO_USB_FAST_PATH_DISABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 4); \
++}
++
++#define HAL_IDE_DRIVE1_DMA_DISABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 3); \
++}
++
++#define HAL_IDE_DMA_UDMA_START() \
++{ \
++ (IDE_STATUS_CONTROL_REG) |= (0x1); \
++}
++
++#define HAL_IDE_DMA_UDMA_STOP() \
++{ \
++ (IDE_STATUS_CONTROL_REG) &= ~(0x1); \
++}
++
++#define HAL_IDE_CLEAR_PRD_INTERRUPT_STATUS() \
++{ \
++ (IDE_STATUS_CONTROL_REG) |= (0x1 << 2); \
++}
++
++#define HAL_IDE_CLEAR_INTRQ_INTERRUPT_STATUS() \
++{ \
++ (IDE_STATUS_CONTROL_REG) |= (0x1 << 1); \
++}
++
++#define HAL_IDE_HOST_TRANSFER_WRITE_OUT() \
++{ \
++ (IDE_STATUS_CONTROL_REG) |= (0x1 << 3); \
++}
++
++#define HAL_IDE_HOST_TRANSFER_READ_IN() \
++{ \
++ (IDE_STATUS_CONTROL_REG) &= ~(0x1 << 3); \
++}
++
++#define HAL_IDE_MASK_PRD_INTERRUPT() \
++{ \
++ (IDE_STATUS_CONTROL_REG) |= (0x1 << 6); \
++}
++
++#define HAL_IDE_UNMASK_PRD_INTERRUPT() \
++{ \
++ (IDE_STATUS_CONTROL_REG) &= ~(0x1 << 6); \
++}
++
++#define HAL_IDE_SET_DESCRIPTOR_TABLE_POINTER(dtp) \
++{ \
++ (IDE_BUS_MASTER_DTP_REG) = (dtp); \
++}
++
++#define HAL_IDE_SET_FAST_PATH_ACCESS_WINDOW(fp_access_window) \
++{ \
++ (IDE_FAST_PATH_ACCESS_WINDOW_REG) = (fp_access_window); \
++}
++
++/*
++ * macro declarations for IDE Device
++ */
++#define HAL_IDE_SELECT_DEVICE_0() \
++{ \
++ (_IDE_DEVICE_REG) = 0; \
++}
++
++#define HAL_IDE_SELECT_DEVICE_1() \
++{ \
++ (_IDE_DEVICE_REG) = (0x1 << 4); \
++}
++
++#define HAL_IDE_ENABLE_DEVICE_INTRQ() \
++{ \
++ (IDE_DEVICE_CONTROL_REG) = (0); \
++}
++
++#define HAL_IDE_DISABLE_DEVICE_INTRQ() \
++{ \
++ (IDE_DEVICE_CONTROL_REG) = (0x2); \
++}
++
++
++#endif // end of #ifndef _STAR_IDE_H_
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_intc.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_intc.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_intc.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_intc.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,328 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_INTC_H_
++#define _STAR_INTC_H_
++
++
++//#include <mach/star_sys_memory_map.h>
++#include <mach/star_sys_memory_map.h>
++
++#if defined(__UBOOT__)
++#define INTC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_VIC_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define INTC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_VIC_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define INTC_INTERRUPT_RAW_STATUS_REG INTC_MEM_MAP_VALUE(0x000)
++#define INTC_EDGE_INTERRUPT_SOURCE_CLEAR_REG INTC_MEM_MAP_VALUE(0x004)
++#define INTC_INTERRUPT_MASK_REG INTC_MEM_MAP_VALUE(0x008)
++#define INTC_INTERRUPT_MASK_CLEAR_REG INTC_MEM_MAP_VALUE(0x00C)
++#define INTC_INTERRUPT_TRIGGER_MODE_REG INTC_MEM_MAP_VALUE(0x010)
++#define INTC_INTERRUPT_TRIGGER_LEVEL_REG INTC_MEM_MAP_VALUE(0x014)
++#define INTC_FIQ_SELECT_REG INTC_MEM_MAP_VALUE(0x018)
++#define INTC_IRQ_STATUS_REG INTC_MEM_MAP_VALUE(0x01C)
++#define INTC_FIQ_STATUS_REG INTC_MEM_MAP_VALUE(0x020)
++#define INTC_SOFTWARE_INTERRUPT_REG INTC_MEM_MAP_VALUE(0x024)
++#define INTC_SOFTWARE_INTERRUPT_CLEAR_REG INTC_MEM_MAP_VALUE(0x028)
++#define INTC_SOFTWARE_PRIORITY_MASK_REG INTC_MEM_MAP_VALUE(0x02C)
++#define INTC_POWER_MANAGEMENT_INTERRUPT_REG INTC_MEM_MAP_VALUE(0x034)
++
++#define INTC_VECTOR_ADDRESS_0_REG INTC_MEM_MAP_VALUE(0x040)
++#define INTC_VECTOR_ADDRESS_1_REG INTC_MEM_MAP_VALUE(0x044)
++#define INTC_VECTOR_ADDRESS_2_REG INTC_MEM_MAP_VALUE(0x048)
++#define INTC_VECTOR_ADDRESS_3_REG INTC_MEM_MAP_VALUE(0x04C)
++#define INTC_VECTOR_ADDRESS_4_REG INTC_MEM_MAP_VALUE(0x050)
++#define INTC_VECTOR_ADDRESS_5_REG INTC_MEM_MAP_VALUE(0x054)
++#define INTC_VECTOR_ADDRESS_6_REG INTC_MEM_MAP_VALUE(0x058)
++#define INTC_VECTOR_ADDRESS_7_REG INTC_MEM_MAP_VALUE(0x05C)
++#define INTC_VECTOR_ADDRESS_8_REG INTC_MEM_MAP_VALUE(0x060)
++#define INTC_VECTOR_ADDRESS_9_REG INTC_MEM_MAP_VALUE(0x064)
++#define INTC_VECTOR_ADDRESS_10_REG INTC_MEM_MAP_VALUE(0x068)
++#define INTC_VECTOR_ADDRESS_11_REG INTC_MEM_MAP_VALUE(0x06C)
++#define INTC_VECTOR_ADDRESS_12_REG INTC_MEM_MAP_VALUE(0x070)
++#define INTC_VECTOR_ADDRESS_13_REG INTC_MEM_MAP_VALUE(0x074)
++#define INTC_VECTOR_ADDRESS_14_REG INTC_MEM_MAP_VALUE(0x078)
++#define INTC_VECTOR_ADDRESS_15_REG INTC_MEM_MAP_VALUE(0x07C)
++#define INTC_VECTOR_ADDRESS_16_REG INTC_MEM_MAP_VALUE(0x080)
++#define INTC_VECTOR_ADDRESS_17_REG INTC_MEM_MAP_VALUE(0x084)
++#define INTC_VECTOR_ADDRESS_18_REG INTC_MEM_MAP_VALUE(0x088)
++#define INTC_VECTOR_ADDRESS_19_REG INTC_MEM_MAP_VALUE(0x08C)
++#define INTC_VECTOR_ADDRESS_20_REG INTC_MEM_MAP_VALUE(0x090)
++#define INTC_VECTOR_ADDRESS_21_REG INTC_MEM_MAP_VALUE(0x094)
++#define INTC_VECTOR_ADDRESS_22_REG INTC_MEM_MAP_VALUE(0x098)
++#define INTC_VECTOR_ADDRESS_23_REG INTC_MEM_MAP_VALUE(0x09C)
++#define INTC_VECTOR_ADDRESS_24_REG INTC_MEM_MAP_VALUE(0x0A0)
++#define INTC_VECTOR_ADDRESS_25_REG INTC_MEM_MAP_VALUE(0x0A4)
++#define INTC_VECTOR_ADDRESS_26_REG INTC_MEM_MAP_VALUE(0x0A8)
++#define INTC_VECTOR_ADDRESS_27_REG INTC_MEM_MAP_VALUE(0x0AC)
++#define INTC_VECTOR_ADDRESS_28_REG INTC_MEM_MAP_VALUE(0x0B0)
++#define INTC_VECTOR_ADDRESS_29_REG INTC_MEM_MAP_VALUE(0x0B4)
++#define INTC_VECTOR_ADDRESS_30_REG INTC_MEM_MAP_VALUE(0x0B8)
++#define INTC_VECTOR_ADDRESS_31_REG INTC_MEM_MAP_VALUE(0x0BC)
++
++#define INTC_INTERRUPT_PRIORITY_0_REG INTC_MEM_MAP_VALUE(0x0C0)
++#define INTC_INTERRUPT_PRIORITY_1_REG INTC_MEM_MAP_VALUE(0x0C4)
++#define INTC_INTERRUPT_PRIORITY_2_REG INTC_MEM_MAP_VALUE(0x0C8)
++#define INTC_INTERRUPT_PRIORITY_3_REG INTC_MEM_MAP_VALUE(0x0CC)
++#define INTC_INTERRUPT_PRIORITY_4_REG INTC_MEM_MAP_VALUE(0x0D0)
++#define INTC_INTERRUPT_PRIORITY_5_REG INTC_MEM_MAP_VALUE(0x0D4)
++#define INTC_INTERRUPT_PRIORITY_6_REG INTC_MEM_MAP_VALUE(0x0D8)
++#define INTC_INTERRUPT_PRIORITY_7_REG INTC_MEM_MAP_VALUE(0x0DC)
++#define INTC_INTERRUPT_PRIORITY_8_REG INTC_MEM_MAP_VALUE(0x0E0)
++#define INTC_INTERRUPT_PRIORITY_9_REG INTC_MEM_MAP_VALUE(0x0E4)
++#define INTC_INTERRUPT_PRIORITY_10_REG INTC_MEM_MAP_VALUE(0x0E8)
++#define INTC_INTERRUPT_PRIORITY_11_REG INTC_MEM_MAP_VALUE(0x0EC)
++#define INTC_INTERRUPT_PRIORITY_12_REG INTC_MEM_MAP_VALUE(0x0F0)
++#define INTC_INTERRUPT_PRIORITY_13_REG INTC_MEM_MAP_VALUE(0x0F4)
++#define INTC_INTERRUPT_PRIORITY_14_REG INTC_MEM_MAP_VALUE(0x0F8)
++#define INTC_INTERRUPT_PRIORITY_15_REG INTC_MEM_MAP_VALUE(0x0FC)
++#define INTC_INTERRUPT_PRIORITY_16_REG INTC_MEM_MAP_VALUE(0x100)
++#define INTC_INTERRUPT_PRIORITY_17_REG INTC_MEM_MAP_VALUE(0x104)
++#define INTC_INTERRUPT_PRIORITY_18_REG INTC_MEM_MAP_VALUE(0x108)
++#define INTC_INTERRUPT_PRIORITY_19_REG INTC_MEM_MAP_VALUE(0x10C)
++#define INTC_INTERRUPT_PRIORITY_20_REG INTC_MEM_MAP_VALUE(0x110)
++#define INTC_INTERRUPT_PRIORITY_21_REG INTC_MEM_MAP_VALUE(0x114)
++#define INTC_INTERRUPT_PRIORITY_22_REG INTC_MEM_MAP_VALUE(0x118)
++#define INTC_INTERRUPT_PRIORITY_23_REG INTC_MEM_MAP_VALUE(0x11C)
++#define INTC_INTERRUPT_PRIORITY_24_REG INTC_MEM_MAP_VALUE(0x120)
++#define INTC_INTERRUPT_PRIORITY_25_REG INTC_MEM_MAP_VALUE(0x124)
++#define INTC_INTERRUPT_PRIORITY_26_REG INTC_MEM_MAP_VALUE(0x128)
++#define INTC_INTERRUPT_PRIORITY_27_REG INTC_MEM_MAP_VALUE(0x12C)
++#define INTC_INTERRUPT_PRIORITY_28_REG INTC_MEM_MAP_VALUE(0x130)
++#define INTC_INTERRUPT_PRIORITY_29_REG INTC_MEM_MAP_VALUE(0x134)
++#define INTC_INTERRUPT_PRIORITY_30_REG INTC_MEM_MAP_VALUE(0x138)
++#define INTC_INTERRUPT_PRIORITY_31_REG INTC_MEM_MAP_VALUE(0x13C)
++
++#define INTC_IRQ_VECTOR_ADDRESS_REG INTC_MEM_MAP_VALUE(0x140)
++
++#define INTC_VECTOR_INTERRUPT_ENABLE_REG INTC_MEM_MAP_VALUE(0x144)
++
++
++
++/*
++ * define constants macros
++ */
++#define INTC_TIMER1_BIT_INDEX (0)
++#define INTC_TIMER2_BIT_INDEX (1)
++
++#define INTC_CLOCK_SCALE_BIT_INDEX (2)
++
++#define INTC_WATCHDOG_TIMER_BIT_INDEX (3)
++
++#define INTC_GPIO_EXTERNAL_INT_BIT_INDEX (4)
++
++#define INTC_PCI_INTA_BIT_INDEX (5)
++#define INTC_PCI_INTB_BIT_INDEX (6)
++#define INTC_PCI_BROKEN_BIT_INDEX (7)
++#define INTC_PCI_AHB2BRIDGE_BIT_INDEX (8)
++
++#define INTC_UART0_BIT_INDEX (9)
++#define INTC_UART1_BIT_INDEX (10)
++
++#define INTC_GDMAC_TC_BIT_INDEX (11)
++#define INTC_GDMAC_ERROR_BIT_INDEX (12)
++
++#define INTC_PCMCIA_BRIDGE_BIT_INDEX (13)
++
++#define INTC_RTC_BIT_INDEX (14)
++
++#define INTC_PCM_BIT_INDEX (15)
++
++#define INTC_USB20_DEVICE_BIT_INDEX (16)
++
++#define INTC_IDE_BIT_INDEX (17)
++
++#define INTC_NIC_STATUS_BIT_INDEX (18)
++#define INTC_NIC_TXTC_BIT_INDEX (19)
++#define INTC_NIC_RXRC_BIT_INDEX (20)
++#define INTC_NIC_TXQE_BIT_INDEX (21)
++#define INTC_NIC_RXQF_BIT_INDEX (22)
++
++#define INTC_USB11_BIT_INDEX (23)
++#define INTC_USB20_BIT_INDEX (24)
++
++#define INTC_I2S_BIT_INDEX (25)
++#define INTC_SPI_BIT_INDEX (26)
++#define INTC_I2C_BIT_INDEX (27)
++
++#define INTC_USB_DEVICE_VBUS_BIT_INDEX (28)
++
++#define INTC_EXT_INT29_BIT_INDEX (29)
++#define INTC_EXT_INT30_BIT_INDEX (30)
++#define INTC_HSDMAC_BIT_INDEX (31)
++
++
++/*
++ * define interrupt types
++ */
++#define INTC_IRQ_INTERRUPT (0)
++#define INTC_FIQ_INTERRUPT (1)
++
++/*
++ * define interrupt trigger mode
++ */
++#define INTC_LEVEL_TRIGGER (0)
++#define INTC_EDGE_TRIGGER (1)
++
++/*
++ * define rising/falling edge for edge trigger mode
++ */
++#define INTC_RISING_EDGE (0)
++#define INTC_FALLING_EDGE (1)
++
++/*
++ * define active High/Low for level trigger mode
++ */
++#define INTC_ACTIVE_HIGH (0)
++#define INTC_ACTIVE_LOW (1)
++
++/*
++ * macro declarations
++ */
++#define HAL_INTC_READ_INTERRUPT_RAW_STATUS(int_raw_status) \
++{ \
++ (int_raw_status) = (INTC_INTERRUPT_RAW_STATUS_REG); \
++}
++
++
++#define HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(source_bit_index) \
++{ \
++ (INTC_EDGE_INTERRUPT_SOURCE_CLEAR_REG) = (1 << source_bit_index); \
++}
++
++
++#define HAL_INTC_READ_INTERRUPT_MASK(int_mask) \
++{ \
++ (int_mask) = (INTC_INTERRUPT_MASK_REG); \
++}
++
++
++#define HAL_INTC_WRITE_INTERRUPT_MASK(int_mask) \
++{ \
++ (INTC_INTERRUPT_MASK_REG) = (int_mask); \
++}
++
++
++#define HAL_INTC_DISABLE_INTERRUPT_SOURCE(source_bit_index) \
++{ \
++ (INTC_INTERRUPT_MASK_REG) = (1 << source_bit_index); \
++}
++
++
++#define HAL_INTC_ENABLE_INTERRUPT_SOURCE(source_bit_index) \
++{ \
++ (INTC_INTERRUPT_MASK_CLEAR_REG) = (1 << source_bit_index); \
++}
++
++
++#define HAL_INTC_SET_EDGE_TRIGGER_MODE(source_bit_index) \
++{ \
++ (INTC_INTERRUPT_TRIGGER_MODE_REG) |= (1 << source_bit_index);\
++}
++
++
++#define HAL_INTC_SET_LEVEL_TRIGGER_MODE(source_bit_index) \
++{ \
++ (INTC_INTERRUPT_TRIGGER_MODE_REG) &= (~(1 << source_bit_index)); \
++}
++
++
++#define HAL_INTC_SET_RISING_EDGE_TRIGGER_LEVEL(source_bit_index) \
++{ \
++ (INTC_INTERRUPT_TRIGGER_LEVEL_REG) &= (~(1 << source_bit_index)); \
++}
++
++
++#define HAL_INTC_SET_FALLING_EDGE_TRIGGER_LEVEL(source_bit_index) \
++{ \
++ (INTC_INTERRUPT_TRIGGER_LEVEL_REG) |= (1 << source_bit_index); \
++}
++
++
++#define HAL_INTC_SET_ACTIVE_HIGH_TRIGGER_LEVEL(source_bit_index) \
++{ \
++ (INTC_INTERRUPT_TRIGGER_LEVEL_REG) &= (~(1 << source_bit_index));\
++}
++
++
++#define HAL_INTC_SET_ACTIVE_LOW_TRIGGER_LEVEL(source_bit_index) \
++{ \
++ (INTC_INTERRUPT_TRIGGER_LEVEL_REG) |= ((1 << source_bit_index)); \
++}
++
++
++#define HAL_INTC_ASSIGN_INTERRUPT_TO_IRQ(source_bit_index) \
++{ \
++ (INTC_FIQ_SELECT_REG) &= (~(1 << source_bit_index)); \
++}
++
++
++#define HAL_INTC_ASSIGN_INTERRUPT_TO_FIQ(source_bit_index) \
++{ \
++ (INTC_FIQ_SELECT_REG) |= (1 << source_bit_index); \
++}
++
++
++#define HAL_INTC_READ_IRQ_STATUS(int_irq_status) \
++{ \
++ (int_irq_status) = (INTC_IRQ_STATUS_REG); \
++}
++
++
++#define HAL_INTC_READ_FIQ_STATUS(int_fiq_status) \
++{ \
++ (int_fiq_status) = (INTC_FIQ_STATUS_REG); \
++}
++
++
++#define HAL_INTC_READ_SOFTWARE_INTERRUPT(software_interrupt) \
++{ \
++ (software_interrupt) = (INTC_SOFTWARE_INTERRUPT_REG); \
++}
++
++
++#define HAL_INTC_ENABLE_SOFTWARE_INTERRUPT(source_bit_index) \
++{ \
++ (INTC_SOFTWARE_INTERRUPT_REG) = (1 << source_bit_index); \
++}
++
++
++#define HAL_INTC_CLEAR_SOFTWARE_INTERRUPT(source_bit_index) \
++{ \
++ (INTC_SOFTWARE_INTERRUPT_CLEAR_REG) = (1 << source_bit_index); \
++}
++
++
++#define HAL_INTC_SELECT_INTERRUPT_SOURCE_FOR_SLEEP_WAKEUP(source_bit_index) \
++{ \
++ (INTC_POWER_MANAGEMENT_INTERRUPT_REG) = (1 << source_bit_index); \
++}
++
++#endif // end of #ifndef _STAR_INTC_H_
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_misc.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_misc.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_misc.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_misc.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,402 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_MISC_H_
++#define _STAR_MISC_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define MISC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_MISC_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define MISC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_MISC_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define MISC_MEMORY_REMAP_REG MISC_MEM_MAP_VALUE(0x00)
++#define MISC_CHIP_CONFIG_REG MISC_MEM_MAP_VALUE(0x04)
++#define MISC_DEBUG_PROBE_DATA_REG MISC_MEM_MAP_VALUE(0x08)
++#define MISC_DEBUG_PROBE_SELECTION_REG MISC_MEM_MAP_VALUE(0x0C)
++#define MISC_PCI_CONTROL_BROKEN_MASK_REG MISC_MEM_MAP_VALUE(0x10)
++#define MISC_PCI_BROKEN_STATUS_REG MISC_MEM_MAP_VALUE(0x14)
++#define MISC_PCI_DEVICE_VENDOR_ID_REG MISC_MEM_MAP_VALUE(0x18)
++#define MISC_USB_HOST_PHY_CONTROL_TEST_REG MISC_MEM_MAP_VALUE(0x1C)
++#define MISC_GPIOA_PIN_ENABLE_REG MISC_MEM_MAP_VALUE(0x20)
++#define MISC_GPIOB_PIN_ENABLE_REG MISC_MEM_MAP_VALUE(0x24)
++#define MISC_GPIOA_RESISTOR_CONFIG_REG MISC_MEM_MAP_VALUE(0x28)
++#define MISC_GPIOA_DRIVE_STRENGTH_CONFIG_REG MISC_MEM_MAP_VALUE(0x2C)
++#define MISC_FAST_ETHERNET_PHY_CONFIG_REG MISC_MEM_MAP_VALUE(0x30)
++#define MISC_SOFTWARE_TEST_1_REG MISC_MEM_MAP_VALUE(0x38)
++#define MISC_SOFTWARE_TEST_2_REG MISC_MEM_MAP_VALUE(0x3C)
++
++#define MISC_E_FUSE_0_REG MISC_MEM_MAP_VALUE(0x60)
++#define MISC_E_FUSE_1_REG MISC_MEM_MAP_VALUE(0x64)
++
++
++/*
++ * define constants macros
++ */
++#define MISC_PARALLEL_FLASH_BOOT (0)
++#define MISC_SPI_SERIAL_FLASH_BOOT (1)
++
++#define MISC_LITTLE_ENDIAN (0)
++#define MISC_BIG_ENDIAN (1)
++
++#define MISC_FARADAY_ICE (0)
++#define MISC_ARM_ICE (1)
++
++#define MISC_EXT_INT29_PINS ((0x1 << 0))
++#define MISC_EXT_INT30_PINS ((0x1 << 1))
++#define MISC_EXT_INT31_PINS ((0x1 << 2))
++#define MISC_I2C_PINS ((0x1 << 13) | (0x1 << 14))
++#define MISC_I2S_PINS ((0x1 << 15) | (0x1 << 16) | (0x1 << 17))
++#define MISC_PCM_PINS ((0x1 << 18) | (0x1 << 19) | (0x1 << 20) | (0x1 << 21))
++#define MISC_LED0_PINS ((0x1 << 22))
++#define MISC_LED1_PINS ((0x1 << 23))
++#define MISC_LED2_PINS ((0x1 << 24))
++#define MISC_LED012_PINS ((0x1 << 22) | (0x1 << 23) | (0x1 << 24))
++#define MISC_WDTIMER_RESET_PINS ((0x1 << 25))
++#define MISC_SPI_PINS ((0x1 << 26) | (0x1 << 27) | (0x1 << 28) | (0x1 << 29) | (0x1 << 30) | (0x1 << 31))
++#define MISC_MDC_MDIO_PINS ((0x1 << 0) | (0x1 << 1))
++#define MISC_NIC_COL_PINS ((0x1 << 2))
++#define MISC_IDE_PINS ((0xFF << 3))
++#define MISC_SRAM_BANK1_PINS ((0x1 << 11) | (0x1 << 14))
++#define MISC_SRAM_BANK2_PINS ((0x1 << 12) | (0x1 << 15))
++#define MISC_SRAM_BANK3_PINS ((0x1 << 13) | (0x1 << 16))
++#define MISC_PCMCIA_PINS ((0x1 << 17) | (0x1 << 18) | (0x1 << 19) | (0x1 << 20))
++#define MISC_UART1_PINS ((0x1 << 21) | (0x1 << 22))
++#define MISC_PCI_PINS (((u32)0x1FF << 23))
++
++#define MISC_UART0_ACT0_Pin (0x1 << 2)
++#define MISC_UART1_ACT1_Pin (0x1 << 3)
++
++#define MISC_GPIOA_PIN_0 (0)
++#define MISC_GPIOA_PIN_1 (1)
++#define MISC_GPIOA_PIN_2 (2)
++#define MISC_GPIOA_PIN_3 (3)
++#define MISC_GPIOA_PIN_4 (4)
++#define MISC_GPIOA_PIN_5 (5)
++#define MISC_GPIOA_PIN_6 (6)
++#define MISC_GPIOA_PIN_7 (7)
++#define MISC_GPIOA_PIN_8 (8)
++#define MISC_GPIOA_PIN_9 (9)
++#define MISC_GPIOA_PIN_10 (10)
++
++#define MISC_GPIOA_75K_RESISTOR_PULL_DOWN (1)
++#define MISC_GPIOA_75K_RESISTOR_PULL_UP (2)
++#define MISC_GPIOA_75K_RESISTOR_PULL_KEEPER (3)
++
++#define MISC_GPIOA_DRIVE_STRENGTH_4MA (0)
++#define MISC_GPIOA_DRIVE_STRENGTH_8MA (1)
++
++
++/*
++ * macro declarations
++ */
++#define HAL_MISC_ENABLE_SPI_SERIAL_FLASH_BANK_ACCESS() \
++{ \
++ (MISC_CHIP_CONFIG_REG) |= (0x1 << 4); \
++}
++
++#define HAL_MISC_DISABLE_SPI_SERIAL_FLASH_BANK_ACCESS() \
++{ \
++ (MISC_CHIP_CONFIG_REG) &= ~(0x1 << 4); \
++}
++
++
++/*
++ * Macro defines for GPIOA and GPIOB Pin Enable Register
++ */
++#define HAL_MISC_ENABLE_EXT_INT29_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_EXT_INT29_PINS); \
++}
++
++#define HAL_MISC_DISABLE_EXT_INT29_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_EXT_INT29_PINS); \
++}
++
++#define HAL_MISC_ENABLE_EXT_INT30_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_EXT_INT30_PINS); \
++}
++
++#define HAL_MISC_DISABLE_EXT_INT30_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_EXT_INT30_PINS); \
++}
++
++#define HAL_MISC_ENABLE_I2C_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_I2C_PINS); \
++}
++
++#define HAL_MISC_DISABLE_I2C_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_I2C_PINS); \
++}
++
++#define HAL_MISC_ENABLE_I2S_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_I2S_PINS); \
++}
++
++#define HAL_MISC_DISABLE_I2S_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_I2S_PINS); \
++}
++
++#define HAL_MISC_ENABLE_PCM_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_PCM_PINS); \
++}
++
++#define HAL_MISC_DISABLE_PCM_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_PCM_PINS); \
++}
++
++#define HAL_MISC_ENABLE_LED0_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_LED0_PINS); \
++}
++
++#define HAL_MISC_DISABLE_LED0_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_LED0_PINS); \
++}
++
++#define HAL_MISC_ENABLE_LED1_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_LED1_PINS); \
++}
++
++#define HAL_MISC_DISABLE_LED1_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_LED1_PINS); \
++}
++
++#define HAL_MISC_ENABLE_LED2_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_LED2_PINS); \
++}
++
++#define HAL_MISC_DISABLE_LED2_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_LED2_PINS); \
++}
++
++#define HAL_MISC_ENABLE_LED012_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_LED012_PINS); \
++}
++
++#define HAL_MISC_DISABLE_LED012_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_LED012_PINS); \
++}
++
++#define HAL_MISC_ENABLE_WDTIMER_RESET_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_WDTIMER_RESET_PINS); \
++}
++
++#define HAL_MISC_DISABLE_WDTIMER_RESET_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_WDTIMER_RESET_PINS); \
++}
++
++#define HAL_MISC_ENABLE_SPI_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_SPI_PINS); \
++}
++
++#define HAL_MISC_DISABLE_SPI_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_SPI_PINS); \
++}
++
++#define HAL_MISC_ENABLE_UART0_ACT0_PIN() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_UART0_ACT0_Pin); \
++}
++
++#define HAL_MISC_DISABLE_UART0_ACT0_PIN() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_UART0_ACT0_Pin); \
++}
++
++#define HAL_MISC_ENABLE_UART1_ACT1_PIN() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_UART1_ACT1_Pin); \
++}
++
++#define HAL_MISC_DISABLE_UART1_ACT1_PIN() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_UART1_ACT1_Pin); \
++}
++
++#define HAL_MISC_ENABLE_MDC_MDIO_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_MDC_MDIO_PINS); \
++}
++
++#define HAL_MISC_DISABLE_MDC_MDIO_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_MDC_MDIO_PINS); \
++}
++
++#define HAL_MISC_ENABLE_NIC_COL_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_NIC_COL_PINS); \
++}
++
++#define HAL_MISC_DISABLE_NIC_COL_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_NIC_COL_PINS); \
++}
++
++#define HAL_MISC_ENABLE_IDE_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_IDE_PINS); \
++}
++
++#define HAL_MISC_DISABLE_IDE_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_IDE_PINS); \
++}
++
++#define HAL_MISC_ENABLE_SRAM_BANK1_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_SRAM_BANK1_PINS); \
++}
++
++#define HAL_MISC_DISABLE_SRAM_BANK1_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_SRAM_BANK1_PINS); \
++}
++
++#define HAL_MISC_ENABLE_SRAM_BANK2_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_SRAM_BANK2_PINS); \
++}
++
++#define HAL_MISC_DISABLE_SRAM_BANK2_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_SRAM_BANK2_PINS); \
++}
++
++#define HAL_MISC_ENABLE_SRAM_BANK3_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_SRAM_BANK3_PINS); \
++}
++
++#define HAL_MISC_DISABLE_SRAM_BANK3_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_SRAM_BANK3_PINS); \
++}
++
++#define HAL_MISC_ENABLE_PCMCIA_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_PCMCIA_PINS); \
++}
++
++#define HAL_MISC_DISABLE_PCMCIA_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_PCMCIA_PINS); \
++}
++
++#define HAL_MISC_ENABLE_UART1_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_UART1_PINS); \
++}
++
++#define HAL_MISC_DISABLE_UART1_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_UART1_PINS); \
++}
++
++#define HAL_MISC_ENABLE_PCI_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_PCI_PINS); \
++}
++
++#define HAL_MISC_DISABLE_PCI_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_PCI_PINS); \
++}
++
++#define HAL_MISC_ENABLE_ALL_SHARED_GPIO_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) = (0x0); \
++ (MISC_GPIOB_PIN_ENABLE_REG) = (0x0); \
++}
++
++#define HAL_MISC_DISABLE_ALL_SHARED_GPIO_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) = (0xFFFFFFFF); \
++ (MISC_GPIOB_PIN_ENABLE_REG) = (0xFFFFFFFF); \
++}
++
++#define HAL_MISC_CONFIGURE_GPIOA_RESISTOR(pin_index, value) \
++{ \
++ (MISC_GPIOA_RESISTOR_CONFIG_REG) &= ~(0x3 << (2 * pin_index)); \
++ (MISC_GPIOA_RESISTOR_CONFIG_REG) |= ((value & 0x3) << (2 * pin_index)); \
++}
++
++#define HAL_MISC_CONFIGURE_GPIOA_DRIVE_STRENGTH(pin_index, value) \
++{ \
++ (MISC_GPIOA_DRIVE_STRENGTH_CONFIG_REG) &= ~(0x1 << pin_index); \
++ (MISC_GPIOA_DRIVE_STRENGTH_CONFIG_REG) |= (value << pin_index); \
++}
++
++#define HAL_MISC_SELECT_FAST_ETHERNET_PHY_LED_MODE0() \
++{ \
++ (MISC_FAST_ETHERNET_PHY_CONFIG_REG) = (0x0); \
++}
++
++#define HAL_MISC_SELECT_FAST_ETHERNET_PHY_LED_MODE1() \
++{ \
++ (MISC_FAST_ETHERNET_PHY_CONFIG_REG) = (0x1); \
++}
++
++#define HAL_MISC_SELECT_FAST_ETHERNET_PHY_LED_MODE2() \
++{ \
++ (MISC_FAST_ETHERNET_PHY_CONFIG_REG) = (0x2); \
++}
++
++#define HAL_MISC_SELECT_FAST_ETHERNET_PHY_LED_MODE3() \
++{ \
++ (MISC_FAST_ETHERNET_PHY_CONFIG_REG) = (0x3); \
++}
++
++
++#endif // end of #ifndef _STAR_MISC_H_
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_nic.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_nic.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_nic.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_nic.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,346 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_NIC_H_
++#define _STAR_NIC_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define NIC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_NIC_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define NIC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_NIC_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define NIC_PHY_CONTROL_REG0 NIC_MEM_MAP_VALUE(0x000)
++#define NIC_PHY_CONTROL_REG1 NIC_MEM_MAP_VALUE(0x004)
++
++#define NIC_MAC_CONTROL_REG NIC_MEM_MAP_VALUE(0x008)
++#define NIC_FLOW_CONTROL_CONFIG_REG NIC_MEM_MAP_VALUE(0x00C)
++
++#define NIC_ARL_CONFIG_REG NIC_MEM_MAP_VALUE(0x010)
++
++#define NIC_MY_MAC_HIGH_BYTE_REG NIC_MEM_MAP_VALUE(0x014)
++#define NIC_MY_MAC_LOW_BYTE_REG NIC_MEM_MAP_VALUE(0x018)
++
++#define NIC_HASH_TABLE_CONTROL_REG NIC_MEM_MAP_VALUE(0x01C)
++
++#define NIC_MY_VLANID_CONTROL_REG NIC_MEM_MAP_VALUE(0x020)
++
++#define NIC_MY_VLANID_0_1 NIC_MEM_MAP_VALUE(0x024)
++#define NIC_MY_VLANID_2_3 NIC_MEM_MAP_VALUE(0x028)
++
++#define NIC_DMA_CONFIG_REG NIC_MEM_MAP_VALUE(0x030)
++#define NIC_TX_DMA_CONTROL_REG NIC_MEM_MAP_VALUE(0x034)
++#define NIC_RX_DMA_CONTROL_REG NIC_MEM_MAP_VALUE(0x038)
++#define NIC_TX_DESC_PTR_REG NIC_MEM_MAP_VALUE(0x03C)
++#define NIC_RX_DESC_PTR_REG NIC_MEM_MAP_VALUE(0x040)
++
++#define NIC_TX_DESC_BASE_ADDR_REG NIC_MEM_MAP_VALUE(0x044)
++#define NIC_RX_DESC_BASE_ADDR_REG NIC_MEM_MAP_VALUE(0x048)
++#define NIC_DELAYED_INT_CONFIG_REG NIC_MEM_MAP_VALUE(0x04C)
++
++#define NIC_INT_STATUS_REG NIC_MEM_MAP_VALUE(0x050)
++#define NIC_INT_MASK_REG NIC_MEM_MAP_VALUE(0x054)
++
++#define NIC_TEST_0_REG NIC_MEM_MAP_VALUE(0x058)
++#define NIC_TEST_1_REG NIC_MEM_MAP_VALUE(0x05C)
++
++#define NIC_MIB_RX_OK_PKT_CNTR NIC_MEM_MAP_VALUE(0x100)
++#define NIC_MIB_RX_OK_BYTE_CNTR NIC_MEM_MAP_VALUE(0x104)
++#define NIC_MIB_RX_RUNT_BYTE_CNTR NIC_MEM_MAP_VALUE(0x108)
++#define NIC_MIB_RX_OSIZE_DROP_PKT_CNTR NIC_MEM_MAP_VALUE(0x10C)
++
++#define NIC_MIB_RX_NO_BUF_DROP_PKT_CNTR NIC_MEM_MAP_VALUE(0x110)
++
++#define NIC_MIB_RX_CRC_ERR_PKT_CNTR NIC_MEM_MAP_VALUE(0x114)
++
++#define NIC_MIB_RX_ARL_DROP_PKT_CNTR NIC_MEM_MAP_VALUE(0x118)
++
++#define NIC_MIB_MYVLANID_MISMATCH_DROP_PKT_CNTR NIC_MEM_MAP_VALUE(0x11C)
++
++#define NIC_MIB_RX_CHKSUM_ERR_PKT_CNTR NIC_MEM_MAP_VALUE(0x120)
++
++#define NIC_MIB_RX_PAUSE_FRAME_PKT_CNTR NIC_MEM_MAP_VALUE(0x124)
++
++#define NIC_MIB_TX_OK_PKT_CNTR NIC_MEM_MAP_VALUE(0x128)
++#define NIC_MIB_TX_OK_BYTE_CNTR NIC_MEM_MAP_VALUE(0x12C)
++
++#define NIC_MIB_TX_COLLISION_CNTR NIC_MEM_MAP_VALUE(0x130)
++#define NIC_MIB_TX_PAUSE_FRAME_CNTR NIC_MEM_MAP_VALUE(0x130)
++
++#define NIC_MIB_TX_FIFO_UNDERRUN_RETX_CNTR NIC_MEM_MAP_VALUE(0x134)
++
++
++
++
++/*
++ * define constants macros
++ */
++
++#define NIC_PHY_ADDRESS 1 //the phy addr const value
++#define NIC_PHY_ID 0x0243 //the phy id
++
++#define GW_NIC_MAX_TFD_NUM (32)
++#define GW_NIC_MAX_RFD_NUM (32)
++#define MAX_BUFFERS (64)
++
++
++
++#define MMU_OFF (0)
++#define MMU_ON (1)
++#define OS_NULL (0)
++
++
++#define NET_BUFFER_PACKET_SIZE (512)
++#define NET_BUFFER_SHIFT_BIT_NUM (9) // 2*n9=512
++
++#define MAX_PACKET_LEN (1536)
++
++#define INTERNAL_LOOPBACK_MODE (1)
++#define SOFTWARE_REPEATER_MODE (2)
++
++#define TXTC_INT_BIT (0x08000000)
++#define TX_INSV_BIT (0x04000000)
++
++#define LS_BIT (0x10000000)
++#define FS_BIT (0x20000000)
++#define EOR_BIT (0x40000000)
++#define FS_LS_BIT (0x30000000)
++#define C_BIT (0x80000000)
++#define FS_LS_C_BIT (0xB0000000)
++#define FS_LS_INT_BIT (0x38000000)
++
++
++
++// HASH TABLE CONTROL REGISTER
++#define NIC_HASH_TABLE_BIST_DONE_BIT (0x1 << 17)
++#define NIC_HASH_TABLE_BIST_OK_BIT (0x1 << 16)
++#define NIC_HASH_COMMAND_START_BIT (0x1 << 14)
++#define NIC_HASH_COMMAND_BIT (0x1 << 13)
++#define NIC_HASH_BIT_DATA (0x1 << 12)
++#define NIC_HASH_BIT_ADDRESS_BIT (0x1ff)
++
++
++#define NIC_REG_CNT ((0x48 << 2) + 1)
++
++/*
++ * macro access
++ */
++
++#define GW_NIC_TX_TFD_NEXT(work_tfd_ptr) \
++ work_tfd_ptr = NIC_TX_TFD_Ring.head + (((u32)(work_tfd_ptr - NIC_TX_TFD_Ring.head) + 1) % GW_NIC_MAX_TFD_NUM)
++
++
++#define GW_NIC_TX_TFD_PREVIOUS(work_tfd_ptr) \
++ work_tfd_ptr = NIC_TX_TFD_Ring.head + ((GW_NIC_MAX_TFD_NUM + (u32)(work_tfd_ptr - NIC_TX_TFD_Ring.head) - 1) % GW_NIC_MAX_TFD_NUM)
++
++
++#define GW_NIC_RX_RFD_NEXT(work_rfd_ptr) \
++ work_rfd_ptr = NIC_RX_RFD_Ring.head + (((u32)(work_rfd_ptr - NIC_RX_RFD_Ring.head) + 1) % GW_NIC_MAX_RFD_NUM)
++
++
++#define GW_NIC_RX_RFD_PREVIOUS(work_rfd_ptr) \
++ work_rfd_ptr = NIC_RX_RFD_Ring.head + ((GW_NIC_MAX_RFD_NUM + (u32)(work_rfd_ptr - NIC_RX_RFD_Ring.head) - 1) % GW_NIC_MAX_RFD_NUM)
++
++
++/*
++ * PHY register defines
++ */
++#define PHY_MII_CONTROL_REG_ADDR 0x00
++#define PHY_MII_STATUS_REG_ADDR 0x01
++#define PHY_ID1_REG_ADDR 0x02
++#define PHY_ID2_REG_ADDR 0x03
++#define PHY_AN_ADVERTISEMENT_REG_ADDR 0x04
++#define PHY_AN_REAMOTE_CAP_REG_ADDR 0x05
++
++
++#define PHY_RESERVED1_REG_ADDR 0x10
++#define PHY_RESERVED2_REG_ADDR 0x11
++#define PHY_CH_STATUS_OUTPUT_REG_ADDR 0x12
++#define PHY_RESERVED3_REG_ADDR 0x13
++#define PHY_RESERVED4_REG_ADDR 0x14
++
++
++#define PHY_SPEC_CONTROL_REG_ADDR 0x16
++#define PHY_INTC_CONTROL_STATUS_REG_ADDR 0x17
++
++/*
++ * NIC registers access macros defines
++ */
++
++//0x004
++#define HAL_NIC_WRITE_PHY_CONTROL1(config_value) \
++ ((NIC_PHY_CONTROL_REG1) = (config_value))
++
++#define HAL_NIC_READ_PHY_CONTROL1(config_value) \
++ ((config_value) = (NIC_PHY_CONTROL_REG1))
++
++//0x008
++#define HAL_NIC_WRITE_MAC_CONFIGURATION(config_value) \
++ ((NIC_MAC_CONTROL_REG) = (config_value))
++
++#define HAL_NIC_READ_MAC_CONFIGURATION(config_value) \
++ ((config_value) = (NIC_MAC_CONTROL_REG))
++
++//0x00C
++#define HAL_NIC_WRITE_FLOW_CONTROL_CONFIG(fc_cfg) \
++ ((NIC_FLOW_CONTROL_CONFIG_REG) = (fc_cfg))
++
++#define HAL_NIC_READ_FLOW_CONTROL_CONFIG(fc_cfg) \
++ ((fc_cfg) = (NIC_FLOW_CONTROL_CONFIG_REG))
++
++//0x010
++#define HAL_NIC_WRITE_ARL_CONFIGURATION(cfg) \
++ ((NIC_ARL_CONFIG_REG) = (cfg))
++
++#define HAL_NIC_READ_ARL_CONFIGURATION(cfg) \
++ ((cfg) = (NIC_ARL_CONFIG_REG))
++
++//0x014,
++#define HAL_NIC_WRITE_MY_MAC_HIGH_BYTE(cfg) \
++ ((NIC_MY_MAC_HIGH_BYTE_REG) = (cfg & 0x0000FFFF ) )
++
++#define HAL_NIC_READ_MY_MAC_HIGH_BYTE(cfg) \
++ ((cfg) = (NIC_MY_MAC_HIGH_BYTE_REG & 0x0000FFFF ))
++
++//0x018
++#define HAL_NIC_WRITE_MY_MAC_LOW_BYTE(cfg) \
++ ((NIC_MY_MAC_LOW_BYTE_REG) = (cfg))
++
++#define HAL_NIC_READ_MY_MAC_LOW_BYTE(cfg) \
++ ((cfg) = (NIC_MY_MAC_LOW_BYTE_REG))
++
++//0x03C
++#define HAL_NIC_READ_INTERRUPT_STATUS(int_status) \
++ ((int_status) = (NIC_INT_STATUS_REG))
++
++#define HAL_NIC_CLEAR_ALL_INTERRUPT_STATUS_SOURCES()\
++ ((NIC_INT_STATUS_REG) = (0xFFFFFFFF))
++
++#define HAL_NIC_CLEAR_INTERRUPT_STATUS_SOURCES(source) \
++ ((NIC_INT_STATUS_REG) |= (source))
++
++#define HAL_NIC_CLEAR_INTERRUPT_STATUS_SOURCE_BIT(source_bit_index) \
++ ((NIC_INT_STATUS_REG) |= (1 << (source_bit_index)))
++
++//0x040
++#define HAL_NIC_DISABLE_ALL_INTERRUPT_STATUS_SOURCES() \
++ ((NIC_INT_MASK_REG) = (0xFFFFFFFF))
++
++#define HAL_NIC_ENABLE_ALL_INTERRUPT_STATUS_SOURCES() \
++ ((NIC_INT_MASK_REG) = (0x00000000))
++
++#define HAL_NIC_DISABLE_INTERRUPT_STATUS_SOURCE_BIT(source_bit_index) \
++ ((NIC_INT_MASK_REG) |= (1 << (source_bit_index)))
++
++#define HAL_NIC_ENABLE_INTERRUPT_STATUS_SOURCE_BIT(source_bit_index) \
++ ((NIC_INT_MASK_REG) &= ~(1 << (source_bit_index)))
++
++//0x44
++#define HAL_NIC_WRITE_TEST0_REG(cfg) \
++ ((NIC_TEST_0_REG) = (cfg))
++
++#define HAL_NIC_READ_TEST0_REG(cfg) \
++ ((cfg) = (NIC_TEST_0_REG))
++
++//0x48
++#define HAL_NIC_WRITE_TEST1_REG(cfg) \
++ ((NIC_TEST_1_REG) = (cfg))
++
++#define HAL_NIC_READ_TEST1_REG(cfg) \
++ ((cfg) = (NIC_TEST_1_REG))
++
++
++
++/*
++ * NIC's DMA macros defines
++ */
++#define HAL_NIC_TX_DMA_START() \
++ ((NIC_TX_DMA_CONTROL_REG) = (1))
++
++
++#define HAL_NIC_TX_DMA_STOP() \
++ ((NIC_TX_DMA_CONTROL_REG) = (0))
++
++
++#define HAL_NIC_READ_TX_DMA_STATE(state) \
++ ((state) = (NIC_TX_DMA_CONTROL_REG))
++
++
++#define HAL_NIC_RX_DMA_START() \
++ ((NIC_RX_DMA_CONTROL_REG) = (1))
++
++
++#define HAL_NIC_RX_DMA_STOP() \
++ ((NIC_RX_DMA_CONTROL_REG) = (0))
++
++
++#define HAL_NIC_WRITE_TXSD(tssd_value) \
++ ((NIC_TX_DESC_PTR_REG) = (tssd_value))
++
++
++#define HAL_NIC_READ_TXSD(tssd_value) \
++ ((tssd_value) = (NIC_TX_DESC_PTR_REG))
++
++
++#define HAL_NIC_WRITE_RXSD(fssd_value) \
++ ((NIC_RX_DESC_PTR_REG) = (fssd_value))
++
++
++#define HAL_NIC_READ_RXSD(fssd_value) \
++ ((fssd_value) = (NIC_RX_DESC_PTR_REG))
++
++
++#define HAL_NIC_WRITE_TX_BASE(ts_base_value) \
++ ((NIC_TX_DESC_BASE_ADDR_REG) = (ts_base_value))
++
++
++#define HAL_NIC_READ_TX_BASE(ts_base_value) \
++ ((ts_base_value) = (NIC_TX_DESC_BASE_ADDR_REG))
++
++
++#define HAL_NIC_WRITE_RX_BASE(fs_base_value) \
++ ((NIC_RX_DESC_BASE_ADDR_REG) = (fs_base_value))
++
++
++#define HAL_NIC_READ_RX_BASE(fs_base_value) \
++ ((fs_base_value) = (NIC_RX_DESC_BASE_ADDR_REG))
++
++
++#define HAL_NIC_WRITE_DELAYED_INTERRUPT_CONFIG(delayed_interrupt_config) \
++ ((NIC_DELAYED_INT_CONFIG_REG) = (delayed_interrupt_config))
++
++
++#define HAL_NIC_READ_DELAYED_INTERRUPT_CONFIG(delayed_interrupt_config) \
++ ((delayed_interrupt_config) = (NIC_DELAYED_INT_CONFIG_REG))
++
++#endif // end of #ifndef _STAR_NIC_H_
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_pci_bridge.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_pci_bridge.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_pci_bridge.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_pci_bridge.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,132 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_PCI_DRIDGE_H_
++#define _STAR_PCI_DRIDGE_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#define PCI_IO_SPACE_BASE_ADDR (SYSPA_PCI_IO_SPACE_BASE_ADDR)
++#define PCI_IO_SPACE_SIZE 0x08000000 /* 64MB */
++#define PCI_IO_SPACE_START PCI_IO_SPACE_BASE_ADDR
++#define PCI_IO_SPACE_END (PCI_IO_SPACE_BASE_ADDR + PCI_IO_SPACE_SIZE - 1)
++#define PCI_MEMORY_SPACE_BASE_ADDR (SYSPA_PCI_MEMORY_SPACE_BASE_ADDR)
++#define PCI_MEMORY_SPACE_SIZE 0x10000000 /* 256MB */
++#define PCI_NPREFETCH_MEMORY_SPACE_START PCI_MEMORY_SPACE_BASE_ADDR
++#define PCI_NPREFETCH_MEMORY_SPACE_SIZE 0x00800000 /* 8MB */
++#define PCI_NPREFETCH_MEMORY_SPACE_END (PCI_NPREFETCH_MEMORY_SPACE_START + PCI_NPREFETCH_MEMORY_SPACE_SIZE - 1)
++#define PCI_PREFETCH_MEMORY_SPACE_START (PCI_NPREFETCH_MEMORY_SPACE_START + PCI_NPREFETCH_MEMORY_SPACE_SIZE)
++#define PCI_PREFETCH_MEMORY_SPACE_SIZE 0x00800000 /* 8MB */
++#define PCI_PREFETCH_MEMORY_SPACE_END (PCI_PREFETCH_MEMORY_SPACE_START + PCI_PREFETCH_MEMORY_SPACE_SIZE - 1)
++
++
++#if defined(__UBOOT__)
++#define PCIB_MEM_MAP_VALUE(base, reg_offset) (*((u32 volatile *)(SYSPA_PCI_##base##_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define PCIB_MEM_MAP_VALUE(base, reg_offset) (*((u32 volatile *)(SYSVA_PCI_##base##_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define PCI_BRIDGE_CONFIG_DATA PCIB_MEM_MAP_VALUE(CONFIG_DATA_BASE, 0x2C)
++#define PCI_BRIDGE_CONFIG_ADDR PCIB_MEM_MAP_VALUE(CONFIG_ADDR_BASE, 0x28)
++
++#define PCI_BRIDGE_CONFIG_DATA_REG_OFFSET 0x2C
++#define PCI_BRIDGE_CONFIG_ADDR_REG_OFFSET 0x28
++
++/*
++ * define constants macros
++ */
++#define PCIB_BUS_CLOCK_33M 1
++
++#define PCIB_BUS_CLOCK_66M 2
++
++#define PCIB_DEVICE_ID 0x8131
++
++#define PCIB_VENDOR_ID 0xEEEE
++
++#define PCIB_CLASS_CODE 0xFF0000
++
++#define PCIB_REVISION_ID 0x00
++
++#define PCIB_BAR0_MEMORY_SPACE_BASE 0x20000000
++
++#define PCIB_BAR1_IO_SPACE_BASE 0x20000000
++
++
++#define PCI_MEMORY_SPACE_BASE 0xB0000000
++
++#define PCI_IO_SPACE_BASE 0xA8000000
++
++
++#define PCI_MAX_BUS_NUM 0x01
++#define PCI_MAX_DEVICE_NUM 0x14
++#define PCI_MAX_FUNCTION_NUM 0x01
++#define PCI_MAX_REG_NUM 0x3C
++
++
++#define PCI_MAX_DEVICE_TYPE_NUM 0x13
++#define PCI_MAX_BAR_NUM 0x06
++
++
++#define PCI_CSH_VENDOR_ID_REG_ADDR 0x00
++#define PCI_CSH_DEVICE_ID_REG_ADDR 0x02
++#define PCI_CSH_COMMAND_REG_ADDR 0x04
++#define PCI_CSH_STATUS_REG_ADDR 0x06
++#define PCI_CSH_REVISION_CLASS_REG_ADDR 0x08
++#define PCI_CSH_CACHE_LINE_SIZE_REG_ADDR 0x0C
++#define PCI_CSH_LATENCY_TIMER_REG_ADDR 0x0D
++#define PCI_CSH_HEADER_TYPE_REG_ADDR 0x0E
++#define PCI_CSH_BIST_REG_ADDR 0x0F
++#define PCI_CSH_BAR_REG_ADDR 0x10
++
++
++#define PCI_IO_SPACE_SIZE_1M 0x00
++#define PCI_IO_SPACE_SIZE_2M 0x01
++#define PCI_IO_SPACE_SIZE_4M 0x02
++#define PCI_IO_SPACE_SIZE_8M 0x03
++#define PCI_IO_SPACE_SIZE_16M 0x04
++#define PCI_IO_SPACE_SIZE_32M 0x05
++#define PCI_IO_SPACE_SIZE_64M 0x06
++#define PCI_IO_SPACE_SIZE_128M 0x07
++#define PCI_IO_SPACE_SIZE_256M 0x08
++#define PCI_IO_SPACE_SIZE_512M 0x09
++#define PCI_IO_SPACE_SIZE_1G 0x0A
++#define PCI_IO_SPACE_SIZE_2G 0x0B
++
++
++#define PCI_MEMORY_SPACE_TYPE 0
++#define PCI_IO_SPACE_TYPE 1
++
++#define PCI_BROKEN_FLAG 1
++#define PCI_AHB2PCIB_FLAG 2
++
++
++#endif // end of #ifndef _STAR_PCI_DRIDGE_H_
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_pcmcia_bridge.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_pcmcia_bridge.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_pcmcia_bridge.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_pcmcia_bridge.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,231 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_PCMCIA_DRIDGE_H_
++#define _STAR_PCMCIA_DRIDGE_H_
++
++/******************************************************************************
++ * MODULE NAME: star_pcmcia_bridge.h
++ * PROJECT CODE: Equuleus
++ * DESCRIPTION:
++ * MAINTAINER: Eric Yang
++ * DATE: 15 September 2005
++ *
++ * SOURCE CONTROL:
++ *
++ * LICENSE:
++ * This source code is copyright (c) 2005 Star Semi Inc.
++ * All rights reserved.
++ *
++ * REVISION HISTORY:
++ * 15 September 2005 - Eric Yang - Initial Version v1.0
++ *
++ *
++ * SOURCE:
++ * ISSUES:
++ * NOTES TO USERS:
++ ******************************************************************************/
++
++#include "star_sys_memory_map.h"
++
++
++#if defined(__UBOOT__)
++#define PCMCIA_BRIDGE_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_PCMCIA_CONTROL_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define PCMCIA_BRIDGE_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_PCMCIA_CONTROL_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define PCMCIA_CONFIGURATION_REG PCMCIA_BRIDGE_MEM_MAP_VALUE(0x20)
++#define PCMCIA_MEMORY_ACCESS_TIMING_PARAM_REG PCMCIA_BRIDGE_MEM_MAP_VALUE(0x24)
++#define PCMCIA_IO_ACCESS_TIMING_PARAM_REG PCMCIA_BRIDGE_MEM_MAP_VALUE(0x28)
++
++
++#define PCMCIA_ATTRIBUTE_MEMORY_SPACE_BASE_ADDR (SYSPA_PCMCIA_ATTRIBUTE_MEMORY_BASE_ADDR)
++#define PCMCIA_COMMOM_MEMORY_SPACE_BASE_ADDR (SYSPA_PCMCIA_COMMON_MEMORY_BASE_ADDR)
++#define PCMCIA_IO_SPACE_BASE_ADDR (SYSPA_PCMCIA_IO_SPACE_BASE_ADDR)
++
++
++
++/*
++ * define constants macros
++ */
++#define PCMCIA_DATA_BUS_WIDTH_8 (0)
++
++#define PCMCIA_DATA_BUS_WIDTH_16 (1)
++
++
++/*
++ * Flags for PCMCIA_STATUS
++ */
++#define FLAG_STATUS_BVD1 0x01
++#define FLAG_STATUS_STSCHG 0x01
++#define FLAG_STATUS_BVD2 0x02
++#define FLAG_STATUS_SPKR 0x02
++#define FLAG_STATUS_DETECT 0xf3 /* bit 2=0,3=0 ,0x0c bit 2=1,3=1 */
++#define FLAG_STATUS_WRPROT 0x10
++#define FLAG_STATUS_READY 0x20
++#define FLAG_STATUS_INPACK 0x40
++
++
++/*
++ * Flags for PCMCIA_CSC
++ */
++#define FLAG_CSC_BVD1 0x01
++#define FLAG_CSC_BVD2 0x02
++#define FLAG_CSC_READY 0x04
++#define FLAG_CSC_INPACK 0x08
++#define FLAG_CSC_STSCHG 0x10
++#define FLAG_CSC_CARDINT 0x20
++#define FLAG_CSC_DETECT 0x40
++#define FLAG_CSC_SWCDC 0x80
++
++
++/*
++ * Flags for PCMCIA_POWER
++ */
++#define FLAG_POWER_OFF 0x00 /* Turn off the socket */
++#define FLAG_POWER_3V 0x01 /* 1:Vcc = 3.3v 0:Vcc = 5.0v */
++#define FLAG_POWER_SWH 0x02 /* Direct 5V/3V switch enable */
++#define FLAG_POWER_CTL 0x10 /* Socket power control */
++#define FLAG_POWER_AUTO 0x20 /* Auto power switch enable */
++#define FLAG_POWER_OUTENA 0x40 /* Output enable */
++
++
++/*
++ * Flags for PCMCIA_GBLCTL
++ */
++#define FLAG_GBLCTL_PWRDOWN 0x01
++#define FLAG_GBLCTL_WBACK 0x02
++#define FLAG_GBLCTL_16BITS 0x04
++#define FLAG_GBLCTL_IOCARD 0x08
++#define FLAG_GBLCTL_SWCDINT 0x10
++#define FLAG_GBLCTL_RESET 0x20
++
++
++/*
++ * Flags for PCMCIA_INTCFG
++ */
++#define FLAG_INTCFG_BDEAD 0x01
++#define FLAG_INTCFG_BWARN 0x02
++#define FLAG_INTCFG_READY 0x04
++#define FLAG_INTCFG_INPACK 0x08
++#define FLAG_INTCFG_LEVEL 0x10
++#define FLAG_INTCFG_FEDGE 0x20
++#define FLAG_INTCFG_REDGE 0x30
++#define FLAG_INTCFG_DETECT 0x40
++#define FLAG_INTCFG_STSCHG 0x80
++
++
++/*
++ * Definitions for Card Status flags for GetStatus
++ */
++#define STATUS_BATDEAD 0x0001
++#define STATUS_BATWARN 0x0002
++#define STATUS_DETECT 0x0004
++#define STATUS_WRPROT 0x0008
++#define STATUS_READY 0x0010
++#define STATUS_INPACK 0x0020
++#define STATUS_STSCHG 0x0040 /* just for CSC */
++#define SOFTWARE_STATUS_DETECT 0x0040 /* just for CSC */
++
++
++/*
++ * Set Socket configuration flags
++ */
++#define SS_PWR_AUTO 0x0001
++#define SS_PWR_SWH 0x0002
++#define SS_PWR_SEL 0x0004
++#define SS_POWER_ON 0x0008
++#define SS_OUTPUT_ENA 0x0010
++#define SS_IOCARD 0x0020
++#define SS_RESET 0x0040
++#define SS_WBACK 0x0080
++#define SS_16BITS 0x0100
++#define SS_PWR_DOWN_MODE 0x0200
++#define SS_SWCDINT 0x0400
++
++
++/*
++ * Set Interrupt Configuration flags
++ */
++#define INTR_BATDEAD 0x0001
++#define INTR_BATWARN 0x0002
++#define INTR_READY 0x0004
++#define INTR_INPACK 0x0008
++#define INTR_CARDINT 0x0010
++#define INTR_DETECT 0x0020
++#define INTR_STSCHG 0x0040
++
++
++/*
++ * tuple code
++ */
++#define CISTPL_NULL 0x00
++#define CISTPL_DEVICE 0x01
++#define CISTPL_NO_LINK 0x14
++#define CISTPL_VERS_1 0x15
++#define CISTPL_CONFIG 0x1a
++#define CISTPL_CFTABLE_ENTRY 0x1b
++#define CISTPL_MANFID 0x20
++#define CISTPL_END 0xff
++
++
++/*
++ * Return codes
++ */
++#define CS_SUCCESS 0x00
++#define CS_UNSUPPORTED_FUNCTION 0x15
++#define CS_NO_MORE_ITEMS 0x1f
++#define CS_BAD_TUPLE 0x40
++
++
++/*
++ * Attributes for tuple calls
++ */
++#define TUPLE_RETURN_LINK 0x01
++#define TUPLE_RETURN_COMMON 0x02
++
++#define RETURN_FIRST_TUPLE 0xff
++
++
++/*
++ * macro declarations
++ */
++#define HAL_PCMCIA_ENABLE_PCMCIA_CONTROLLER() \
++{ \
++ (PCMCIA_CONFIGURATION_REG) |= (0x1 << 1); \
++}
++
++#define HAL_PCMCIA_DISABLE_PCMCIA_CONTROLLER() \
++{ \
++ (PCMCIA_CONFIGURATION_REG) &= ~(0x1 << 1); \
++}
++
++
++#endif // end of #ifndef _STAR_PCMCIA_DRIDGE_H_
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_pcm.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_pcm.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_pcm.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_pcm.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,277 @@
++/******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_PCM_H_
++#define _STAR_PCM_H_
++
++/******************************************************************************
++ * MODULE NAME: star_pcm.h
++ * PROJECT CODE: Orion
++ * DESCRIPTION:
++ * MAINTAINER: MJLIU
++ * DATE: 15 September 2005
++ *
++ * SOURCE CONTROL:
++ *
++ * LICENSE:
++ * This source code is copyright (c) 2005 Star Semi Inc.
++ * All rights reserved.
++ *
++ * REVISION HISTORY:
++ * 15 September 2005 - MJLIU - Initial Version v1.0
++ *
++ *
++ * SOURCE:
++ * ISSUES:
++ * NOTES TO USERS:
++ ******************************************************************************/
++
++#include <mach/star_sys_memory_map.h>
++
++#define PCM_BASE_ADDR (SYSVA_PCM_BASE_ADDR)
++#define PCM_MEM_MAP_ADDR(reg_offset) (PCM_BASE_ADDR + reg_offset)
++#define PCM_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)PCM_MEM_MAP_ADDR(reg_offset)))
++
++
++/*
++ * define access macros
++ */
++#define PCM_CONFIGURATION_0_REG PCM_MEM_MAP_VALUE(0x80)
++#define PCM_CONFIGURATION_1_REG PCM_MEM_MAP_VALUE(0x84)
++
++#define PCM_CHANNEL_0_CONFIG_REG PCM_MEM_MAP_VALUE(0x88)
++#define PCM_CHANNEL_1_CONFIG_REG PCM_MEM_MAP_VALUE(0x8C)
++#define PCM_CHANNEL_2_CONFIG_REG PCM_MEM_MAP_VALUE(0x90)
++#define PCM_CHANNEL_3_CONFIG_REG PCM_MEM_MAP_VALUE(0x94)
++
++#define PCM_TX_DATA_31_0_REG PCM_MEM_MAP_VALUE(0x98)
++#define PCM_TX_DATA_63_32_REG PCM_MEM_MAP_VALUE(0x9C)
++
++#define PCM_RX_DATA_31_0_REG PCM_MEM_MAP_VALUE(0xA0)
++#define PCM_RX_DATA_63_32_REG PCM_MEM_MAP_VALUE(0xA4)
++
++#define PCM_INTERRUPT_STATUS_REG PCM_MEM_MAP_VALUE(0xA8)
++#define PCM_INTERRUPT_ENABLE_REG PCM_MEM_MAP_VALUE(0xAC)
++
++
++
++/*
++ * define constants macros
++ */
++#define CH0_BIT_INDEX (0x1)
++#define CH1_BIT_INDEX (0x2)
++#define CH2_BIT_INDEX (0x4)
++#define CH3_BIT_INDEX (0x8)
++
++#define PCM_RXBUF_FULL_FG (0x1)
++#define PCM_TXBUF_EMPTY_FG (0x2)
++#define PCM_RXBUF_OVERRUN_FG (0x4)
++#define PCM_TXBUF_UNDERRUN_FG (0x8)
++
++#define PCM_ENABLE_FG (0x1 << 23)
++
++#define PCM_IDL_MODE (0)
++#define PCM_GCI_MODE (1)
++
++#define PCM_DATA_BIT_8 (0)
++#define PCM_DATA_BIT_16 (1)
++
++
++/*
++ * Set Commands Variables
++ */
++#define Software_Reset (0x02)
++#define Hardware_Reset (0x04)
++#define Write_Transmit_Time_Slot (0x40)
++#define Read_Transmit_Time_Slot (0x41)
++#define Write_Receive_Time_Slot (0x42)
++#define Read_Receive_Time_Slot (0x43)
++#define Write_Tx_Rx_CLK_Slot_Tx_CLK_Edge (0x44)
++#define Read_Tx_Rx_CLK_Slot_Tx_CLK_Edge (0x45)
++#define Write_Device_Configure_Reg (0x46)
++#define Read_Device_Configure_Reg (0x47)
++#define Write_Channel_Enable_Operating_Mode_Reg (0x4A)
++#define Read_Channel_Enable_Operating_Mode_Reg (0x4B)
++#define Read_Signal_Reg (0x4D)
++#define Input_Data_Reg (0x52)
++#define Output_Data_Reg (0x53)
++#define Input_Direction_Reg (0x54)
++#define Output_Direction_Reg (0x55)
++#define Write_System_State (0x56)
++#define Read_System_State (0x57)
++#define Write_Operating_Functon (0x60)
++#define Read_Operating_Functon (0x61)
++#define Write_System_State_Config (0x68)
++#define Read_System_State_Config (0x69)
++#define Write_Interrupt_Mask_Reg (0x6C)
++#define Read_Interrupt_Mask_Reg (0x6D)
++#define Write_Operating_Condition (0x70)
++#define Write_Loop_Supervision_Parameter (0xC2)
++#define Write_DC_Feed_Parameter (0xC6)
++#define Write_Signal_A_B_Parameter (0xD2)
++#define Write_Switching_Reg_Parameter (0xE4)
++#define Write_Switching_Reg_Control (0xE6)
++
++
++/*
++ * define data structure
++ */
++typedef struct _PCM_CHANNEL_OBJECT_ PCM_CHANNEL_OBJECT_T;
++
++struct _PCM_CHANNEL_OBJECT_
++{
++ u16 channel_0_tx_data;
++ u16 channel_0_rx_data;
++ u32 channel_0_data_width; /* 0 : 8-bit, 1 : 16-bit */
++
++ u16 channel_1_tx_data;
++ u16 channel_1_rx_data;
++ u32 channel_1_data_width;
++
++ u16 channel_2_tx_data;
++ u16 channel_2_rx_data;
++ u32 channel_2_data_width;
++
++ u16 channel_3_tx_data;
++ u16 channel_3_rx_data;
++ u32 channel_3_data_width;
++
++ u32 channel_enable_config; /* bit[0] = 0 : channel 0 disabled
++ [0] = 1 : channel 0 enabled
++ bit[1] = 0 : channel 1 disabled
++ [1] = 1 : channel 1 enabled
++ bit[2] = 0 : channel 2 disabled
++ [2] = 1 : channel 2 enabled
++ bit[3] = 0 : channel 3 disabled
++ [3] = 1 : channel 3 enabled */
++};
++
++
++typedef struct _PCM_OBJECT_ PCM_OBJECT_T;
++
++struct _PCM_OBJECT_
++{
++ u32 config_0;
++ u32 config_1;
++
++ u32 channel_0_config;
++ u32 channel_1_config;
++ u32 channel_2_config;
++ u32 channel_3_config;
++
++ u32 interrupt_config;
++
++ /*
++ * For interrupt setting
++ */
++// INTC_OBJECT_T intc_obj;
++};
++
++
++
++/*
++ * function declarations
++ */
++void Hal_Pcm_Initialize(PCM_OBJECT_T *);
++
++
++/*
++ * macro declarations
++ */
++#define HAL_PCM_ENABLE_PCM() \
++{ \
++ (PCM_CONFIGURATION_0_REG) |= ((u32)0x1 << 31); \
++}
++
++#define HAL_PCM_DISABLE_PCM() \
++{ \
++ (PCM_CONFIGURATION_0_REG) &= ~((u32)0x1 << 31); \
++}
++
++#define HAL_PCM_ENABLE_DATA_SWAP() \
++{ \
++ (PCM_CONFIGURATION_0_REG) |= (0x1 << 24); \
++}
++
++#define HAL_PCM_DISABLE_DATA_SWAP() \
++{ \
++ (PCM_CONFIGURATION_0_REG) &= ~(0x1 << 24); \
++}
++
++#define HAL_PCM_WRITE_TX_DATA_0(tx_data_0) \
++{ \
++ (PCM_TX_DATA_31_0_REG) = tx_data_0; \
++}
++
++#define HAL_PCM_WRITE_TX_DATA_1(tx_data_1) \
++{ \
++ (PCM_TX_DATA_63_32_REG) = tx_data_1; \
++}
++
++#define HAL_PCM_READ_RX_DATA_0(rx_data_0) \
++{ \
++ (rx_data_0) = PCM_RX_DATA_31_0_REG; \
++}
++
++#define HAL_PCM_READ_RX_DATA_1(rx_data_1) \
++{ \
++ (rx_data_1) = PCM_RX_DATA_63_32_REG; \
++}
++
++#define HAL_PCM_READ_INTERRUPT_STATUS(status) \
++{ \
++ (status) = PCM_INTERRUPT_STATUS_REG; \
++}
++
++#define HAL_PCM_CLEAR_INTERRUPT_STATUS(status) \
++{ \
++ (PCM_INTERRUPT_STATUS_REG) = (status & 0xC0); \
++}
++
++#define HAL_PCM_DISABLE_RECEIVE_BUFFER_FULL_INTERRUPT() \
++{ \
++ (PCM_INTERRUPT_ENABLE_REG) &= ~(0x1 << 0); \
++}
++
++#define HAL_PCM_DISABLE_TRANSMIT_BUFFER_EMPTY_INTERRUPT() \
++{ \
++ (PCM_INTERRUPT_ENABLE_REG) &= ~(0x1 << 1); \
++}
++
++#define HAL_PCM_DISABLE_RECEIVE_BUFFER_OVERRUN_INTERRUPT() \
++{ \
++ (PCM_INTERRUPT_ENABLE_REG) &= ~(0x1 << 2); \
++}
++
++#define HAL_PCM_DISABLE_TRANSMIT_BUFFER_UNDERRUN_INTERRUPT() \
++{ \
++ (PCM_INTERRUPT_ENABLE_REG) &= ~(0x1 << 3); \
++}
++
++#define HAL_PCM_DISABLE_ALL_INTERRUPT_SOURCES() \
++{ \
++ (PCM_INTERRUPT_ENABLE_REG) = 0; \
++}
++
++#endif // end of #ifndef _STAR_PCM_H_
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_powermgt.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_powermgt.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_powermgt.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_powermgt.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,616 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_POWERMGT_H_
++#define _STAR_POWERMGT_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define PWRMGT_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_POWER_MANAGEMENT_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define PWRMGT_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_POWER_MANAGEMENT_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define PWRMGT_CLOCK_GATE_CONTROL0_REG PWRMGT_MEM_MAP_VALUE(0x00)
++#define PWRMGT_CLOCK_GATE_CONTROL1_REG PWRMGT_MEM_MAP_VALUE(0x04)
++#define PWRMGT_SOFTWARE_RESET_CONTROL_REG PWRMGT_MEM_MAP_VALUE(0x08)
++#define PWRMGT_SYSTEM_CLOCK_CONTROL_REG PWRMGT_MEM_MAP_VALUE(0x0C)
++#define PWRMGT_PLL_POWER_DOWN_CONTROL_REG PWRMGT_MEM_MAP_VALUE(0x10)
++#define PWRMGT_CPU_INITIALIZATION_REG PWRMGT_MEM_MAP_VALUE(0x14)
++#define PWRMGT_PAD_DRIVE_STRENGTH_CONTROL_REG PWRMGT_MEM_MAP_VALUE(0x1C)
++#define PWRMGT_USB_DEVICE_POWERMGT_REG PWRMGT_MEM_MAP_VALUE(0x20)
++#define PWRMGT_REGULATOR_CONTROL_REG PWRMGT_MEM_MAP_VALUE(0x24)
++#define PWRMGT_RTC_XTAL_CONTROL_REG PWRMGT_MEM_MAP_VALUE(0x28)
++#define PWRMGT_PLL250_CONTROL_REG PWRMGT_MEM_MAP_VALUE(0x2C)
++
++
++/*
++ * define constants macros
++ */
++#define PWRMGT_PCMCIA_SOFTWARE_RESET_BIT_INDEX (1)
++#define PWRMGT_IDE_SOFTWARE_RESET_BIT_INDEX (2)
++#define PWRMGT_VIC_SOFTWARE_RESET_BIT_INDEX (3)
++#define PWRMGT_DMA_SOFTWARE_RESET_BIT_INDEX (4)
++#define PWRMGT_NIC_SOFTWARE_RESET_BIT_INDEX (5)
++#define PWRMGT_USB_HOST_SOFTWARE_RESET_BIT_INDEX (6)
++#define PWRMGT_PCI_BRIDGE_SOFTWARE_RESET_BIT_INDEX (7)
++#define PWRMGT_P2S_SOFTWARE_RESET_BIT_INDEX (8)
++#define PWRMGT_UART0_SOFTWARE_RESET_BIT_INDEX (9)
++#define PWRMGT_UART1_SOFTWARE_RESET_BIT_INDEX (10)
++#define PWRMGT_TIMER_SOFTWARE_RESET_BIT_INDEX (11)
++#define PWRMGT_WDTIMER_SOFTWARE_RESET_BIT_INDEX (12)
++#define PWRMGT_GPIO_SOFTWARE_RESET_BIT_INDEX (13)
++#define PWRMGT_USB_DEVICE_SOFTWARE_RESET_BIT_INDEX (14)
++#define PWRMGT_FAST_ETHERNET_PHY_SOFTWARE_RESET_BIT_INDEX (15)
++#define PWRMGT_HSDMA_SOFTWARE_RESET_BIT_INDEX (16)
++
++
++#define PWRMGT_PLL_FREQUENCY_175MHZ (0 << 0)
++#define PWRMGT_PLL_FREQUENCY_200MHZ (1 << 0)
++#define PWRMGT_PLL_FREQUENCY_225MHZ (2 << 0)
++#define PWRMGT_PLL_FREQUENCY_250MHZ (3 << 0)
++
++#define PWRMGT_CPUCLK_DIVIDER_BY_1 (0 << 2)
++#define PWRMGT_CPUCLK_DIVIDER_BY_2 (1 << 2)
++#define PWRMGT_CPUCLK_DIVIDER_BY_3 (2 << 2)
++#define PWRMGT_CPUCLK_DIVIDER_BY_4 (3 << 2)
++
++#define PWRMGT_HCLK_DIVIDER_BY_1 (0 << 4)
++#define PWRMGT_HCLK_DIVIDER_BY_2 (1 << 4)
++#define PWRMGT_HCLK_DIVIDER_BY_3 (2 << 4)
++#define PWRMGT_HCLK_DIVIDER_BY_4 (3 << 4)
++
++#define PWRMGT_HCLK_SOURCE_FCLK (0 << 6)
++#define PWRMGT_HCLK_SOURCE_125MHZ (1 << 6)
++
++#define PWRMGT_PCLK_DIVIDER_BY_1 (0 << 8)
++#define PWRMGT_PCLK_DIVIDER_BY_2 (1 << 8)
++#define PWRMGT_PCLK_DIVIDER_BY_3 (2 << 8)
++#define PWRMGT_PCLK_DIVIDER_BY_4 (3 << 8)
++
++#define PWRMGT_PCICLK_DIVIDER_BY_1 (0 << 10)
++#define PWRMGT_PCICLK_DIVIDER_BY_2 (1 << 10)
++#define PWRMGT_PCICLK_DIVIDER_BY_3 (2 << 10)
++#define PWRMGT_PCICLK_DIVIDER_BY_4 (3 << 10)
++
++
++#define PWRMGT_PLLCLK_TO_CPUCLK_RATIO_BY_1 (1)
++#define PWRMGT_PLLCLK_TO_CPUCLK_RATIO_BY_2 (2)
++#define PWRMGT_PLLCLK_TO_CPUCLK_RATIO_BY_3 (3)
++#define PWRMGT_PLLCLK_TO_CPUCLK_RATIO_BY_4 (4)
++
++#define PWRMGT_CPUCLK_TO_HCLK_RATIO_BY_1 (1)
++#define PWRMGT_CPUCLK_TO_HCLK_RATIO_BY_2 (2)
++#define PWRMGT_CPUCLK_TO_HCLK_RATIO_BY_3 (3)
++#define PWRMGT_CPUCLK_TO_HCLK_RATIO_BY_4 (4)
++
++#define PWRMGT_HCLK_TO_PCLK_RATIO_BY_1 (1)
++#define PWRMGT_HCLK_TO_PCLK_RATIO_BY_2 (2)
++#define PWRMGT_HCLK_TO_PCLK_RATIO_BY_3 (3)
++#define PWRMGT_HCLK_TO_PCLK_RATIO_BY_4 (4)
++
++/*
++ * Macro defines for Clock Gate Control
++ */
++#define HAL_PWRMGT_DISABLE_DRAMC_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~(0x1); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_NIC_CLOCK() \
++{ \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 0); \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x0F << 20); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 5); \
++}
++
++#define HAL_PWRMGT_DISABLE_NIC_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~(0x0F << 20); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_PCI_BRIDGE_33M_CLOCK() \
++{ \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 1); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 10); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (0x1 << 10); \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x1 << 28) | (0x1 << 30); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 7); \
++}
++
++#define HAL_PWRMGT_ENABLE_PCI_BRIDGE_66M_CLOCK() \
++{ \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 1); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 10); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (0x0 << 10); \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x1 << 28) | (0x1 << 30); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 7); \
++}
++
++#define HAL_PWRMGT_DISABLE_PCI_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~((0x1 << 28) | (0x1 << 30)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_USB_CLOCK() \
++{ \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0xF << 1); \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x1 << 24); \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 28); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 6) | (0x1 << 14); \
++}
++
++#define HAL_PWRMGT_DISABLE_USB_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~(0x1 << 24); \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~(0x1 << 28); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_DMA_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x1 << 16); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 4); \
++}
++
++#define HAL_PWRMGT_DISABLE_DMA_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~(0x1 << 16); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_IDE_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x1 << 8) | (0x1 << 9); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 2); \
++}
++
++#define HAL_PWRMGT_DISABLE_IDE_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~((0x1 << 8) | (0x1 << 9)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_UART0_CLOCK() \
++{ \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~((0x1 << 1) | (0x1 << 2) | (0x1 << 5)); \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 12); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 9); \
++}
++
++#define HAL_PWRMGT_DISABLE_UART0_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~(0x1 << 12); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_UART1_CLOCK() \
++{ \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~((0x1 << 1) | (0x1 << 2) | (0x1 << 5)); \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 13); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 10); \
++}
++
++#define HAL_PWRMGT_DISABLE_UART1_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~(0x1 << 13); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_PCMCIA_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x1 << 4) | (0x1 << 5); \
++}
++
++#define HAL_PWRMGT_DISABLE_PCMCIA_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~((0x1 << 4) | (0x1 << 5)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_GPIO_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 25); \
++}
++
++#define HAL_PWRMGT_DISABLE_GPIO_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~(0x1 << 25); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_WDTIMER_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 21) | (0x1 << 22); \
++}
++
++#define HAL_PWRMGT_DISABLE_WDTIMER_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~((0x1 << 21) | (0x1 << 22)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_RTC_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 23); \
++}
++
++#define HAL_PWRMGT_DISABLE_RTC_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~(0x1 << 23); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_TIMER_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 17) | (0x1 << 18) | (0x1 << 19); \
++}
++
++#define HAL_PWRMGT_DISABLE_TIMER_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~((0x1 << 17) | (0x1 << 18) | (0x1 << 19)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_I2C_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 1); \
++}
++
++#define HAL_PWRMGT_DISABLE_I2C_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~(0x1 << 1); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_I2S_CLOCK() \
++{ \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~((0x1 << 5) | (0x1 << 6)); \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 1) | (0x1 << 10); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 8); \
++}
++
++#define HAL_PWRMGT_DISABLE_I2S_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~((0x1 << 1) | (0x1 << 10)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_PCM_CLOCK() \
++{ \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 5); \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 1) | (0x1 << 6); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 8); \
++}
++
++#define HAL_PWRMGT_DISABLE_PCM_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~((0x1 << 1) | (0x1 << 6)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_SPI_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 0) | (0x1 << 1); \
++}
++
++#define HAL_PWRMGT_DISABLE_SPI_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~((0x1 << 0) | (0x1 << 1)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_VIC_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x1 << 12); \
++}
++
++#define HAL_PWRMGT_DISABLE_VIC_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~(0x1 << 12); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_SMC_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x1 << 4) | (0x1 << 5); \
++}
++
++#define HAL_PWRMGT_DISABLE_SMC_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~((0x1 << 4) | (0x1 << 5)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_HSDMA_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 29); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 16); \
++}
++
++#define HAL_PWRMGT_DISABLE_HSDMA_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~(0x1 << 29); \
++}
++
++
++
++/*
++ * Macro defines for Reset Control
++ */
++#define HAL_PWRMGT_GLOBAL_SOFTWARE_RESET() \
++{ \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG &= ~(0x1); \
++}
++
++
++/*
++ * Macro defines for System Clock Control
++ */
++#define HAL_PWRMGT_SET_PLL_FREQUENCY_175MHZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~0x3; \
++}
++
++
++#define HAL_PWRMGT_SET_PLL_FREQUENCY_200MHZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~0x3; \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= 0x1; \
++}
++
++
++#define HAL_PWRMGT_SET_PLL_FREQUENCY_225MHZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~0x3; \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= 0x2; \
++}
++
++
++#define HAL_PWRMGT_SET_PLL_FREQUENCY_250MHZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~0x3; \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= 0x3; \
++}
++
++
++#define HAL_PWRMGT_CONFIG_PLLCLK_TO_CPUCLK_RATIO(ratio) \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 2); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (((ratio - 1) & 0x3) << 2); \
++}
++
++
++#define HAL_PWRMGT_CONFIG_CPUCLK_TO_HCLK_RATIO(ratio) \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 4); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (((ratio - 1) & 0x3) << 4); \
++}
++
++
++#define HAL_PWRMGT_HCLK_SOURCE_FCLK() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x1 << 6); \
++}
++
++
++#define HAL_PWRMGT_HCLK_SOURCE_125MHZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (0x1 << 6); \
++}
++
++
++#define HAL_PWRMGT_GIGA_NIC_CLOCK_SOURCE_HCLK() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x1 << 7); \
++}
++
++
++#define HAL_PWRMGT_GIGA_NIC_CLOCK_SOURCE_62_5MHZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (0x1 << 7); \
++}
++
++
++#define HAL_PWRMGT_CONFIG_HCLK_TO_PCLK_RATIO(ratio) \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 8); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (((ratio - 1) & 0x3) << 8); \
++}
++
++
++#define HAL_PWRMGT_I2S_CLOCK_SOURCE_8192000HZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 12); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (0x0 << 12); \
++}
++
++
++#define HAL_PWRMGT_I2S_CLOCK_SOURCE_11289600HZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 12); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (0x1 << 12); \
++}
++
++
++#define HAL_PWRMGT_I2S_CLOCK_SOURCE_12288000HZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 12); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (0x2 << 12); \
++}
++
++
++#define HAL_PWRMGT_CONFIGURE_MDC_CLOCK_DIVIDER(divided_value) \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 14); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= ((divided_value & 0x3) << 14); \
++}
++
++
++#define HAL_PWRMGT_CONFIGURE_CLOCK_OUT_PIN(pin_source_select, divided_value) \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3F << 16); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= ((pin_source_select & 0xF) << 16); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= ((divided_value & 0x3) << 20); \
++}
++
++
++/*
++ * Macro defines for PLL Power Down Control
++ */
++#define HAL_PWRMGT_POWER_DOWN_SYSTEM_XTAL_PAD() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG |= (0x1 << 7)
++
++#define HAL_PWRMGT_POWER_ON_SYSTEM_XTAL_PAD() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 7)
++
++
++#define HAL_PWRMGT_POWER_DOWN_PLL_X5() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG |= (0x1 << 0)
++
++#define HAL_PWRMGT_POWER_ON_PLL_X5() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 0)
++
++
++#define HAL_PWRMGT_POWER_DOWN_PLL_X8() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG |= (0x1 << 1)
++
++#define HAL_PWRMGT_POWER_ON_PLL_X8() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 1)
++
++
++#define HAL_PWRMGT_POWER_DOWN_PLL_X3() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG |= (0x1 << 2)
++
++#define HAL_PWRMGT_POWER_ON_PLL_X3() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 2)
++
++
++#define HAL_PWRMGT_POWER_DOWN_USBH_PHY_PLL() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG |= (0x1 << 3)
++
++#define HAL_PWRMGT_POWER_ON_USBH_PHY_PLL() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 3)
++
++
++#define HAL_PWRMGT_POWER_DOWN_USBD_PHY_PLL() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG |= (0x1 << 4)
++
++#define HAL_PWRMGT_POWER_ON_USBD_PHY_PLL() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 4)
++
++
++#define HAL_PWRMGT_POWER_DOWN_PLL_X2250() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG |= (0x1 << 5)
++
++#define HAL_PWRMGT_POWER_ON_PLL_X2250() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 5)
++
++
++#define HAL_PWRMGT_POWER_DOWN_PLL_X7() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG |= (0x1 << 6)
++
++#define HAL_PWRMGT_POWER_ON_PLL_X7() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 6)
++
++
++#define HAL_PWRMGT_POWER_DOWN_ALL_PLL() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG = 0x7F;
++
++#define HAL_PWRMGT_POWER_ON_ALL_PLL() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG = 0;
++
++
++/*
++ * Macro defines for Pad Drive Strength Control
++ */
++#define HAL_PWRMGT_SELECT_PAD_DRIVE_STRENGTH_PCMCIA_CARDBUS_MODE() \
++{ \
++ PWRMGT_PAD_DRIVE_STRENGTH_CONTROL_REG &= ~(0x3 << 0); \
++}
++
++#define HAL_PWRMGT_SELECT_PAD_DRIVE_STRENGTH_PCI_MODE() \
++{ \
++ PWRMGT_PAD_DRIVE_STRENGTH_CONTROL_REG &= ~(0x3 << 0); \
++ PWRMGT_PAD_DRIVE_STRENGTH_CONTROL_REG |= (0x1 << 0); \
++}
++
++#define HAL_PWRMGT_SELECT_PAD_DRIVE_STRENGTH_MII_MODE() \
++{ \
++ PWRMGT_PAD_DRIVE_STRENGTH_CONTROL_REG |= (0x1 << 2); \
++}
++
++#define HAL_PWRMGT_SELECT_PAD_DRIVE_STRENGTH_RGMII_MODE() \
++{ \
++ PWRMGT_PAD_DRIVE_STRENGTH_CONTROL_REG &= ~(0x1 << 2); \
++}
++
++#define HAL_PWRMGT_ENABLE_MII_PAD_SIGNAL_NOT_BOUNDED() \
++{ \
++ PWRMGT_PAD_DRIVE_STRENGTH_CONTROL_REG |= (0x1 << 3); \
++}
++
++#define HAL_PWRMGT_DISABLE_MII_PAD_SIGNAL_NOT_BOUNDED() \
++{ \
++ PWRMGT_PAD_DRIVE_STRENGTH_CONTROL_REG &= ~(0x1 << 3); \
++}
++
++
++/*
++ * Macro defines for USB Device Power Management
++ */
++#define HAL_PWRMGT_REMOTE_WAKEUP_USB_HOST() \
++{ \
++ PWRMGT_USB_DEVICE_POWERMGT_REG |= (0x1 << 4); \
++}
++
++#define HAL_PWRMGT_USB_DEVICE_PHY_CLOCK_SOURCE_EXTERNAL_12MHZ() \
++{ \
++ PWRMGT_USB_DEVICE_POWERMGT_REG &= ~(0x1 << 5); \
++}
++
++#define HAL_PWRMGT_USB_DEVICE_PHY_CLOCK_SOURCE_INTERNAL_12MHZ() \
++{ \
++ PWRMGT_USB_DEVICE_POWERMGT_REG |= (0x1 << 5); \
++}
++
++
++/*
++ * Macro defines for Regulator Control
++ */
++
++
++#endif // end of #ifndef _STAR_POWERMGT_H_
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_rtc.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_rtc.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_rtc.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_rtc.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,87 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_RTC_H_
++#define _STAR_RTC_H_
++
++#include <mach/star_sys_memory_map.h>
++
++#define RTC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_RTC_BASE_ADDR + reg_offset)))
++
++#define RTC_SECOND_REG RTC_MEM_MAP_VALUE(0x00)
++#define RTC_MINUTE_REG RTC_MEM_MAP_VALUE(0x04)
++#define RTC_HOUR_REG RTC_MEM_MAP_VALUE(0x08)
++#define RTC_DAY_REG RTC_MEM_MAP_VALUE(0x0C)
++#define RTC_SECOND_ALARM_REG RTC_MEM_MAP_VALUE(0x10)
++#define RTC_MINUTE_ALARM_REG RTC_MEM_MAP_VALUE(0x14)
++#define RTC_HOUR_ALARM_REG RTC_MEM_MAP_VALUE(0x18)
++#define RTC_RECORD_REG RTC_MEM_MAP_VALUE(0x1C)
++#define RTC_CONTROL_REG RTC_MEM_MAP_VALUE(0x20)
++#define RTC_INTERRUPT_STATUS_REG RTC_MEM_MAP_VALUE(0x34)
++
++#define RTC_ENABLE_BIT (1 << 0)
++#define RTC_AUTO_SECOND_ALARM_ENABLE_BIT (1 << 1)
++#define RTC_AUTO_MINUTE_ALARM_ENABLE_BIT (1 << 2)
++#define RTC_AUTO_HOUR_ALARM_ENABLE_BIT (1 << 3)
++#define RTC_AUTO_DAY_ALARM_ENABLE_BIT (1 << 4)
++#define RTC_MATCH_ALARM_ENABLE_BIT (1 << 5)
++#define RTC_BATTERY_LOW_VOLTAGE_ENABLE_BIT (1 << 6)
++
++#define RTC_AUTO_SECOND_ALARM_INTR_BIT (1 << 0)
++#define RTC_AUTO_MINUTE_ALARM_INTR_BIT (1 << 1)
++#define RTC_AUTO_HOUR_ALARM_INTR_BIT (1 << 2)
++#define RTC_AUTO_DAY_ALARM_INTR_BIT (1 << 3)
++#define RTC_MATCH_ALARM_INTR_BIT (1 << 4)
++#define RTC_BATTERY_LOW_VOLTAGE_INTR_BIT (1 << 5)
++
++#define HAL_RTC_READ_SECOND(second) ((second) = (RTC_SECOND_REG) & 0x3F);
++#define HAL_RTC_READ_MINUTE(minute) ((minute) = (RTC_MINUTE_REG) & 0x3F);
++#define HAL_RTC_READ_HOUR(hour) ((hour) = (RTC_HOUR_REG) & 0x1F);
++#define HAL_RTC_READ_DAY(day) ((day) = (RTC_DAY_REG) & 0xFFFF);
++#define HAL_RTC_ENABLE() ((RTC_CONTROL_REG) |= (RTC_ENABLE_BIT));
++#define HAL_RTC_DISABLE() ((RTC_CONTROL_REG) &= ~(RTC_ENABLE_BIT));
++#define HAL_RTC_AUTO_SECOND_ALARM_ENABLE() ((RTC_CONTROL_REG) |= (RTC_AUTO_SECOND_ALARM_ENABLE_BIT));
++#define HAL_RTC_AUTO_SECOND_ALARM_DISABLE() ((RTC_CONTROL_REG) &= ~(RTC_AUTO_SECOND_ALARM_ENABLE_BIT));
++#define HAL_RTC_AUTO_MINUTE_ALARM_ENABLE() ((RTC_CONTROL_REG) |= (RTC_AUTO_MINUTE_ALARM_ENABLE_BIT));
++#define HAL_RTC_AUTO_MINUTE_ALARM_DISABLE() ((RTC_CONTROL_REG) &= ~(RTC_AUTO_MINUTE_ALARM_ENABLE_BIT));
++#define HAL_RTC_AUTO_HOUR_ALARM_ENABLE() ((RTC_CONTROL_REG) |= (RTC_AUTO_HOUR_ALARM_ENABLE_BIT));
++#define HAL_RTC_AUTO_HOUR_ALARM_DISABLE() ((RTC_CONTROL_REG) &= ~(RTC_AUTO_HOUR_ALARM_ENABLE_BIT));
++#define HAL_RTC_AUTO_DAY_ALARM_ENABLE() ((RTC_CONTROL_REG) |= (RTC_AUTO_DAY_ALARM_ENABLE_BIT));
++#define HAL_RTC_AUTO_DAY_ALARM_DISABLE() ((RTC_CONTROL_REG) &= ~(RTC_AUTO_DAY_ALARM_ENABLE_BIT));
++#define HAL_RTC_MATCH_ALARM_ENABLE() ((RTC_CONTROL_REG) |= (RTC_MATCH_ALARM_ENABLE_BIT));
++#define HAL_RTC_MATCH_ALARM_DISABLE() ((RTC_CONTROL_REG) &= ~(RTC_MATCH_ALARM_ENABLE_BIT));
++#define HAL_RTC_BATTERY_LOW_VOLTAGE_INTERRUPT_ENABLE() ((RTC_CONTROL_REG) |= (RTC_BATTERY_LOW_VOLTAGE_ENABLE_BIT));
++#define HAL_RTC_BATTERY_LOW_VOLTAGE_INTERRUPT_DISABLE() ((RTC_CONTROL_REG) &= ~(RTC_BATTERY_LOW_VOLTAGE_ENABLE_BIT));
++#define HAL_RTC_WRITE_RECORD(record) ((RTC_RECORD_REG) = (record));
++#define HAL_RTC_READ_RECORD(record) ((record) = (RTC_RECORD_REG));
++#define HAL_RTC_WRITE_MATCHED_ALARM_SECOND(second) ((RTC_SECOND_ALARM_REG) = (second & 0x3F));
++#define HAL_RTC_READ_MATCHED_ALARM_SECOND(second) ((second) = (RTC_SECOND_ALARM_REG) & 0x3F);
++#define HAL_RTC_WRITE_MATCHED_ALARM_MINUTE(minute) ((RTC_MINUTE_ALARM_REG) = (minute & 0x3F));
++#define HAL_RTC_READ_MATCHED_ALARM_MINUTE(minute) ((minute) = (RTC_MINUTE_ALARM_REG) & 0x3F);
++#define HAL_RTC_WRITE_MATCHED_ALARM_HOUR(hour) ((RTC_HOUR_ALARM_REG) = (hour & 0x1F));
++#define HAL_RTC_READ_MATCHED_ALARM_HOUR(hour) ((hour) = (RTC_HOUR_ALARM_REG) & 0x1F);
++#define HAL_RTC_READ_INTERRUPT_STATUS(status) ((status) = (RTC_INTERRUPT_STATUS_REG) & 0x3F);
++#define HAL_RTC_WRITE_INTERRUPT_STATUS(status) ((RTC_INTERRUPT_STATUS_REG) = (status) & 0x3F);
++
++#endif
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_smc.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_smc.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_smc.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_smc.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,57 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_SMC_H_
++#define _STAR_SMC_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define SMC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_SMC_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define SMC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_SMC_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++
++/*
++ * Static Memory Controller Registers
++ */
++#define SMC_MEM_BANK0_CONFIG_REG SMC_MEM_MAP_VALUE(0x00)
++#define SMC_MEM_BANK0_TIMING_REG SMC_MEM_MAP_VALUE(0x04)
++#define SMC_MEM_BANK1_CONFIG_REG SMC_MEM_MAP_VALUE(0x08)
++#define SMC_MEM_BANK1_TIMING_REG SMC_MEM_MAP_VALUE(0x0C)
++#define SMC_MEM_BANK2_CONFIG_REG SMC_MEM_MAP_VALUE(0x10)
++#define SMC_MEM_BANK2_TIMING_REG SMC_MEM_MAP_VALUE(0x14)
++#define SMC_MEM_BANK3_CONFIG_REG SMC_MEM_MAP_VALUE(0x18)
++#define SMC_MEM_BANK3_TIMING_REG SMC_MEM_MAP_VALUE(0x1C)
++
++/*
++ * macros declarations
++ */
++
++#endif // end of #ifndef _STAR_SMC_H_
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_spi.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_spi.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_spi.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_spi.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,169 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_SPI_H_
++#define _STAR_SPI_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define SPI_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_SPI_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define SPI_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_SPI_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define SPI_CONFIGURATION_REG SPI_MEM_MAP_VALUE(0x40)
++#define SPI_SERVICE_STATUS_REG SPI_MEM_MAP_VALUE(0x44)
++#define SPI_BIT_RATE_CONTROL_REG SPI_MEM_MAP_VALUE(0x48)
++#define SPI_TRANSMIT_CONTROL_REG SPI_MEM_MAP_VALUE(0x4C)
++#define SPI_TRANSMIT_BUFFER_REG SPI_MEM_MAP_VALUE(0x50)
++#define SPI_RECEIVE_CONTROL_REG SPI_MEM_MAP_VALUE(0x54)
++#define SPI_RECEIVE_BUFFER_REG SPI_MEM_MAP_VALUE(0x58)
++#define SPI_FIFO_TRANSMIT_CONFIG_REG SPI_MEM_MAP_VALUE(0x5C)
++#define SPI_FIFO_TRANSMIT_CONTROL_REG SPI_MEM_MAP_VALUE(0x60)
++#define SPI_FIFO_RECEIVE_CONFIG_REG SPI_MEM_MAP_VALUE(0x64)
++#define SPI_INTERRUPT_STATUS_REG SPI_MEM_MAP_VALUE(0x68)
++#define SPI_INTERRUPT_ENABLE_REG SPI_MEM_MAP_VALUE(0x6C)
++
++
++/*
++ * define constants macros
++ */
++#define SPI_TX_RX_FIFO_DEPTH (8)
++
++#define SPI_CH0 (0)
++#define SPI_CH1 (1)
++#define SPI_CH2 (2)
++#define SPI_CH3 (3)
++
++
++#define SPI_RXFIFO_OT_FG (0x01)
++#define SPI_TXFIFO_UT_FG (0x02)
++#define SPI_RXBUF_FULL_FG (0x04)
++#define SPI_TXBUF_EMPTY_FG (0x08)
++
++#define SPI_RXFIFO_OR_FG (0x10)
++#define SPI_TXFIFO_UR_FG (0x20)
++#define SPI_RXBUF_OR_FG (0x40)
++#define SPI_TXBUF_UR_FG (0x80)
++
++/*
++ * define Character Length Control
++ */
++#define SPI_LEN_BIT_8 (0)
++#define SPI_LEN_BIT_16 (1)
++#define SPI_LEN_BIT_24 (2)
++#define SPI_LEN_BIT_32 (3)
++
++
++/*
++ * macro declarations
++ */
++#define HAL_SPI_ENABLE_SPI() \
++{ \
++ (SPI_CONFIGURATION_REG) |= ((u_int32)0x1 << 31); \
++}
++
++#define HAL_SPI_DISABLE_SPI() \
++{ \
++ (SPI_CONFIGURATION_REG) &= ~((u_int32)0x1 << 31); \
++}
++
++#define HAL_SPI_ENABLE_DATA_SWAP() \
++{ \
++ (SPI_CONFIGURATION_REG) |= (0x1 << 24); \
++}
++
++#define HAL_SPI_DISABLE_DATA_SWAP() \
++{ \
++ (SPI_CONFIGURATION_REG) &= ~(0x1 << 24); \
++}
++
++#define HAL_SPI_TRANSMIT_DATA(tx_data) \
++{ \
++ (SPI_TRANSMIT_BUFFER_REG) = tx_data; \
++}
++
++#define HAL_SPI_RECEIVE_DATA(rx_data) \
++{ \
++ (rx_data) = SPI_RECEIVE_BUFFER_REG; \
++}
++
++#define HAL_SPI_GET_TRANSMIT_FIFO_WORDS_NUMBER(tx_fifo_words_num) \
++{ \
++ (tx_fifo_words_num) = SPI_FIFO_TRANSMIT_CONFIG_REG & 0xF; \
++}
++
++#define HAL_SPI_GET_RECEIVE_FIFO_WORDS_NUMBER(rx_fifo_words_num) \
++{ \
++ (rx_fifo_words_num) = SPI_FIFO_RECEIVE_CONFIG_REG & 0xF; \
++}
++
++#define HAL_SPI_DISABLE_ALL_INTERRUPT_SOURCES() \
++{ \
++ (SPI_INTERRUPT_ENABLE_REG) = 0; \
++}
++
++#define HAL_SPI_DISABLE_TX_FIFO_THRESHOLD_INTERRUPT() \
++{ \
++ (SPI_INTERRUPT_ENABLE_REG) &= ~(0x1 << 1); \
++}
++
++#define HAL_SPI_DISABLE_RX_FIFO_THRESHOLD_INTERRUPT() \
++{ \
++ (SPI_INTERRUPT_ENABLE_REG) &= ~(0x1 << 0); \
++}
++
++#define HAL_SPI_READ_INTERRUPT_STATUS(status) \
++{ \
++ (status) = SPI_INTERRUPT_STATUS_REG; \
++}
++
++#define HAL_SPI_CLEAR_INTERRUPT_STATUS(status) \
++{ \
++ (SPI_INTERRUPT_STATUS_REG) = (status & 0xF0); \
++}
++
++#define HAL_SPI_SET_FIFO_TRANSMIT_DELAY(delay) \
++{ \
++ (SPI_FIFO_TRANSMIT_CONTROL_REG) = (delay & 0x1F); \
++}
++
++#define STR8100_SPI_SERIAL_MODE_GENERAL 0x0
++#define STR8100_SPI_SERIAL_MODE_MICROPROCESSOR 0x1
++
++struct str8100_spi_dev_attr
++{
++ int spi_serial_mode;
++};
++
++#endif // end of #ifndef _STAR_SPI_H_
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_sys_memory_map.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_sys_memory_map.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_sys_memory_map.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_sys_memory_map.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,109 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_SYS_MEMORY_MAP_H_
++#define _STAR_SYS_MEMORY_MAP_H_
++
++
++#if 0
++#define __UBOOT__
++#else
++#define __LINUX__
++#endif
++
++
++/*
++ * sytem memory mapping after reset
++ */
++#define SYSPA_FLASH_SRAM_BANK0_BASE_ADDR 0x10000000
++#define SYSPA_FLASH_SRAM_BANK1_BASE_ADDR 0x11000000
++#define SYSPA_FLASH_SRAM_BANK2_BASE_ADDR 0x12000000
++#define SYSPA_FLASH_SRAM_BANK3_BASE_ADDR 0x13000000
++#define SYSPA_PCMCIA_ATTRIBUTE_MEMORY_BASE_ADDR 0x14000000
++#define SYSPA_PCMCIA_COMMON_MEMORY_BASE_ADDR 0x15000000
++#define SYSPA_PCMCIA_IO_SPACE_BASE_ADDR 0x16000000
++#define SYSPA_IDE_DEVICE_BASE_ADDR 0x18000000
++#define SYSPA_SDRAM_MEMORY_BASE_ADDR 0x20000000
++#define SYSPA_GDMAC_BASE_ADDR 0x60000000
++#define SYSPA_NIC_BASE_ADDR 0x70000000
++#define SYSPA_SPI_BASE_ADDR 0x71000000
++#define SYSPA_PCM_BASE_ADDR 0x71000000
++#define SYSPA_I2C_BASE_ADDR 0x71000000
++#define SYSPA_I2S_BASE_ADDR 0x71000000
++#define SYSPA_DDRC_SDRC_BASE_ADDR 0x72000000
++#define SYSPA_SMC_BASE_ADDR 0x73000000
++#define SYSPA_PCMCIA_CONTROL_BASE_ADDR 0x73000000
++#define SYSPA_IDE_CONTROLLER_BASE_ADDR 0x74000000
++#define SYSPA_MISC_BASE_ADDR 0x76000000
++#define SYSPA_POWER_MANAGEMENT_BASE_ADDR 0x77000000
++#define SYSPA_UART0_BASE_ADDR 0x78000000
++#define SYSPA_UART1_BASE_ADDR 0x78800000
++#define SYSPA_TIMER_BASE_ADDR 0x79000000
++#define SYSPA_WATCHDOG_TIMER_BASE_ADDR 0x7A000000
++#define SYSPA_RTC_BASE_ADDR 0x7B000000
++#define SYSPA_GPIOA_BASE_ADDR 0x7C000000
++#define SYSPA_GPIOB_BASE_ADDR 0x7C800000
++#define SYSPA_PCI_BRIDGE_CONFIG_DATA_BASE_ADDR 0xA0000000
++#define SYSPA_PCI_BRIDGE_CONFIG_ADDR_BASE_ADDR 0xA4000000
++#define SYSPA_PCI_IO_SPACE_BASE_ADDR 0xA8000000
++#define SYSPA_PCI_MEMORY_SPACE_BASE_ADDR 0xB0000000
++#define SYSPA_USB11_CONFIG_BASE_ADDR 0xC0000000
++#define SYSPA_USB11_OPERATION_BASE_ADDR 0xC4000000
++#define SYSPA_USB20_CONFIG_BASE_ADDR 0xC8000000
++#define SYSPA_USB20_OPERATION_BASE_ADDR 0xCC000000
++#define SYSPA_USB20_DEVICE_BASE_ADDR 0xD0000000
++#define SYSPA_VIC_BASE_ADDR 0xFFFFF000
++
++#if defined(__LINUX__)
++#define SYSVA_FLASH_BASE_ADDR 0xFF000000
++#define SYSVA_IDE_DEVICE_BASE_ADDR 0xFFF00000
++#define SYSVA_GDMAC_BASE_ADDR 0xFFF01000
++#define SYSVA_NIC_BASE_ADDR 0xFFF02000
++#define SYSVA_SPI_BASE_ADDR 0xFFF03000
++#define SYSVA_PCM_BASE_ADDR 0xFFF04000
++#define SYSVA_I2C_BASE_ADDR 0xFFF05000
++#define SYSVA_I2S_BASE_ADDR 0xFFF06000
++#define SYSVA_DDRC_SDRC_BASE_ADDR 0xFFF07000
++#define SYSVA_SMC_BASE_ADDR 0xFFF08000
++#define SYSVA_PCMCIA_CONTROL_BASE_ADDR 0xFFF09000
++#define SYSVA_IDE_CONTROLLER_BASE_ADDR 0xFFF0A000
++#define SYSVA_MISC_BASE_ADDR 0xFFF0B000
++#define SYSVA_POWER_MANAGEMENT_BASE_ADDR 0xFFF0C000
++#define SYSVA_UART0_BASE_ADDR 0xFFF0D000
++#define SYSVA_UART1_BASE_ADDR 0xFFF0E000
++#define SYSVA_TIMER_BASE_ADDR 0xFFF0F000
++#define SYSVA_WATCHDOG_TIMER_BASE_ADDR 0xFFF10000
++#define SYSVA_RTC_BASE_ADDR 0xFFF11000
++#define SYSVA_GPIOA_BASE_ADDR 0xFFF12000
++#define SYSVA_GPIOB_BASE_ADDR 0xFFF13000
++#define SYSVA_PCI_BRIDGE_CONFIG_DATA_BASE_ADDR 0xFFF14000
++#define SYSVA_PCI_BRIDGE_CONFIG_ADDR_BASE_ADDR 0xFFF15000
++#define SYSVA_USB11_CONFIG_BASE_ADDR 0xFFF16000
++#define SYSVA_USB11_OPERATION_BASE_ADDR 0xFFF17000
++#define SYSVA_USB20_CONFIG_BASE_ADDR 0xFFF18000
++#define SYSVA_USB20_OPERATION_BASE_ADDR 0xFFF19000
++#define SYSVA_USB20_DEVICE_BASE_ADDR 0xFFF1A000
++#define SYSVA_VIC_BASE_ADDR 0xFFF1B000
++#endif //__LINUX__
++
++#endif // end of #ifndef _STAR_SYS_MEMORY_MAP_H_
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_timer.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_timer.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_timer.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_timer.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,312 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_TIMER_H_
++#define _STAR_TIMER_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define TIMER_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_TIMER_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define TIMER_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_TIMER_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define TIMER1_COUNTER_REG TIMER_MEM_MAP_VALUE(0x00)
++#define TIMER1_AUTO_RELOAD_VALUE_REG TIMER_MEM_MAP_VALUE(0x04)
++#define TIMER1_MATCH_VALUE1_REG TIMER_MEM_MAP_VALUE(0x08)
++#define TIMER1_MATCH_VALUE2_REG TIMER_MEM_MAP_VALUE(0x0C)
++
++#define TIMER2_COUNTER_REG TIMER_MEM_MAP_VALUE(0x10)
++#define TIMER2_AUTO_RELOAD_VALUE_REG TIMER_MEM_MAP_VALUE(0x14)
++#define TIMER2_MATCH_VALUE1_REG TIMER_MEM_MAP_VALUE(0x18)
++#define TIMER2_MATCH_VALUE2_REG TIMER_MEM_MAP_VALUE(0x1C)
++
++#define TIMER1_TIMER2_CONTROL_REG TIMER_MEM_MAP_VALUE(0x30)
++#define TIMER1_TIMER2_INTERRUPT_STATUS_REG TIMER_MEM_MAP_VALUE(0x34)
++#define TIMER1_TIMER2_INTERRUPT_MASK_REG TIMER_MEM_MAP_VALUE(0x38)
++
++#define TIMER3_COUNTER_LOW_REG TIMER_MEM_MAP_VALUE(0x40)
++#define TIMER3_CONTROL_REG TIMER_MEM_MAP_VALUE(0x44)
++
++
++/*
++ * define constants macros
++ */
++#define TIMER1_ENABLE_BIT_INDEX 0
++#define TIMER1_CLOCK_SOURCE_BIT_INDEX 1
++#define TIMER1_OVERFLOW_ENABLE_BIT_INDEX 2
++
++#define TIMER2_ENABLE_BIT_INDEX 3
++#define TIMER2_CLOCK_SOURCE_BIT_INDEX 4
++#define TIMER2_OVERFLOW_ENABLE_BIT_INDEX 5
++
++#define TIMER1_UP_DOWN_COUNT_BIT_INDEX 9
++#define TIMER2_UP_DOWN_COUNT_BIT_INDEX 10
++
++#define TIMER1_MATCH1_INTERRUPT_BIT_INDEX 0
++#define TIMER1_MATCH2_INTERRUPT_BIT_INDEX 1
++#define TIMER1_OVERFLOW_INTERRUPT_BIT_INDEX 2
++
++#define TIMER2_MATCH1_INTERRUPT_BIT_INDEX 3
++#define TIMER2_MATCH2_INTERRUPT_BIT_INDEX 4
++#define TIMER2_OVERFLOW_INTERRUPT_BIT_INDEX 5
++
++#define TIMER3_ENABLE_BIT_INDEX 17
++#define TIMER3_RESET_BIT_INDEX 16
++
++#define TIMER_CLOCK_SOURCE_PCLK 0
++#define TIMER_CLOCK_SOURCE_EXT_CLK 1
++
++
++#define TIMER_OVERFLOW_MODE_DISABLE 0
++#define TIMER_OVERFLOW_MODE_ENABLE 1
++
++
++#define TIMER_COUNTER_MODE_UP 0
++#define TIMER_COUNTER_MODE_DOWN 1
++
++
++#define MATCH1_MASK_ENABLE (1 << 0)
++
++#define MATCH2_MASK_ENABLE (1 << 1)
++
++#define OVERFLOW_MASK_ENABLE (1 << 2)
++
++
++/*
++ * macro declarations
++ */
++#define HAL_TIMER_ENABLE_TIMER1() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) |= (1 << TIMER1_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_DISABLE_TIMER1() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) &= ~(1 << TIMER1_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_ENABLE_TIMER2() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) |= (1 << TIMER2_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_DISABLE_TIMER2() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) &= ~(1 << TIMER2_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_ENABLE_TIMER1_OVERFLOW_MODE() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) |= (1 << TIMER1_OVERFLOW_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_DISABLE_TIMER1_OVERFLOW_MODE() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) &= ~(1 << TIMER1_OVERFLOW_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_ENABLE_TIMER2_OVERFLOW_MODE() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) |= (1 << TIMER2_OVERFLOW_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_DISABLE_TIMER2_OVERFLOW_MODE() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) &= ~(1 << TIMER2_OVERFLOW_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_SET_TIMER1_DOWNCOUNT() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) |= (1 << TIMER1_UP_DOWN_COUNT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_SET_TIMER1_UPCOUNT() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) &= ~(1 << TIMER1_UP_DOWN_COUNT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_SET_TIMER2_DOWNCOUNT() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) |= (1 << TIMER2_UP_DOWN_COUNT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_SET_TIMER2_UPCOUNT() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) &= ~(1 << TIMER2_UP_DOWN_COUNT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_READ_INTERRUPT_STATUS(interrupt_status) \
++{ \
++ ((interrupt_status) = (TIMER1_TIMER2_INTERRUPT_STATUS_REG)); \
++}
++
++
++#define HAL_TIMER_WRITE_INTERRUPT_STATUS(interrupt_status) \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_STATUS_REG) = (interrupt_status)); \
++}
++
++
++#define HAL_TIMER_READ_INTERRUPT_MASK(interrupt_mask) \
++{ \
++ ((interrupt_mask) = (TIMER1_TIMER2_INTERRUPT_MASK_REG)); \
++}
++
++
++#define HAL_TIMER_WRITE_INTERRUPT_MASK(interrupt_mask) \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) = (interrupt_mask)); \
++}
++
++
++#define HAL_TIMER_MASK_TIMER1_TIMER2_ALL_INTERRUPTS() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) = (0x3F));\
++}
++
++
++#define HAL_TIMER_MASK_TIMER1_MATCH1_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) |= (1 << TIMER1_MATCH1_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_MASK_TIMER1_MATCH2_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) |= (1 << TIMER1_MATCH2_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_MASK_TIMER1_OVERFLOW_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) |= (1 << TIMER1_OVERFLOW_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_UNMASK_TIMER1_MATCH1_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) &= ~(1 << TIMER1_MATCH1_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_UNMASK_TIMER1_MATCH2_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) &= ~(1 << TIMER1_MATCH2_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_UNMASK_TIMER1_OVERFLOW_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) &= ~(1 << TIMER1_OVERFLOW_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_MASK_TIMER2_MATCH1_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) |= (1 << TIMER2_MATCH1_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_MASK_TIMER2_MATCH2_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) |= (1 << TIMER2_MATCH2_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_MASK_TIMER2_OVERFLOW_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) |= (1 << TIMER2_OVERFLOW_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_UNMASK_TIMER2_MATCH1_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) &= ~(1 << TIMER2_MATCH1_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_UNMASK_TIMER2_MATCH2_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) &= ~(1 << TIMER2_MATCH2_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_UNMASK_TIMER2_OVERFLOW_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) &= ~(1 << TIMER2_OVERFLOW_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_DISABLE_TIMER3() \
++{ \
++ ((TIMER3_CONTROL_REG) = 0); \
++}
++
++
++#define HAL_TIMER_ENABLE_TIMER3() \
++{ \
++ ((TIMER3_CONTROL_REG) = (1 << TIMER3_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_RESET_TIMER3() \
++{ \
++ ((TIMER3_CONTROL_REG) = (1 << TIMER3_RESET_BIT_INDEX)); \
++}
++
++#ifndef __ASSEMBLY__
++static inline unsigned long long HAL_TIMER_GET_TIMER3_COUNTER(void)
++{
++ unsigned long h;
++ unsigned long l;
++
++ h = TIMER3_CONTROL_REG & 0xFFFF;
++ l = TIMER3_COUNTER_LOW_REG;
++
++ return ((((unsigned long long)h) << 32) | l);
++}
++#endif
++
++#endif // end of #ifndef _STAR_TIMER_H_
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_uart.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_uart.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_uart.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_uart.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,350 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_UART_H_
++#define _STAR_UART_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#define UART_MEM_MAP_VALUE_PHY(reg_offset) (*((u32 volatile *)(SYSPA_UART0_BASE_ADDR + reg_offset)))
++#define UART_MEM_MAP_VALUE_VIR(reg_offset) (*((u32 volatile *)(SYSVA_UART0_BASE_ADDR + reg_offset)))
++
++
++#define UART1_OFFSET 0x800000 //SYS_UART1_BASE_ADDR = 0x78800000 = (UART1_OFFSET+ SYS_UART0_BASE_ADDR)
++
++#define __UART_RBR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x00)
++#define __UART_THR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x00)
++#define __UART_DLL(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x00)
++
++#define __UART_IER(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x04)
++#define __UART_DLM(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x04)
++
++#define __UART_IIR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x08)
++#define __UART_FCR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x08)
++#define __UART_PSR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x08)
++
++#define __UART_LCR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x0C)
++#define __UART_MCR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x10) //UART(n) Control Reg
++#define __UART_LSR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x14)
++#define __UART_SPR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x1C)
++
++#if defined(__UBOOT__)
++#define _UART_RBR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x00)
++#define _UART_THR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x00)
++#define _UART_DLL(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x00)
++
++#define _UART_IER(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x04)
++#define _UART_DLM(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x04)
++
++#define _UART_IIR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x08)
++#define _UART_FCR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x08)
++#define _UART_PSR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x08)
++
++#define _UART_LCR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x0C)
++#define _UART_MCR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x10) //UART(n) Control Reg
++#define _UART_LSR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x14)
++#define _UART_SPR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x1C)
++#elif defined(__LINUX__)
++#define _UART_RBR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x00)
++#define _UART_THR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x00)
++#define _UART_DLL(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x00)
++
++#define _UART_IER(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x04)
++#define _UART_DLM(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x04)
++
++#define _UART_IIR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x08)
++#define _UART_FCR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x08)
++#define _UART_PSR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x08)
++
++#define _UART_LCR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x0C)
++#define _UART_MCR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x10) //UART(n) Control Reg
++#define _UART_LSR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x14)
++#define _UART_SPR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x1C)
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define constants macros
++ */
++#define UART_INPUT_CLOCK (13000000)
++
++
++#define UART_FIFO_DEPTH 16
++
++
++#define RX_DATA_READY_INT (1 << 0)
++#define THR_EMPTY_INT (1 << 1)
++#define RX_LINE_STATUS_INT (1 << 2)
++#define MODEM_STATUS_INT (1 << 3)
++
++
++#define NO_INT_PENDING_MASK (0x1)
++#define RX_LINE_STATUS_INT_MASK (0x6)
++#define RX_DATA_READY_INT_MASK (0x4)
++#define RX_DATA_TIMEOUT_INT_MASK (0xC)
++#define THR_EMPTY_INT_MASK (0x2)
++#define MODEM_STATUS_CHANGE_MASK (0x0)
++
++
++/* FCR Register */
++#define FIFO_ENABLE (1 << 0)
++#define RX_FIFO_RESET (1 << 1)
++#define TX_FIFO_RESET (1 << 2)
++#define DMA_MODE (1 << 3)
++
++
++#define RX_FIFO_TRIGGER_LEVEL_1 (0 << 6)
++#define RX_FIFO_TRIGGER_LEVEL_4 (1 << 6)
++#define RX_FIFO_TRIGGER_LEVEL_8 (2 << 6)
++#define RX_FIFO_TRIGGER_LEVEL_14 (3 << 6)
++
++
++#define TX_FIFO_TRIGGER_LEVEL_1 (0 << 4)
++#define TX_FIFO_TRIGGER_LEVEL_3 (1 << 4)
++#define TX_FIFO_TRIGGER_LEVEL_9 (2 << 4)
++#define TX_FIFO_TRIGGER_LEVEL_13 (3 << 4)
++
++
++
++/* LCR Register */
++#define WORD_LENGTH_5 (0 << 0)
++#define WORD_LENGTH_6 (1 << 0)
++#define WORD_LENGTH_7 (2 << 0)
++#define WORD_LENGTH_8 (3 << 0)
++
++#define STOP_BIT_1 (0 << 2)
++#define STOP_BIT_1_5 (1 << 2)
++#define STOP_BIT_2 (1 << 2)
++
++#define PARITY_CHECK_NONE (0 << 3)
++#define PARITY_CHECK_EVEN (3 << 3)
++#define PARITY_CHECK_ODD (1 << 3)
++#define PARITY_CHECK_STICK_ONE (5 << 3)
++#define PARITY_CHECK_STICK_ZERO (7 << 3)
++
++#define SET_BREAK (1 << 6)
++
++#define DLAB_ENABLE (1 << 7)
++
++/* MCR Register */
++//#define UART_MCR_DTR 0x1 /* Data Terminal Ready */
++//#define UART_MCR_RTS 0x2 /* Request to Send */
++//#define UART_MCR_OUT1 0x4 /* output1 */
++//#define UART_MCR_OUT2 0x8 /* output2 or global interrupt enable */
++#define UART_MCR_LPBK 0x10 /* loopback mode */
++
++
++/* LSR Register */
++#define _DATA_READY (1 << 0)
++#define OVERRUN_ERROR (1 << 1)
++#define PARITY_ERROR (1 << 2)
++#define FRAMING_ERROR (1 << 3)
++#define BREAK_INTERRUPT (1 << 4)
++#define THR_EMPTY (1 << 5)
++#define TRANSMITTER_EMPTY (1 << 6)
++#define FIFO_DATA_ERROR (1 << 7)
++
++#define TEST_PARITY_ERROR (1 << 0)
++#define TEST_FRAMING_ERROR (1 << 1)
++#define TEST_BAUD_GEN (1 << 2)
++#define TEST_LOOPBACK_ENABLE (1 << 3)
++
++
++#define WORD_FIVE_BITS 5
++#define WORD_SIX_BITS 6
++#define WORD_SEVEN_BITS 7
++#define WORD_EIGHT_BITS 8
++
++#define NONE_PARITY 1
++#define EVEN_PARITY 2
++#define ODD_PARITY 3
++#define ONE_PARITY 4
++#define ZERO_PARITY 5
++
++#define ONE_STOP_BIT 1
++#define ONE_HALF_STOP_BIT 2
++#define TWO_STOP_BIT 3
++
++#define TX_RX_FIFO_DISABLE 0
++#define TX_RX_FIFO_ENABLE 1
++
++
++/*
++ * macros declarations
++ */
++
++#define HAL_UART_READ_DATA(idx,data) \
++{ \
++ ((data) = (_UART_RBR(idx)) & 0xFF); \
++}
++
++
++#define HAL_UART_WRITE_DATA(idx,data) \
++{ \
++ ((_UART_THR(idx)) = (data) & 0xFF); \
++}
++
++
++#define HAL_UART_ENABLE_INTERRUPT_TYPE(idx,interrupt_type) \
++{ \
++ ((_UART_IER(idx)) |= (interrupt_type & 0xF)); \
++}
++
++
++#define HAL_UART_DISABLE_INTERRUPT_TYPE(idx,interrupt_type) \
++{ \
++ ((_UART_IER(idx)) &= ~(interrupt_type & 0xF)); \
++}
++
++
++#define HAL_UART_READ_INTERRUPT_IDENTIFICATION(idx,uart_IIR) \
++{ \
++ ((uart_IIR) = (_UART_IIR(idx))); \
++}
++
++
++#define HAL_UART_CHECK_NO_INT_PENDING(idx,uart_IIR) \
++{ \
++ (((uart_IIR) & 0xF) == (NO_INT_PENDING_MASK)); \
++}
++
++
++#define HAL_UART_CHECK_RX_LINE_STATUS_INT(idx,uart_IIR) \
++ (((uart_IIR) & 0xF) == (RX_LINE_STATUS_INT_MASK))
++
++
++#define HAL_UART_CHECK_RX_DATA_READY_INT(idx,uart_IIR) \
++ (((uart_IIR) & 0xF) == (RX_DATA_READY_INT_MASK))
++
++
++#define HAL_UART_CHECK_RX_DATA_TIMEOUT_INT(idx,uart_IIR) \
++ (((uart_IIR) & 0xF) == (RX_DATA_TIMEOUT_INT_MASK))
++
++
++#define HAL_UART_CHECK_THR_EMPTY_INT(idx,uart_IIR) \
++ (((uart_IIR) & 0xF) == (THR_EMPTY_INT_MASK))
++
++
++#define HAL_UART_FIFO_ENABLE(idx) \
++{ \
++ ((_UART_FCR(idx)) |= (FIFO_ENABLE)); \
++}
++
++
++#define HAL_UART_FIFO_DISABLE(idx) \
++{ \
++ ((_UART_FCR(idx)) &= ~(FIFO_ENABLE)); \
++}
++
++
++#define HAL_UART_RESET_RX_FIFO(idx) \
++{ \
++ ((_UART_FCR(idx)) |= (RX_FIFO_RESET)); \
++}
++
++
++#define HAL_UART_RESET_TX_FIFO(idx) \
++{ \
++ ((_UART_FCR(idx)) |= (TX_FIFO_RESET)); \
++}
++
++
++#define HAL_UART_DLAB_ENABLE(idx) \
++{ \
++ ((_UART_LCR(idx)) |= (DLAB_ENABLE)); \
++}
++
++
++#define HAL_UART_DLAB_DISABLE(idx) \
++{ \
++ ((_UART_LCR(idx)) &= ~(DLAB_ENABLE)); \
++}
++
++
++#define HAL_UART_ENABLE_LOOPBACK_MODE(idx) \
++{ \
++ ((_UART_MCR(idx)) |= (UART_MCR_LPBK)); \
++}
++
++
++#define HAL_UART_DISABLE_LOOPBACK_MODE(idx) \
++{ \
++ ((_UART_MCR(idx)) &= ~(UART_MCR_LPBK)); \
++}
++
++
++#define HAL_UART_READ_LINE_STATUS(idx,uart_LSR) \
++{ \
++ ((uart_LSR) = (_UART_LSR(idx))); \
++}
++
++
++#define HAL_UART_WRITE_DLL(idx,dll_value) \
++{ \
++ HAL_UART_DLAB_ENABLE(idx); \
++ _UART_DLL(idx) = (u32)dll_value; \
++ HAL_UART_DLAB_DISABLE(idx); \
++}
++
++
++#define HAL_UART_WRITE_DLM(idx,dlm_value) \
++{ \
++ HAL_UART_DLAB_ENABLE(idx); \
++ _UART_DLM(idx) = (u32)dlm_value; \
++ HAL_UART_DLAB_DISABLE(idx); \
++}
++
++
++#define HAL_UART_WRITE_PSR(idx,psr_value) \
++{ \
++ HAL_UART_DLAB_ENABLE(idx); \
++ _UART_PSR(idx) = (u32)(psr_value & 0x3); \
++ HAL_UART_DLAB_DISABLE(idx); \
++}
++
++
++#define HAL_UART_READ_PSR(idx,psr_value) \
++{ \
++ HAL_UART_DLAB_ENABLE(idx); \
++ (psr_value) = (u32)((_UART_PSR(idx)) & 0x3); \
++ HAL_UART_DLAB_DISABLE(idx); \
++}
++
++
++#define HAL_UART_CHECK_RX_DATA_READY(idx) \
++ (((_UART_LSR(idx)) & _DATA_READY) == (_DATA_READY))
++
++
++#define HAL_UART_CHECK_TX_FIFO_EMPTY(idx) \
++ (((_UART_LSR(idx)) & THR_EMPTY) == (THR_EMPTY))
++
++
++#define HAL_UART_CHECK_TRANSMITTER_EMPTY(idx) \
++ (((_UART_LSR(idx)) & TRANSMITTER_EMPTY) == (TRANSMITTER_EMPTY))
++
++
++#endif // end of #ifndef _STAR_UART_H_
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_wdtimer.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_wdtimer.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/star_wdtimer.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/star_wdtimer.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,170 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_WATCHDOG_TIMER_H_
++#define _STAR_WATCHDOG_TIMER_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define WDTIMER_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_WATCHDOG_TIMER_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define WDTIMER_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_WATCHDOG_TIMER_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define WDTIMER_COUNTER_REG WDTIMER_MEM_MAP_VALUE(0x00)
++#define WDTIMER_AUTO_RELOAD_REG WDTIMER_MEM_MAP_VALUE(0x04)
++#define WDTIMER_COUNTER_RESTART_REG WDTIMER_MEM_MAP_VALUE(0x08)
++#define WDTIMER_CONTROL_REG WDTIMER_MEM_MAP_VALUE(0x0C)
++#define WDTIMER_STATUS_REG WDTIMER_MEM_MAP_VALUE(0x10)
++#define WDTIMER_CLEAR_REG WDTIMER_MEM_MAP_VALUE(0x14)
++#define WDTIMER_INTERRUPT_LENGTH_REG WDTIMER_MEM_MAP_VALUE(0x18)
++
++
++/*
++ * define constants macros
++ */
++#define WDTIMER_ENABLE_BIT (1 << 0)
++#define WDTIMER_SYSTEM_RESET_ENABLE_BIT (1 << 1)
++#define WDTIMER_SYSTEM_INTERRUPT_ENABLE_BIT (1 << 2)
++#define WDTIMER_EXTERNAL_SIGNAL_ENABLE_BIT (1 << 3)
++#define WDTIMER_EXTERNAL_CLOCK_ENABLE_BIT (1 << 4)
++
++
++#define WDTIMER_MAGIC_RESTART_VALUE (0x5AB9)
++
++
++/*
++ * macros declarations
++ */
++#define HAL_WDTIMER_READ_COUNTER(counter) \
++{ \
++ ((counter) = (WDTIMER_COUNTER_REG)); \
++}
++
++
++#define HAL_WDTIMER_WRITE_AUTO_RELOAD_COUNTER(counter) \
++{ \
++ ((WDTIMER_AUTO_RELOAD_REG) = (counter)); \
++}
++
++
++#define HAL_WDTIMER_READ_AUTO_RELOAD_COUNTER(counter) \
++{ \
++ ((counter) = (WDTIMER_AUTO_RELOAD_REG)); \
++}
++
++
++#define HAL_WDTIMER_ENABLE_RESTART_RELOAD() \
++{ \
++ ((WDTIMER_COUNTER_RESTART_REG) = (WDTIMER_MAGIC_RESTART_VALUE)); \
++}
++
++
++#define HAL_WDTIMER_ENABLE() \
++{ \
++ ((WDTIMER_CONTROL_REG) |= (WDTIMER_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_DISABLE() \
++{ \
++ ((WDTIMER_CONTROL_REG) &= ~(WDTIMER_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_ENABLE_SYSTEM_RESET() \
++{ \
++ ((WDTIMER_CONTROL_REG) |= (WDTIMER_SYSTEM_RESET_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_DISABLE_SYSTEM_RESET() \
++{ \
++ ((WDTIMER_CONTROL_REG) &= ~(WDTIMER_SYSTEM_RESET_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_ENABLE_SYSTEM_INTERRUPT() \
++{ \
++ ((WDTIMER_CONTROL_REG) |= (WDTIMER_SYSTEM_INTERRUPT_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_DISABLE_SYSTEM_INTERRUPT() \
++{ \
++ ((WDTIMER_CONTROL_REG) &= ~(WDTIMER_SYSTEM_INTERRUPT_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_ENABLE_EXTERNAL_SIGNAL() \
++{ \
++ ((WDTIMER_CONTROL_REG) |= (WDTIMER_EXTERNAL_SIGNAL_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_DISABLE_EXTERNAL_SIGNAL() \
++{ \
++ ((WDTIMER_CONTROL_REG) &= ~(WDTIMER_EXTERNAL_SIGNAL_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_CLOCK_SOURCE_PCLK() \
++{ \
++ ((WDTIMER_CONTROL_REG) &= ~(WDTIMER_EXTERNAL_CLOCK_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_CLOCK_SOURCE_EXTCLK() \
++{ \
++ ((WDTIMER_CONTROL_REG) |= (WDTIMER_EXTERNAL_CLOCK_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_READ_STATUS(status) \
++{ \
++ ((status) = (WDTIMER_STATUS_REG) & 0x00000001); \
++}
++
++
++#define HAL_WDTIMER_CLEAR_STATUS() \
++{ \
++ ((WDTIMER_CLEAR_REG) = (1)); \
++}
++
++
++#define HAL_WDTIMER_WRITE_INTERRUPT_LENGTH(length) \
++{ \
++ ((WDTIMER_INTERRUPT_LENGTH_REG) = (length) & 0x000000FF); \
++}
++
++
++#endif // end of #ifndef _STAR_WATCHDOG_TIMER_H_
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/system.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/system.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/system.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/system.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,50 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef __ASM_ARCH_SYSTEM_H__
++#define __ASM_ARCH_SYSTEM_H__
++
++#include <mach/star_powermgt.h>
++#include <mach/star_timer.h>
++
++static inline void arch_idle(void)
++{
++ volatile u32 dst= (*((u32 volatile *)(SYSVA_FLASH_BASE_ADDR + 0x20000)));
++
++// local_irq_enable();
++
++ cpu_do_idle();
++}
++
++static inline void arch_reset(char mode, const char *cmd)
++{
++ HAL_PWRMGT_GLOBAL_SOFTWARE_RESET();
++}
++
++extern u64 volatile str8100_counter_tick;
++static inline u64 str8100_read_counter(void)
++{
++ return (str8100_counter_tick + TIMER2_COUNTER_REG);
++}
++
++#endif
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/timex.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/timex.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/timex.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/timex.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,33 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef __ASM_ARCH_TIMEX_H__
++#define __ASM_ARCH_TIMEX_H__
++
++#if 1 // on ASIC
++#define CLOCK_TICK_RATE (43750000)
++#else // on FPGA
++#define CLOCK_TICK_RATE (13000000)
++#endif
++
++#endif /* __ASM_ARCH_TIMEX_H__ */
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/uncompress.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/uncompress.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/uncompress.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/uncompress.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,87 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef __ASM_ARCH_UNCOMPRESS_H__
++#define __ASM_ARCH_UNCOMPRESS_H__
++
++#include <mach/star_uart.h>
++
++#define flush(x)
++
++
++static void putstr(const char *s)
++{
++ while (*s) {
++ volatile unsigned int status = 0;
++
++ do {
++ status = __UART_LSR(0);
++ } while (!((status & THR_EMPTY) == THR_EMPTY));
++
++ __UART_THR(0) = *s;
++
++ if (*s == '\n') {
++ do {
++ status = __UART_LSR(0);
++ } while (!((status & THR_EMPTY) == THR_EMPTY));
++ __UART_THR(0) = '\r';
++ }
++ s++;
++ }
++}
++
++static const char * const digits="0123456789ABCDEF";
++static void ser_puts_hex8(unsigned char hex)
++{
++ char buf[3];
++ buf[0] = digits[(hex >> 4) & 0xF];
++ buf[1] = digits[hex & 0xF];
++
++ buf[2] = '\0';
++ putstr(buf);
++}
++void ser_puts_hex32(unsigned long hex)
++{
++ char buf[9];
++ int i;
++
++ for(i=7; i >= 0; i--)
++ {
++ buf[7-i] = digits[(hex >> (i * 4)) & 0xF];
++ }
++
++ buf[8] = '\0';
++ putstr(buf);
++}
++
++/*
++static void putc(int c)
++{
++ star_putstr(&c);
++}
++
++*/
++#define arch_decomp_setup()
++#define arch_decomp_wdog()
++
++#endif
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/include/mach/vmalloc.h linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/vmalloc.h
+--- linux-2.6.35.11/arch/arm/mach-str8100/include/mach/vmalloc.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/include/mach/vmalloc.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,31 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef __ASM_ARCH_VMALLOC_H__
++#define __ASM_ARCH_VMALLOC_H__
++
++//#include <linux/config.h>
++
++#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
++
++#endif
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/Kconfig linux-2.6.35.11-ts7500/arch/arm/mach-str8100/Kconfig
+--- linux-2.6.35.11/arch/arm/mach-str8100/Kconfig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/Kconfig 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,143 @@
++if ARCH_STR8100
++
++menu "STR8100 Options"
++
++config CONSOLE_BAUD_RATE
++ int "Console Baud Rate"
++ default 38400
++ help
++ set the console baudrate
++
++config VIC_INTERRUPT
++ bool "Enable Vector Interrupt Controller"
++ default y
++ help
++ enable the vector interrupt controller
++
++choice
++ prompt "DRAM SIZE"
++ default STR8100_DRAM_16M
++
++config STR8100_DRAM_16M
++ bool "16MBytes"
++
++config STR8100_DRAM_32M
++ bool "32MBytes"
++
++config STR8100_DRAM_64M
++ bool "64MBytes"
++
++endchoice
++
++if PCI
++choice
++ prompt "PCI Frequency"
++ default STR8100_PCI33M
++
++config STR8100_PCI33M
++ bool "PCI_33Mhz"
++
++config STR8100_PCI66M
++ bool "PCI_66Mhz"
++
++endchoice
++endif
++
++config STR8100_DMA
++ bool "Enable DMA Controller"
++ default n
++ help
++ enable the DMA controller
++
++config STR8100_HSDMA
++ bool "Enable HSDMA Controller"
++ default n
++ help
++ enable the HSDMA controller
++
++config STR8100_INFO
++ bool "STR8100 Infomation at /proc/str8100/info"
++
++config STR8100_USBD_REBOOT_INTHANDLER
++ tristate "USB Mass Storage Device"
++
++config STR8100_I2S
++ bool "Enable I2S sound"
++ default n
++ help
++ enable the I2S sound with /proc/str8100/i2s
++
++config STR8100_I2S_DEMO
++ tristate "Enable I2S sound demo driver"
++ default n
++ help
++ enable the I2S sound demo driver with /proc/str8100/i2s
++
++config STR8100_I2S_WM8772_DEMO
++ tristate "Enable I2S sound demo driver with WM8772"
++ default n
++ help
++ enable the I2S sound demo driver with wm8772
++
++config LE88221_CONTROL
++ bool "Legerity LE88221 Control Support"
++ depends on SPI
++
++config STR8100_PCM_LEGERITY_2PHONE_DEMO
++ tristate "2 phone PCM sound demo driver for Legerity"
++ select LE88221_CONTROL
++ default n
++
++config STR8100_RTC
++ bool "STR8100 Real Time Clock Support"
++
++config STR8100_GPIO
++ bool "STR8100 GPIO Support"
++
++config STR8100_GPIO_INTERRUPT
++ bool "Interrupt Library Support"
++ depends on STR8100_GPIO
++
++config STR8100_GPIO_GENERIC_INTERFACE
++ bool "Generic GPIO Interface Support"
++ depends on STR8100_GPIO
++ select GENERIC_GPIO
++
++comment "Flash MAP"
++config STR8100_FLASH_PART
++ bool "STR8100 flash partition setting"
++
++if STR8100_FLASH_PART
++ config ARMBOOT_OFFSET
++ hex "ARMBOOT OFFSET"
++ default 0x0
++ help
++ The armboot start offset in flash layout
++
++ config KERNEL_OFFSET
++ hex "KERNEL OFFSET"
++ default 0x40000
++ help
++ The kernel start offset in flash layout
++
++ config ROOTFS_OFFSET
++ hex "ROOTFS OFFSET"
++ default 0x140000
++ help
++ The rootfs start offset in flash layout
++
++ config CFG_OFFSET
++ hex "CFG OFFSET"
++ default 0x7f0000
++ help
++ The cfg start offset in flash layout
++endif
++
++
++comment "Third Party Support"
++
++config STR8100_EWC_SUPPORT
++ bool "EWC(802.11N) Support"
++endmenu
++
++endif
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/le88221_control.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/le88221_control.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/le88221_control.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/le88221_control.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,1037 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/interrupt.h>
++#include <linux/spi/spi.h>
++#include <linux/delay.h>
++#include <asm/semaphore.h>
++#include <mach/star_spi.h>
++
++static struct spi_device *le88221_spidev;
++static struct semaphore le88221_lock;
++
++/******************************************************************************
++* Busy Tone
++* Frequency: 480Hz + 620Hz
++* Temporal Pattern: 0.5s on/ 0.5s off
++* Event Reported After: 2 cycles of precise, 3 cycles of nonprecise
++*******************************************************************************/
++void le88221_busy_tone(struct spi_device *spi)
++{
++ u8 rx_data;
++ u8 write_data;
++ int retval;
++
++ //enable channel 1 and channel 2
++ write_data = 0x4A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x03;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set Signal generator
++ //0x00: all disabled
++ write_data = 0xDE;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set Signal generator C and D
++ // 05 1F 1C C5 06 9D 1C C5
++ //FreqC= 1311(0x051f) * 0.3662 = 480.0882 Hz
++ //AmpC = 7365(0x1cc5) *
++ //FreqD= 1693(0x069d) * 0.3662 = 619.9766 Hz
++ //AmpCD= 7365(0x1cc5) *
++ write_data = 0xD4;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x05;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x1F;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x1C;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0xC5;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x06;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x9D;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x1C;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0xC5;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set Cadence Timer
++ // 00 64 00 64 (100ms On/ 100ms Off)
++ write_data = 0xE0;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x64;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x64;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set Signal generator
++ //Eanble Signal generator cadencing, Signal generator C,D
++ write_data = 0xDE;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x8C;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set System State
++ //Activate codec, Active Low battery
++ write_data = 0x56;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x23;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++}
++
++/******************************************************************************
++* Dial Tone
++* Frequency: 350Hz + 440Hz
++* Temporal Pattern: Steady tone
++* Event Reported After: Approximately 0.75 seconds
++*******************************************************************************/
++void spi_le88221_dial_tone(struct spi_device *spi)
++{
++ u8 rx_data;
++ u8 write_data;
++ int retval;
++
++ //enable channel 1 and channel 2
++ write_data = 0x4A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x03;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set Signal generator
++ //0x00: all disabled
++ write_data = 0xDE;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set Signal generator C and D
++ // 03 BC 1C C5 04 B2 1C C5
++ write_data = 0xD4;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x03;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0xBC;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x1C;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0xC5;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x04;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0xB2;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x1C;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0xC5;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set Cadence Timer
++ // 00 00 00 00
++ write_data = 0xE0;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set Signal generator
++ //Eanble Signal generator cadencing, Signal generator C,D
++ write_data = 0xDE;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x8C;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set System State
++ //Activate codec, Active Low battery
++ write_data = 0x56;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x23;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++}
++
++void le88221_balanced_ring(struct spi_device *spi)
++{
++ u8 rx_data;
++ u8 write_data;
++ int retval;
++
++ //enable channel 1 and channel 2
++ write_data = 0x4A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x03;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set Signal generator
++ //0x00: all disabled
++ write_data = 0xDE;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Write Signal Generator A,B and Bias Param
++ // 00 00 00 00 37 42 5B 00 00 00 00
++ //0x00:Ramp has a positive slope, SG A,B out continuous, sinusoidal waves
++ //Bias : 0 (0x0000) V
++ //FreqA: 55(0x0037) * 0.3662 = 20.141 Hz
++ //AmpA : 16987(0x425B)
++ //FreqB: 0(0x0000) * 0.3662 = 0 Hz
++ //AmpB : 0(0x0000)
++ write_data = 0xD2;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x37;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x42;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x5B;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set System State
++ //Activate codec, Active Mid Battery
++ write_data = 0x56;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x2B;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set Loop Supervision Param
++ // 1B 84 B3 05
++ write_data = 0xC2;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x1B;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x84;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0xB3;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x05;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set System state
++ //Deactivate codec, Balanced ringing
++ write_data = 0x56;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x07;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++}
++
++void le88221_unbalanced_ring(struct spi_device *spi)
++{
++ u8 rx_data;
++ u8 write_data;
++ int retval;
++
++ //enable channel 1 and channel 2
++ write_data = 0x4A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x03;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set Signal generator
++ //0x00: all disabled
++ write_data = 0xDE;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set Cadence Timer
++ //01 90 03 20 (400ms on/800ms off)
++ write_data = 0xE0;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x01;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x90;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x03;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x20;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set Signal generator
++ // Enable tone generator specified by EGA...
++ write_data = 0xDE;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x80;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Write Signal Generator A,B and Bias Param
++ // 00 00 00 00 37 21 2D 00 00 00 00
++ //0x00:Ramp has a positive slope, SG A,B out continuous, sinusoidal waves
++ //Bias : 0(0x0000) V
++ //FreqA: 55(0x0037) * 0.3662 = 20.141 Hz
++ //AmpA : 8493(0x212D)
++ //FreqB: 0(0x0000) * 0.3662 = 0 Hz
++ //AmpB : 0(0x0000)
++ write_data = 0xD2;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x37;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x21;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x2D;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set System State
++ //Activate codec, Active Mid Battery
++ write_data = 0x56;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x2B;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set Loop Supervision Param
++ // 1B 84 33 05
++ write_data = 0xC2;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x1B;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x84;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x33;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x05;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++
++ //Set System state
++ //Deactivate codec, Balanced ringing
++ write_data = 0x56;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0x0A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++}
++
++u32 le88221_hook_off(struct spi_device *spi)
++{
++ u8 rx_data;
++ u8 rx_data21, rx_data22;
++ u8 write_data;
++ int retval;
++
++ /* if Hook1/2 off hook status at the same time */
++ /*
++ * Check Hook1/2 On or Off (Read Signaling Register)
++ * Hook Switch, 0:On hook , 1:Off hook
++ */
++ write_data = 0x4F;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data21, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &rx_data22, 1);
++
++ return ((rx_data21 & 0x01) && (rx_data22 & 0x01));
++}
++
++static int le88221_init_hw(struct spi_device *spi)
++{
++#if 0
++ int retval;
++ u8 write_data;
++ u8 read_data;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ if (retval < 0) {
++
++ }
++#endif
++
++#if 0
++ u8 tx_buf[] = { 0x00, 0x00, 0x00, 0x00 };
++ u8 rx_buf[] = { 0x00, 0x00, 0x00, 0x00 };
++ struct spi_transfer t[2];
++ struct spi_message m;
++
++ spi_message_init(&m);
++ memset(t, 0, (sizeof t));
++
++ t[0].tx_buf = tx_buf;
++ t[0].len = sizeof(tx_buf);
++ spi_message_add_tail(&t[0], &m);
++
++ t[1].rx_buf = rx_buf;
++ t[1].len = sizeof(rx_buf);
++ spi_message_add_tail(&t[1], &m);
++
++ down(&le88221_lock);
++ spi_sync(flash->spi, &m);
++ up(&le88221_lock);
++
++#endif
++
++ int retval;
++ u8 write_data;
++ u8 read_data;
++
++ // Hardware Reset
++ write_data = 0x04;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ // 1ms delay
++ udelay(1000);
++
++ // I/O direction
++ write_data = 0x54;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x02;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++#ifdef PRINT_REG
++ write_data = 0x55;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++#endif
++
++ // Write Device Register(Define PCLK freq,ie 2.048MHz)
++ write_data = 0x46;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x02;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ write_data = 0x47;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ // Read Revision Code Number (RCN)
++ write_data = 0x73;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ printk("Revision:0x%02x\n", read_data);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ printk("Product:0x%02x\n", read_data);
++
++ /*
++ * Write SRP register for Flyback power supply(VBL reference)
++ * Note there should be voltages on VBH, VBL, VREF after the following codes are invoked.
++ */
++ write_data = 0xE4;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x05;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x80;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++#ifdef PRINT_REG
++ write_data = 0xE5;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++#endif
++
++ // Write SRC register
++ write_data = 0xE6;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x07;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++#ifdef PRINT_REG
++ write_data = 0xE7;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++#endif
++
++ // wait 100ms delay until switing regulator is stable
++ mdelay(100);
++
++ // System State Register
++ write_data = 0x56;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++#ifdef Print_Reg
++ write_data = 0x57;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++#endif
++
++ // I/O Data Register
++ write_data = 0x52;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++#ifdef PRINT_REG
++ write_data = 0x53;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++#endif
++
++ /*
++ * For channel 1,2 operation
++ */
++ write_data = 0x4A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x03;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++#ifdef PRINT_REG
++ write_data = 0x4B;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++#endif
++
++ // Operating Functions
++ write_data = 0x60;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x3F;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++#ifdef PRINT_REG
++ write_data = 0x61;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++#endif
++
++ // Operating Conditions
++ write_data = 0x70;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++#ifdef PRINT_REG
++ write_data = 0x71;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++#endif
++
++ // Loop Supervision Parameters 19 88 A4 00 */
++ write_data = 0xC2;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x19;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x88;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xA4;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ // DC Feed Parameters 2C 08
++ write_data = 0xC6;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x2C;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x08;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ // Signal Generator A and B Parameters 00 04 25 00 37 3E C3 00 00 00 00
++ write_data = 0xD2;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x04;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x25;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x37;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x3E;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xC3;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x44;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x68;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x35;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ // Digital Impedance Scaling Network
++ write_data = 0xCA;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xEA;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++#ifdef PRINT_REG
++ write_data = 0xCB;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++#endif
++
++ // Z-Filter (FIR Only) Coefficients BA EB 2A 2C B5 25 AA 24 2C 3D
++ write_data = 0x98;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xBA;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xEB;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x2A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x2C;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xB5;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x25;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xAA;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x24;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x2C;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x3D;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ // Z-Filter (IIR Only) Coefficients AA BA 27 9F 01
++ write_data = 0x9A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xAA;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xBA;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x27;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x9F;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x01;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ // R-Filter Coefficients 2D 01 2B B0 5A 33 24 5C 35 A4 5A 3D 33 B6
++ write_data = 0x8A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x2D;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x01;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x2B;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xB0;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x5A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x33;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x24;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x5C;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x35;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xA4;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x5A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x3D;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x33;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xB6;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ // X-Filter Coefficients 3A 10 3D 3D B2 A7 6B A5 2A CE 2A 8F
++ write_data = 0x88;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x3A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x10;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x3D;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xB2;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xA7;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x6B;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xA5;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x2A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xCE;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x2A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x8F;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ // GR (Receive Gain A8 71
++ write_data = 0x82;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xA8;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x71;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ // GX (Transmit Gain) A9 F0
++ write_data = 0x80;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xA9;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xF0;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ // Voice Path Gains
++ write_data = 0x50;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++#ifdef PRINT_REG
++ write_data = 0x51;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++#endif
++
++ // B1-Filter (FIR Only) Coefficients 2A 42 22 4B 1C A3 A8 FF 8F AA F5 9F BA F0
++ write_data = 0x86;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x2A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x42;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x22;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x4B;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x1C;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xA3;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xA8;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x8F;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xAA;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xF5;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x9F;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xBA;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xF0;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ // B2-Filter (IIR Only) Coefficients 2E 01
++ write_data = 0x96;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x2E;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x01;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ //le88221_busy_tone(spi);
++ //le88221_dial_tone(spi);
++ //le88221_balanced_ring(spi);
++ le88221_unbalanced_ring(spi);
++
++#if 1
++ while (!le88221_hook_off(spi))
++ ; // do nothing
++#endif
++
++#ifdef OPEN_CH1_2
++ SPI_DEBUG("=== Configure channel 1...\n");
++ /*
++ * For channel 1 operation, Active mode
++ */
++ //Set Channel Enable and Operating Mode
++ //Channel 1 enabled, Channel 2 disabled
++ write_data = 0x4A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x01;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ //Set Signal generator
++ //0x00: all disabled
++ write_data = 0xDE;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ //Set Operating Conditions
++ //0x00 : all disabled
++ write_data = 0x70;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ //Set System state
++ //Activate codec, Active Low Battery
++ write_data = 0x56;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x23;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ /*
++ * If you want loopback test , you can TX_Time_Slot 00, TX_Time_Slot 02
++ */
++ //Set Transmit time slot
++ write_data = 0x40;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++#ifdef LEGERITY_LOOPBACK_TEST
++ //Set Receive time slot
++ write_data = 0x42;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x02;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++#else
++ //Set Receive time slot
++ write_data = 0x42;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++#endif
++
++ //Read Register Status
++ write_data = 0x4B;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ SPI_DEBUG("Read Register Status(0x4B): channel 1 %s, channel 2 %s\n",(rx_data&0x01)?"enabled":"disabled",(rx_data&0x02)?"enabled":"disabled");
++
++ //Read System State Register
++ write_data = 0x57;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ SPI_DEBUG("Read System State Register(0x57): REX=%d, METR=%d, Codec %s, POLNR=%d, SS=0x%x\n",(rx_data&(1<<7)),(rx_data&(1<<6)),(rx_data&(1<<5))?"enabled":"disabled",(rx_data&(1<<4)),(rx_data&0xF));
++
++ //Read Transmit time slot
++ write_data = 0x41;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ //Read Receive time slot
++ write_data = 0x43;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ SPI_DEBUG("=== Configure channel 2...\n");
++ /*
++ * For channel 2 operation, Active mode
++ */
++ //Set Channel Enable and Operating Mode
++ //Channel 1 disabled, Channel 2 enabled
++ write_data = 0x4A;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x02;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ //Set Signal generator
++ //0x00: all disabled
++ write_data = 0xDE;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ //Set Operating Conditions
++ //0x00 : all disabled
++ write_data = 0x70;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ //Set System state
++ //Activate codec, Active Low Battery
++ write_data = 0x56;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x23;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ /*
++ * If you want loopback test , you can TX_Time_Slot 00, TX_Time_Slot 02
++ */
++#ifdef LEGERITY_LOOPBACK_TEST
++ // Transmit time slot
++ write_data = 0x40;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x02;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ // Receive time slot
++ write_data = 0x42;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x00;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++#else
++ // Transmit time slot
++ write_data = 0x40;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x01;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++
++ // Receive time slot
++ write_data = 0x42;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0x01;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++#endif
++
++ //Read Register Status
++ write_data = 0x4B;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ SPI_DEBUG("Read Register Status(0x4B): channel 1 %s, channel 2 %s\n",(rx_data&0x01)?"enabled":"disabled",(rx_data&0x02)?"enabled":"disabled");
++
++ //Read System State Register
++ write_data = 0x57;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ SPI_DEBUG("Read System State Register(0x57): REX=%d, METR=%d, Codec %s, POLNR=%d, SS=0x%x\n",(rx_data&(1<<7)),(rx_data&(1<<6)),(rx_data&(1<<5))?"enabled":"disabled",(rx_data&(1<<4)),(rx_data&0xF));
++
++ //Read Transmit time slot
++ write_data = 0x41;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ SPI_DEBUG("Read Transmit time slot(0x41): Transmit time slot = 0x%02x\n",rx_data&0x7f);
++
++ //Read Receive time slot
++ write_data = 0x43;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ write_data = 0xFF;
++ retval = spi_write_read_sync(spi, &write_data, 1, &read_data, 1);
++ SPI_DEBUG("Read Receive time slot(0x43): Receive time slot = 0x%02x\n",rx_data&0x7f);
++#endif
++
++ return 0;
++}
++
++void Pcm_Initial_Legerity_Le88221(void)
++{
++ le88221_init_hw(le88221_spidev);
++}
++
++static int __devinit le88221_probe(struct spi_device *spi)
++{
++ le88221_spidev = spi;
++ init_MUTEX(&le88221_lock);
++ return 0;
++}
++
++static int __devexit le88221_remove(struct spi_device *spi)
++{
++ printk("le88221_remove() enter\n");
++ return 0;
++}
++
++static struct spi_driver le88221_driver = {
++ .driver = {
++ .name = "le88221",
++ .bus = &spi_bus_type,
++ .owner = THIS_MODULE,
++ },
++ .probe = le88221_probe,
++ .remove = __devexit_p(le88221_remove),
++};
++
++static int le88221_init(void)
++{
++ return spi_register_driver(&le88221_driver);
++}
++
++static void le88221_exit(void)
++{
++ spi_unregister_driver(&le88221_driver);
++}
++
++module_init(le88221_init);
++module_exit(le88221_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Star Semi");
++MODULE_DESCRIPTION("Legerity Le88221 driver");
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/Makefile linux-2.6.35.11-ts7500/arch/arm/mach-str8100/Makefile
+--- linux-2.6.35.11/arch/arm/mach-str8100/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/Makefile 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,26 @@
++#
++# Makefile for the linux kernel.
++#
++
++# Object file lists.
++
++str8100_demo_pcm_legerity_2phone-objs := str8100_demo_pcm_legerity_config_2phone.o
++str8100_demo_i2s-objs := str8100_demo_i2s_config.o
++str8100_demo_i2s_wm8772-objs := str8100_demo_i2s_wm8772_config.o
++
++obj-y := str8100_debug.o str8100_setup.o str8100_timer.o str8100_intc.o str8100_misc.o str8100_counter.o str8100_pm.o str8100_demo_dma.o
++obj-m :=
++obj-n :=
++obj- :=
++
++obj-$(CONFIG_PCI) += str8100_pci.o
++obj-$(CONFIG_STR8100_DMA) += str8100_dma.o
++obj-$(CONFIG_STR8100_HSDMA) += str8100_hsdma.o
++obj-$(CONFIG_STR8100_I2S) += str8100_i2s.o
++obj-$(CONFIG_STR8100_I2S_DEMO) += str8100_demo_i2s.o
++obj-$(CONFIG_STR8100_I2S_WM8772_DEMO) += str8100_demo_i2s_wm8772.o
++obj-$(CONFIG_LE88221_CONTROL) += le88221_control.o
++obj-$(CONFIG_STR8100_PCM_LEGERITY_2PHONE_DEMO) += str8100_demo_pcm_legerity_2phone.o
++obj-$(CONFIG_STR8100_RTC) += str8100_rtc.o
++obj-$(CONFIG_STR8100_GPIO) += str8100_gpio.o
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/Makefile.boot linux-2.6.35.11-ts7500/arch/arm/mach-str8100/Makefile.boot
+--- linux-2.6.35.11/arch/arm/mach-str8100/Makefile.boot 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/Makefile.boot 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,11 @@
++# Note: the following conditions must always be true:
++# ZRELADDR == virt_to_phys(TEXTADDR)
++# PARAMS_PHYS must be within 4MB of ZRELADDR
++# INITRD_PHYS must be in RAM
++
++ zreladdr-y := 0x00008000
++params_phys-y := 0x00000100
++initrd_phys-y := 0x00C00000
++# scott.test
++kernel_phys-y := 0x00600000
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_counter.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_counter.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_counter.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_counter.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,215 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/interrupt.h>
++#include <linux/time.h>
++#include <linux/init.h>
++#include <linux/timex.h>
++#include <linux/proc_fs.h>
++#include <linux/module.h>
++
++#include <mach/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/uaccess.h>
++#include <asm/mach/irq.h>
++#include <asm/mach/time.h>
++
++u64 volatile str8100_counter_tick;
++EXPORT_SYMBOL(str8100_counter_tick);
++
++static struct proc_dir_entry *str8100_counter_proc_entry;
++
++#if 0
++// this is defined in include/asm/arch-str8100/system.h
++u64 str8100_read_counter(void)
++{
++ return (str8100_counter_tick + TIMER2_COUNTER_REG);
++}
++EXPORT_SYMBOL(str8100_read_counter);
++#endif
++
++static int match1=0;
++static int match2=0;
++static void str8100_setup_counter(void)
++{
++ unsigned long control_value;
++ unsigned long mask_value;
++ unsigned long val;
++
++ control_value = TIMER1_TIMER2_CONTROL_REG;
++ mask_value = TIMER1_TIMER2_INTERRUPT_MASK_REG;
++
++ TIMER2_COUNTER_REG = 0;
++ TIMER2_AUTO_RELOAD_VALUE_REG = 0;
++ TIMER2_MATCH_VALUE1_REG = match1;
++ TIMER2_MATCH_VALUE2_REG = match2;
++
++ // Clock Source: PCLK
++ control_value &= ~(1 << TIMER2_CLOCK_SOURCE_BIT_INDEX);
++
++ // UP Count Mode
++ control_value &= ~(1 << TIMER2_UP_DOWN_COUNT_BIT_INDEX);
++
++ // un-mask match1, match2, and overflow interrupt sources
++ mask_value &= ~(0x7 << 3);
++
++ // mask match1, match2 interrupt sources
++ //mask_value |= (0x3 << 3);
++ val=0;
++ if(!match1) val|=0x1;
++ if(!match2) val|=0x2;
++ mask_value |= (val<< 3);
++
++ TIMER1_TIMER2_CONTROL_REG = control_value;
++ TIMER1_TIMER2_INTERRUPT_MASK_REG = mask_value;
++}
++
++static void str8100_counter_enable(void)
++{
++ unsigned long control_value;
++
++ control_value = TIMER1_TIMER2_CONTROL_REG;
++
++ // enable overflow mode
++ control_value |= (1 << TIMER2_OVERFLOW_ENABLE_BIT_INDEX);
++
++ // enable the timer
++ control_value |= (1 << TIMER2_ENABLE_BIT_INDEX);
++
++ TIMER1_TIMER2_CONTROL_REG = control_value;
++}
++
++static void str8100_counter_disable(void)
++{
++ unsigned long control_value;
++
++ control_value = TIMER1_TIMER2_CONTROL_REG;
++
++ // enable overflow mode
++ control_value &= ~(1 << TIMER2_OVERFLOW_ENABLE_BIT_INDEX);
++
++ // enable the timer
++ control_value &= ~(1 << TIMER2_ENABLE_BIT_INDEX);
++
++ TIMER1_TIMER2_CONTROL_REG = control_value;
++}
++
++/*
++ * IRQ handler for the timer
++ */
++static irqreturn_t
++str8100_counter_interrupt(int irq, void *dev_id /*, struct pt_regs *regs*/)
++{
++#ifndef CONFIG_VIC_INTERRUPT
++ // clear counter interrrupt status
++ TIMER1_TIMER2_INTERRUPT_STATUS_REG &= ~(1 << TIMER2_OVERFLOW_INTERRUPT_BIT_INDEX);
++#endif
++ str8100_counter_tick += (1ULL << 32);
++ if(match1){
++ TIMER2_MATCH_VALUE1_REG=TIMER2_COUNTER_REG+match1;
++ TIMER1_TIMER2_INTERRUPT_MASK_REG |= (0x1<<3);
++ }
++ if(match2){
++ TIMER2_MATCH_VALUE2_REG=TIMER2_COUNTER_REG+match2;
++ TIMER1_TIMER2_INTERRUPT_MASK_REG |= (0x2<<3);
++ }
++ return IRQ_HANDLED;
++}
++
++static struct irqaction str8100_counter_irq = {
++ .name = "STR8100 Counter Tick",
++ /* scott.patch */
++ .flags = IRQF_DISABLED | IRQF_TIMER,
++ .handler = str8100_counter_interrupt,
++};
++
++static int str8100_counter_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
++{
++ return sprintf(page, "str8100_counter_tick: %llu\n", str8100_counter_tick + TIMER2_COUNTER_REG);
++}
++
++
++static int
++str8100_counter_write_proc(struct file *file, const char __user *buffer,
++ unsigned long count, void *data)
++{
++ char *str;
++ char *cmd;
++
++ if (count > 0) {
++ str = (char *)buffer,
++ cmd = strsep(&str, "\t \n");
++ if (!cmd) goto err_out;
++ if (strcmp(cmd, "match1") == 0) {
++ u32 addr;
++ char *arg = strsep(&str, "\t \n");
++ if (!arg) goto err_out;
++ addr = simple_strtoul(arg, &arg, 10);
++ match1=addr;
++
++ } else if (strcmp(cmd, "match2") == 0) {
++ u32 addr;
++ char *arg = strsep(&str, "\t \n");
++ if (!arg) goto err_out;
++ addr = simple_strtoul(arg, &arg, 10);
++ match2=addr;
++
++
++ } else {
++ goto err_out;
++ }
++ }
++ if(match1){
++ TIMER2_MATCH_VALUE1_REG=TIMER2_COUNTER_REG+match1;
++ TIMER1_TIMER2_INTERRUPT_MASK_REG |= (0x1<<3);
++ }
++ if(match2){
++ TIMER2_MATCH_VALUE2_REG=TIMER2_COUNTER_REG+match2;
++ TIMER1_TIMER2_INTERRUPT_MASK_REG |= (0x2<<3);
++ }
++
++ return count;
++
++err_out:
++ return -EFAULT;
++}
++/*
++ * Set up timer interrupt, and return the current time in seconds.
++ */
++int __init str8100_counter_setup(void)
++{
++
++ str8100_setup_counter();
++ setup_irq(INTC_TIMER2_BIT_INDEX, &str8100_counter_irq);
++ str8100_counter_enable();
++ str8100_counter_proc_entry = create_proc_entry("str8100/counter", S_IFREG | S_IRUGO, NULL);
++ if (str8100_counter_proc_entry) {
++ str8100_counter_proc_entry->read_proc = str8100_counter_read_proc;
++ str8100_counter_proc_entry->write_proc = str8100_counter_write_proc;
++ }
++
++ return 0;
++}
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_debug.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_debug.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_debug.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_debug.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,47 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/types.h>
++#include <mach/hardware.h>
++
++void debug_puts(const char *s)
++{
++ while (*s) {
++ volatile unsigned int status = 0;
++ do {
++ status = _UART_LSR(0);
++ } while (!((status & THR_EMPTY) == THR_EMPTY));
++
++ _UART_THR(0) = *s;
++
++ if (*s == '\n') {
++ do {
++ status = _UART_LSR(0);
++ } while (!((status & THR_EMPTY) == THR_EMPTY));
++
++ _UART_THR(0) = '\r';
++ }
++ s++;
++ }
++}
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_demo_dma.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_demo_dma.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_demo_dma.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_demo_dma.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,576 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++//Options
++//#define DEBUG_PRINT
++//=================================================================================
++
++#include <linux/kernel.h> /* printk() */
++#include <linux/delay.h>
++#include <mach/star_demo_dma.h>
++#include <mach/star_i2s.h>
++#include <mach/star_powermgt.h>
++#include <mach/star_misc.h>
++#include <mach/star_gpio.h>
++
++#ifdef DEBUG_PRINT
++#undef DEBUG_PRINT
++//#define DEBUG_PRINT(arg...) if(debug) printk(arg);
++#define DEBUG_PRINT printk
++#else
++#define DEBUG_PRINT(arg...)
++#endif
++
++
++/******************************************************************************
++ *
++ * FUNCTION: Hal_Dmac_Get_Channel_Transfer_Unit_Number
++ * PURPOSE:
++ *
++ ******************************************************************************/
++u32 Hal_Dmac_Get_Channel_Transfer_Unit_Number(u32 byte_size, u32 src_width)
++{
++ u32 transfer_unit_num;
++
++
++ if (src_width == DMAC_CH_SRC_WIDTH_8_BITS) // 8-bit
++ {
++ transfer_unit_num = byte_size;
++ }
++ else if (src_width == DMAC_CH_SRC_WIDTH_16_BITS) // 16-bit
++ {
++ if (byte_size % 2)
++ {
++ transfer_unit_num = (byte_size >> 1) + 1;
++ }
++ else
++ {
++ transfer_unit_num = (byte_size >> 1);
++ }
++ }
++ else if (src_width == DMAC_CH_SRC_WIDTH_32_BITS) // 32-bit
++ {
++ if (byte_size % 4)
++ {
++ transfer_unit_num = (byte_size >> 2) + 1;
++ }
++ else
++ {
++ transfer_unit_num = (byte_size >> 2);
++ }
++ }
++ else
++ {
++ transfer_unit_num = 0;
++ }
++
++ return transfer_unit_num;
++}
++EXPORT_SYMBOL(Hal_Dmac_Get_Channel_Transfer_Unit_Number);
++
++
++void Hal_Dmac_Configure_DMA_Handshake(DMAC_HARDWARE_HANDSHAKE_OBJ_T *dmac_obj)
++{
++ u32 channel_control, ch;
++
++ /*
++ * Configure DMA controller for UART's hardware DMA handshake mode
++ */
++
++ /*
++ * Stop mplayer will also stop PCM if disable GDMA Controller.
++ * Changed to disable corresponding channels only.
++ */
++ //HAL_DMAC_DISABLE();
++ for (ch = 0; ch < DMAC_MAX_CHANNEL_NUM; ch++)
++ {
++ if (dmac_obj->channel_id & DMAC_CH_ID(ch))
++ HAL_DMAC_DISABLE_CHANNEL(ch);
++ }
++
++//#if (ENDIAN_MODE == BIG_ENDIAN)
++#if 0
++ /*Set Master0 and Master 1 endianness as Big Endian*/
++ HAL_DMAC_SET_MASTER0_BIG_ENDIAN();
++ HAL_DMAC_SET_MASTER1_BIG_ENDIAN();
++#else
++ /*Set Master0 and Master 1 endianness as Little Endian*/
++ HAL_DMAC_SET_MASTER0_LITTLE_ENDIAN();
++ HAL_DMAC_SET_MASTER1_LITTLE_ENDIAN();
++#endif
++
++ //Clear TC interrupt status
++ HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(0xFF); // 8 channels
++
++ //Clear Errot/Abort interrupt status
++ HAL_DMAC_CLEAR_ERROR_ABORT_INTERRUPT_STATUS(0x00FF00FF); // 8 channels
++
++ /*
++ * Configure DMA's channel control
++ */
++ channel_control = ((DMAC_CH_TC_MASK_DISABLE << 31) | \
++ ((dmac_obj->target_select&0xf) << 25) | \
++ (DMAC_CH_PRI_LEVEL_3 << 22) | \
++ (DMAC_CH_PROT3_NON_CACHEABLE << 21) | \
++ (DMAC_CH_PROT2_NON_BUFFERABLE << 20) | \
++ (DMAC_CH_PROT1_PRIVILEGED_MODE << 19) | \
++ ((dmac_obj->src_burst_size&0x7) << 16) | \
++ ((dmac_obj->src_width&0x7) << 11) | \
++ ((dmac_obj->dst_width&0x7) << 8) | \
++ (DMAC_CH_MODE_HW_HANDSHAKE << 7) | \
++ ((dmac_obj->srcad_ctl&0x3) << 5) | \
++ ((dmac_obj->dstad_ctl&0x3) << 3) | \
++ (dmac_obj->src_master << 2) | \
++ (dmac_obj->dst_master << 1) | \
++ (DMAC_CH_DISABLE));
++
++#if 0
++ // for testing only
++ if (dmac_obj->llp_addr != 0)
++ {
++ /*
++ * For LLP hardware handshaking with at least one descriptors, disable TC interrupt
++ * of the first descriptor.
++ */
++ channel_control |= (DMAC_CH_TC_MASK_ENABLE << 31);
++ }
++#endif
++ for (ch = 0; ch < DMAC_MAX_CHANNEL_NUM; ch++)
++ {
++ if (dmac_obj->channel_id & DMAC_CH_ID(ch))
++ {
++ /*
++ * Configure channel's CSR register
++ */
++ DMAC_CH_CSR_REG(ch) = channel_control & 0xFFFFFFFE; //Disable CH(n) DMA
++
++ /*
++ * Configure channel's CFG register: disable channel abort interrupt,
++ * enable channel error and terminal count interrupts.
++ */
++ DMAC_CH_CFG_REG(ch) |= (0x07);
++ DMAC_CH_CFG_REG(ch) &= ~((0x3));
++ }
++ }
++
++ for (ch = 0; ch < DMAC_MAX_CHANNEL_NUM; ch++)
++ {
++ if (dmac_obj->channel_id & DMAC_CH_ID(ch))
++ {
++ //Set Src address register
++ DMAC_CH_SRC_ADDR_REG(ch)= dmac_obj->src_addr;
++
++ //Set Dst address register
++ DMAC_CH_DST_ADDR_REG(ch)= dmac_obj->dst_addr;
++
++ //Set Transfer Number
++ if (dmac_obj->src_width == DMAC_CH_SRC_WIDTH_8_BITS)
++ {
++ DMAC_CH_SIZE_REG(ch) = (dmac_obj->transfer_bytes & 0x0FFF);
++ DEBUG_PRINT("%s: 8-bits transfer_bytes=%d, DMAC_CH_SIZE_REG(%d)=%.8x\n",__FUNCTION__,dmac_obj->transfer_bytes,ch,DMAC_CH_SIZE_REG(ch));
++ }
++ else if (dmac_obj->src_width == DMAC_CH_SRC_WIDTH_16_BITS)
++ {
++ DMAC_CH_SIZE_REG(ch) = ((dmac_obj->transfer_bytes >> 1) + (dmac_obj->transfer_bytes % 2)) & 0x0FFF;
++ DEBUG_PRINT("%s: 16-bits transfer_bytes=%d, DMAC_CH_SIZE_REG(%d)=%.8x\n",__FUNCTION__,dmac_obj->transfer_bytes,ch,DMAC_CH_SIZE_REG(ch));
++ }
++ else if (dmac_obj->src_width == DMAC_CH_SRC_WIDTH_32_BITS)
++ {
++ DMAC_CH_SIZE_REG(ch) = ((dmac_obj->transfer_bytes >> 2) + ((dmac_obj->transfer_bytes % 4) ? 1 : 0)) & 0x0FFF;
++ DEBUG_PRINT("%s: 32-bits transfer_bytes=%d, DMAC_CH_SIZE_REG(%d)=%.8x\n",__FUNCTION__,dmac_obj->transfer_bytes,ch,DMAC_CH_SIZE_REG(ch));
++ }
++ else
++ {
++ DEBUG_PRINT("%s: dead\n",__FUNCTION__);
++ while (1);
++ }
++
++ //Enable Channel DMA transfer
++ HAL_DMAC_ENABLE_CHANNEL(ch);
++
++ //Set Channel's Sync logic
++ DMAC_SYNC_REG |= (1 << ch);
++
++ /*
++ * Configure channel LLP if LLP is enabled
++ */
++ DMAC_CH_LLP_REG(ch) = (dmac_obj->llp_addr == 0) ? 0 : (dmac_obj->llp_addr & 0xFFFFFFFC);
++ }
++ }
++}
++EXPORT_SYMBOL(Hal_Dmac_Configure_DMA_Handshake);
++
++irqreturn_t str8100_dma_err_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs)
++{
++ u32 dma_error_status,dma_ch;
++printk("%s: this_irq=%d\n",__FUNCTION__,this_irq);
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(this_irq);
++ //todo:
++
++ HAL_DMAC_READ_ERROR_ABORT_INTERRUPT_STATUS(dma_error_status);
++ for (dma_ch = 0; dma_ch < DMAC_MAX_CHANNEL_NUM; dma_ch++)
++ {
++ if (dma_error_status & DMAC_CH_ID(dma_ch))
++ {
++ printk("%s: this_irq=%d, DMA channel error on ch %d\n",__FUNCTION__,this_irq,dma_ch);
++ HAL_DMAC_DISABLE_CHANNEL(dma_ch);
++ HAL_DMAC_CLEAR_ERROR_ABORT_INTERRUPT_STATUS(DMAC_CH_ID(dma_ch));
++ }
++ }
++
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq);
++
++ return IRQ_HANDLED;
++}
++EXPORT_SYMBOL(str8100_dma_err_irq_handler);
++
++static const u32 rate_map[3][4]={ {48000, 0, 0, 0},
++ {44100,22050,11025, 5512},
++ {32000,16000, 8000, 0}};
++ /*
++ * Configure I2S related parameters
++ */
++/*//#define i2s_sdata_width I2S_DATA_16_BIT
++#define i2s_sdata_width I2S_DATA_32_BIT
++#define i2s_mode I2S_SLAVE_MODE
++//#define i2s_mode I2S_MASTER_MODE
++#define i2s_tranfer_timing_ctrl I2S_I2S_MODE
++//#define i2s_tranfer_timing_ctrl I2S_RJF_MODE
++//#define i2s_tranfer_timing_ctrl I2S_LJF_MODE
++#define i2s_sclk_mode I2S_CLOCK_CONTINUOUS_MODE
++//#define i2s_sclk_mode I2S_CLOCK_256S_MODE
++*/
++
++//int str8100_i2s_init(sampling_rate,I2S_DATA_32_BIT, I2S_MASTER_MODE, I2S_I2S_MODE, I2S_CLOCK_256S_MODE);
++//int str8100_i2s_init(sampling_rate,I2S_DATA_32_BIT, I2S_SLAVE_MODE, I2S_I2S_MODE, I2S_CLOCK_CONTINUOUS_MODE);
++
++int str8100_i2s_init(int sampling_rate,u32 i2s_sdata_width, u32 i2s_mode,
++ u32 i2s_tranfer_timing_ctrl, u32 i2s_sclk_mode){
++ u32 tmp;
++ u32 i/*clock*/ ,j,i2s_src_clk_div;
++ DEBUG_PRINT("%s: sampling_rate=%d\n",__FUNCTION__,sampling_rate);
++
++ for(i=0;i<3;i++)
++ for(j=0;j<4;j++)
++ if(rate_map[i][j]==sampling_rate) goto rate_match;
++
++rate_match:
++ if(i==3&&j==4) {
++ printk("%s: unsupported sampling rate (%d)\n",__FUNCTION__,sampling_rate);
++ return -1;
++ }else{
++ DEBUG_PRINT("%s: clock=%d,src_clk_div=%d\n",__FUNCTION__,i,j);
++ }
++
++ i2s_src_clk_div=j;
++
++ /*
++ * Select I2S clock source; here we use 48K sampling rate for the target file.
++ */
++
++// switch(sampling_rate){
++ switch(i/*clock*/){
++ case 0/*48000*/:
++ HAL_PWRMGT_I2S_CLOCK_SOURCE_12288000HZ();
++ break;
++ case 1/*44100*/:
++ HAL_PWRMGT_I2S_CLOCK_SOURCE_11289600HZ();
++ break;
++ case 2/*32000*/:
++ HAL_PWRMGT_I2S_CLOCK_SOURCE_8192000HZ();
++ break;
++ }
++
++ HAL_PWRMGT_CONFIGURE_CLOCK_OUT_PIN(11,0);
++
++ // Enable I2S pins
++ HAL_MISC_ENABLE_I2S_PINS();
++
++ // Enable I2S clock
++ HAL_PWRMGT_ENABLE_I2S_CLOCK();
++
++ //Hal_Pwrmgt_Software_Reset(PWRMGT_P2S_SOFTWARE_RESET_BIT_INDEX);
++
++
++ /*
++ * Configure I2S to be Master & Transmitter
++ * Note the I2S's WS Clock is derived from Clock & Power Management Functional
++ * Block!!
++ */
++ I2S_CONFIGURATION_REG =
++ (i2s_sdata_width << 0) |
++ (i2s_src_clk_div << 4) |
++ (0x1 << 12) | /* Use I2SSD as data output pin and GPIOA[3] as data input pin for full-duplex mode */
++ (0x0 << 15) | /* Disable clock phase invert */
++ (0x0 << 24) | /* Disable I2S data swap */
++ ((i2s_sclk_mode & 0x1) << 25) |
++ ((i2s_tranfer_timing_ctrl & 0x3) << 26) |
++ (0x0 << 29) | /* Enable I2S Transmitter */
++ (i2s_mode << 30) |
++ (0x0 << 31); /* Disable I2S */
++
++ //Enable none while initializing
++ I2S_INTERRUPT_ENABLE_REG = 0x0;
++// I2S_INTERRUPT_ENABLE_REG |= (I2S_TXBF_R_UR_FLAG | I2S_TXBF_L_UR_FLAG | I2S_TXBF_R_EMPTY_FLAG | I2S_TXBF_L_EMPTY_FLAG);
++
++ // Clear spurious interrupt sources
++ I2S_INTERRUPT_STATUS_REG = 0xF0;
++
++ tmp = I2S_LEFT_RECEIVE_DATA_REG;
++ tmp = I2S_RIGHT_RECEIVE_DATA_REG;
++
++ // Disable I2S
++ HAL_I2S_DISABLE_I2S();
++
++ return 0;
++}
++EXPORT_SYMBOL(str8100_i2s_init);
++
++
++
++/*
++ * Define which GPIO Pins will serve as Winbond's W571C161's SSP (Serial Setup
++ * Potr) Pins which consist of SSPEN, SSPCLK, and SSPTR.
++ * Note these three pins are uni-directional output pins:
++ * SSPEN : mapping to COM1 pin
++ * SSPCLK : mapping to COM2 pin
++ * SSPTR : mapping to COM3 pin
++ */
++//#define SSPEN_GPIO_INDEX (3) /* use GPIOA #3 as WM8772's COM1 */
++#define SSPEN_GPIO_INDEX (0) /* use GPIOA #3 as WM8772's COM1 */
++
++#define SSPCLK_GPIO_INDEX (1) /* use GPIOA #4 as WM8772's COM2 */
++
++#define SSPTR_GPIO_INDEX (2) /* use GPIOA #5 as WM8772's COM3 */
++
++#define SWITCH_GPIO_INDEX (7) /* use GPIOA #6 as WM8772's Transfer or Receiver */
++
++/*
++ * Macro-defines to "output" SSPEN, SSPCLK and SSPTR
++ */
++#define SSPEN_HIGH() HAL_GPIOA_SET_DATA_OUT_HIGH(0x1 << SSPEN_GPIO_INDEX)
++
++#define SSPEN_LOW() HAL_GPIOA_SET_DATA_OUT_LOW(0x1 << SSPEN_GPIO_INDEX)
++
++
++#define SSPCLK_HIGH() HAL_GPIOA_SET_DATA_OUT_HIGH(0x1 << SSPCLK_GPIO_INDEX)
++
++#define SSPCLK_LOW() HAL_GPIOA_SET_DATA_OUT_LOW(0x1 << SSPCLK_GPIO_INDEX)
++
++
++#define SSPTR_HIGH() HAL_GPIOA_SET_DATA_OUT_HIGH(0x1 << SSPTR_GPIO_INDEX)
++
++#define SSPTR_LOW() HAL_GPIOA_SET_DATA_OUT_LOW(0x1 << SSPTR_GPIO_INDEX)
++
++
++/*
++ * SWITCH TX/RX For ASIC VER.
++ */
++#define SSPSW_HIGH() HAL_GPIOA_SET_DATA_OUT_HIGH(0x1 << SWITCH_GPIO_INDEX)
++
++#define SSPSW_LOW() HAL_GPIOA_SET_DATA_OUT_LOW(0x1 << SWITCH_GPIO_INDEX)
++
++/*
++ * Macro-defines to configure the "directions" of SSPEN, SSPCLK and SSPTR
++ */
++#define SSPEN_DIR_OUT() HAL_GPIOA_SET_DIRECTION_OUTPUT(0x1 << SSPEN_GPIO_INDEX)
++
++#define SSPCLK_DIR_OUT() HAL_GPIOA_SET_DIRECTION_OUTPUT(0x1 << SSPCLK_GPIO_INDEX)
++
++#define SSPTR_DIR_OUT() HAL_GPIOA_SET_DIRECTION_OUTPUT(0x1 << SSPTR_GPIO_INDEX)
++
++//For ASIC
++#define SSPSW_DIR_OUT() HAL_GPIOA_SET_DIRECTION_OUTPUT(0x1 << SWITCH_GPIO_INDEX)
++
++
++#define TIME_FACTOR (20)
++
++/*
++ * Function prototype declaration
++ */
++u32 I2s_Gpio_SSP_Initialise(void);
++
++void I2s_Gpio_SSP_Write(u16);
++
++void I2s_Gpio_SSP_Switch_To_Record_Data(void);
++
++void I2s_Gpio_SSP_Switcg_To_Playback_Data(void);
++
++
++/******************************************************************************
++ *
++ * FUNCTION: I2s_Gpio_SSP_Initialise
++ * PURPOSE:
++ *
++ ******************************************************************************/
++u32 I2s_Gpio_SSP_Initialise(void)
++{
++
++ // Enable GPIO clock
++ HAL_PWRMGT_ENABLE_GPIO_CLOCK();
++
++ // Perform GPIO software reset
++// Hal_Pwrmgt_Software_Reset(PWRMGT_GPIO_SOFTWARE_RESET_BIT_INDEX);
++
++
++ /*
++ * 1. Determine/Check which three GPIO pins will serve as SSPEN, SSPCLK and
++ * SSPTR pins
++ * 2. At initialization :
++ * SSPEN : Output Direction, High state
++ * SSPCLK : Output Direction, Low state
++ * SSPTR : Output Direction, Low state
++ */
++ SSPEN_DIR_OUT();
++
++ SSPCLK_DIR_OUT();
++
++ SSPTR_DIR_OUT();
++
++
++ /*
++ * Set SSPEN to be HIGH and SSPCLK/SSPTR be be LOW to "Free" SSP Bus
++ */
++
++ SSPEN_HIGH();
++
++#if 1
++ SSPCLK_LOW();
++
++ SSPTR_LOW();
++#else
++ SSPCLK_HIGH();
++
++ SSPTR_HIGH();
++#endif
++
++ return 0; // for success indication
++}
++EXPORT_SYMBOL(I2s_Gpio_SSP_Initialise);
++
++
++/******************************************************************************
++ *
++ * FUNCTION: I2s_Gpio_SSP_Write
++ * PURPOSE:
++ *
++ ******************************************************************************/
++void I2s_Gpio_SSP_Write(u16 reg_data)
++{
++ unsigned long cpsr_flags;
++ u32 volatile ii;
++
++
++ local_irq_save(cpsr_flags);
++
++ SSPEN_HIGH();
++
++ SSPCLK_LOW();
++
++ SSPTR_LOW();
++
++ ndelay(2 * TIME_FACTOR);
++
++ SSPEN_LOW();
++
++ // Output D15 ~ D0 of reg_data
++ for (ii = 0; ii < 16; ii++)
++ {
++ SSPCLK_LOW();
++
++ ndelay(3 * TIME_FACTOR);//setup time
++
++ if (reg_data & 0x8000)
++ {
++ SSPTR_HIGH();
++ }
++ else
++ {
++ SSPTR_LOW();
++ }
++
++ ndelay(5 * TIME_FACTOR);
++
++ SSPCLK_HIGH();
++
++ ndelay(5 * TIME_FACTOR);//hold time
++
++ SSPCLK_LOW();
++
++ ndelay(3 * TIME_FACTOR);
++
++ // Shift left by one bit to get the next data bit
++ reg_data <<= 1;
++ }
++
++ SSPEN_HIGH();
++
++ SSPCLK_LOW();
++
++ ndelay(1 * TIME_FACTOR);
++
++ // for testing only
++#if 0
++ SSPCLK_HIGH();
++
++// SSPTR_HIGH();
++#endif
++
++
++ // Delay some time
++// for (ii = 0; ii < 0x100000; ii++);
++
++ local_irq_restore(cpsr_flags);
++}
++EXPORT_SYMBOL(I2s_Gpio_SSP_Write);
++
++
++/******************************************************************************
++ *
++ * FUNCTION: I2s_Gpio_SSP_Switch_To_Record_Data
++ * PURPOSE:
++ *
++ ******************************************************************************/
++void I2s_Gpio_SSP_Switch_To_Record_Data(void)
++{
++ SSPSW_DIR_OUT();
++
++ SSPSW_HIGH();
++}
++
++
++/******************************************************************************
++ *
++ * FUNCTION: I2s_Gpio_SSP_Switcg_To_Playback_Data
++ * PURPOSE:
++ *
++ ******************************************************************************/
++void I2s_Gpio_SSP_Switcg_To_Playback_Data(void)
++{
++ SSPSW_DIR_OUT();
++
++ SSPSW_LOW();
++}
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_demo_i2s_config.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_demo_i2s_config.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_demo_i2s_config.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_demo_i2s_config.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,471 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++
++#include <linux/kernel.h> /* printk() */
++#include <linux/errno.h> /* error codes */
++#include <linux/types.h> /* size_t */
++#include <linux/proc_fs.h>
++#include <linux/interrupt.h>
++#include <linux/pci.h>
++
++#include <asm/system.h> /* cli(), *_flags */
++#include <asm/uaccess.h> /* copy_*_user */
++
++#include <mach/star_powermgt.h>
++#include <mach/star_misc.h>
++#include <mach/star_i2s.h>
++#include <mach/star_demo_dma.h>
++
++MODULE_AUTHOR("Mac Lin");
++MODULE_LICENSE("Dual BSD/GPL");
++
++
++#define CONFIG_I2S_USE_DMA
++//Debug = left only
++#define DEBUG
++
++static struct proc_dir_entry *star_i2s_proc_entry=NULL;
++static u32 sampling_rate=44100;
++static u32 sample_size=16;
++
++module_param(sampling_rate, int, 0);
++MODULE_PARM_DESC(gpio, "sampling_rate");
++
++module_param(sample_size, int, 0);
++MODULE_PARM_DESC(gpio, "sample_size");
++
++#define DMA_TRANSFER_MAX_BYTE (0xfff<<(sample_size>>4))
++#define BUFSIZE (0xfff<<4) //twice the 32-bit DMA transfer byte size
++
++static u8* lbuffer;
++static u8* lbuffer_p;
++static u32 llen=0;
++static u32 lpos=0;
++static u32 i2s_err_lur=0;
++
++static u32 debug=0;
++#define DEBUG_PRINT(arg...) if(debug) printk(arg);
++
++//=================================================================================
++//
++#ifdef CONFIG_I2S_USE_DMA
++
++static DMAC_HARDWARE_HANDSHAKE_OBJ_T i2s_wm8759_dma_handshake_left_tx;
++static DMAC_HARDWARE_HANDSHAKE_OBJ_T i2s_wm8759_dma_handshake_right_tx;
++
++static u32 i2s_wm8759_dma_right_tx_channel = 1;
++
++
++
++
++
++void I2s_WM8759_Configure_DMA_Hardware_Handshake(void)
++{
++ /*
++ * Configure DMA's channel setting for I2S's Left Channel Tx
++ * Specially pay attention to the settings of src_width, dst_width, and src_burst_size
++ */
++ i2s_wm8759_dma_handshake_left_tx.channel_num = 0;
++ i2s_wm8759_dma_handshake_left_tx.channel_id = DMAC_CH_ID(i2s_wm8759_dma_handshake_left_tx.channel_num);
++ i2s_wm8759_dma_handshake_left_tx.target_select = DMAC_HW_HAND_SHAKE_I2S_TX_LEFT_ID;
++ i2s_wm8759_dma_handshake_left_tx.src_addr = (u32)lbuffer_p;
++ i2s_wm8759_dma_handshake_left_tx.src_master = DMAC_CH_SRC_SEL_M1;
++ i2s_wm8759_dma_handshake_left_tx.dst_master = DMAC_CH_DST_SEL_M0;
++ i2s_wm8759_dma_handshake_left_tx.srcad_ctl = DMAC_CH_SRCAD_CTL_INC;
++ i2s_wm8759_dma_handshake_left_tx.dstad_ctl = DMAC_CH_DSTAD_CTL_FIX;
++
++ switch(sample_size){
++ case 16:
++ i2s_wm8759_dma_handshake_left_tx.dst_addr = (SYSPA_I2S_BASE_ADDR + 0xCA);
++ i2s_wm8759_dma_handshake_left_tx.src_width = DMAC_CH_SRC_WIDTH_16_BITS;
++ i2s_wm8759_dma_handshake_left_tx.dst_width = DMAC_CH_DST_WIDTH_16_BITS;
++ break;
++ case 32:
++ i2s_wm8759_dma_handshake_left_tx.dst_addr = (SYSPA_I2S_BASE_ADDR + 0xC8);
++ i2s_wm8759_dma_handshake_left_tx.src_width = DMAC_CH_SRC_WIDTH_32_BITS;
++ i2s_wm8759_dma_handshake_left_tx.dst_width = DMAC_CH_DST_WIDTH_32_BITS;
++ break;
++ }
++
++// i2s_wm8759_dma_handshake_left_tx.dst_width = DMAC_CH_DST_WIDTH_16_BITS;
++
++ /*
++ * Note here the total number of bytes for each DMA transfer is specified!!
++ */
++// i2s_wm8759_dma_handshake_left_tx.transfer_bytes = DMA_TRANSFER_MAX_BYTE;
++ i2s_wm8759_dma_handshake_left_tx.transfer_bytes = (llen<DMA_TRANSFER_MAX_BYTE)?llen:DMA_TRANSFER_MAX_BYTE;
++
++ i2s_wm8759_dma_handshake_left_tx.src_burst_size = DMAC_CH_SRC_BURST_SIZE_1;
++
++ Hal_Dmac_Configure_DMA_Handshake(&i2s_wm8759_dma_handshake_left_tx);
++
++#ifndef DEBUG
++ /*
++ * Configure DMA's channel setting for I2S's Right Channel Tx
++ * Specially pay attention to the settings of src_width, dst_width, and src_burst_size
++ */
++ i2s_wm8759_dma_handshake_right_tx.channel_id = DMAC_CH_ID(i2s_wm8759_dma_right_tx_channel);
++
++ i2s_wm8759_dma_handshake_right_tx.target_select = DMAC_HW_HAND_SHAKE_I2S_TX_RIGHT_ID;
++
++ i2s_wm8759_dma_handshake_right_tx.src_addr = (u32)rbuffer_p;
++
++ i2s_wm8759_dma_handshake_right_tx.dst_addr = (SYSPA_I2S_BASE_ADDR + 0xC4);
++
++ i2s_wm8759_dma_handshake_right_tx.src_master = DMAC_CH_SRC_SEL_M1;
++
++ i2s_wm8759_dma_handshake_right_tx.dst_master = DMAC_CH_DST_SEL_M0;
++
++ i2s_wm8759_dma_handshake_right_tx.srcad_ctl = DMAC_CH_SRCAD_CTL_INC;
++
++ i2s_wm8759_dma_handshake_right_tx.dstad_ctl = DMAC_CH_DSTAD_CTL_FIX;
++
++ i2s_wm8759_dma_handshake_right_tx.src_width = DMAC_CH_SRC_WIDTH_32_BITS;
++
++ i2s_wm8759_dma_handshake_right_tx.dst_width = DMAC_CH_DST_WIDTH_32_BITS;
++
++ /*
++ * Note here the total number of bytes for each DMA transfer is specified!!
++ */
++ i2s_wm8759_dma_handshake_right_tx.transfer_bytes = DMA_TRANSFER_MAX_BYTE;
++
++ i2s_wm8759_dma_handshake_right_tx.src_burst_size = DMAC_CH_SRC_BURST_SIZE_1;
++
++ Hal_Dmac_Configure_DMA_Handshake(&i2s_wm8759_dma_handshake_right_tx);
++#endif
++ return;
++}
++#endif //CONFIG_I2S_USE_DMA
++
++
++//=================================================================================
++//
++
++extern void str8100_set_interrupt_trigger(unsigned int, unsigned int, unsigned int);
++
++#ifdef CONFIG_I2S_USE_DMA
++static irqreturn_t str8100_dma_tc_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs)
++{
++ u32 dma_tc_status,tot_size;
++ u32 len;
++//printk("%s: this_irq=%d\n",__FUNCTION__,this_irq);
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(this_irq);
++ //todo:
++
++ HAL_DMAC_READ_TERMINAL_COUNT_INTERRUPT_STATUS(dma_tc_status);
++
++ /*
++ * For DMA's Tx for I2S Left Channel
++ */
++ if (dma_tc_status & DMAC_CH_ID(i2s_wm8759_dma_handshake_left_tx.channel_num))
++ {
++ HAL_DMAC_DISABLE_CHANNEL(i2s_wm8759_dma_handshake_left_tx.channel_num);
++ HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(DMAC_CH_ID(i2s_wm8759_dma_handshake_left_tx.channel_num));
++ lpos+=i2s_wm8759_dma_handshake_left_tx.transfer_bytes;
++ if(lpos<llen){
++ /*
++ * Re-initialize DMA's channel for Left_Tx
++ */
++ DMAC_CH_SRC_ADDR_REG(i2s_wm8759_dma_handshake_left_tx.channel_num) = (u32)lbuffer_p+lpos;
++ DMAC_CH_DST_ADDR_REG(i2s_wm8759_dma_handshake_left_tx.channel_num) = (SYSPA_I2S_BASE_ADDR + 0xC8);
++
++ /*
++ * Note this macro DMAC_CH_SIZE is to configure TOT_SIZE field which is the total transfer
++ * number of source transfer width!
++ */
++ len=(llen - lpos);
++ i2s_wm8759_dma_handshake_left_tx.transfer_bytes= (len<DMA_TRANSFER_MAX_BYTE)?len:DMA_TRANSFER_MAX_BYTE;
++
++ if (i2s_wm8759_dma_handshake_left_tx.src_width == DMAC_CH_SRC_WIDTH_16_BITS)
++ {
++ tot_size = (i2s_wm8759_dma_handshake_left_tx.transfer_bytes >> 1) + ((i2s_wm8759_dma_handshake_left_tx.transfer_bytes % 2) ? 1 : 0);
++ }
++ else if (i2s_wm8759_dma_handshake_left_tx.src_width == DMAC_CH_SRC_WIDTH_32_BITS)
++ {
++ tot_size = (i2s_wm8759_dma_handshake_left_tx.transfer_bytes >> 2) + ((i2s_wm8759_dma_handshake_left_tx.transfer_bytes % 4) ? 1 : 0);
++ }
++ else
++ {
++ tot_size = i2s_wm8759_dma_handshake_left_tx.transfer_bytes;
++ }
++
++ DMAC_CH_SIZE_REG(i2s_wm8759_dma_handshake_left_tx.channel_num) = tot_size & 0x0FFF;
++ HAL_DMAC_ENABLE_CHANNEL(i2s_wm8759_dma_handshake_left_tx.channel_num);
++//printk("%s: 32-bits transfer_bytes=%d, DMAC_CH_SIZE_REG(%d)=%.8x\n",__FUNCTION__,i2s_wm8759_dma_handshake_left_tx.transfer_bytes,i2s_wm8759_dma_handshake_left_tx.channel_num,DMAC_CH_SIZE_REG(i2s_wm8759_dma_handshake_left_tx.channel_num));
++
++ }else{
++ llen=lpos=0;
++ }
++ }
++
++
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq);
++
++ return IRQ_HANDLED;
++}
++
++#endif //CONFIG_I2S_USE_DMA
++
++static irqreturn_t str8100_i2s_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs)
++{
++ u32 interrupt_status;
++ DEBUG_PRINT("%s: this_irq=%d, I2S_INTERRUPT_STATUS_REG=0x%.8x,llen=%d,lpos=%d\n",__FUNCTION__,this_irq,I2S_INTERRUPT_STATUS_REG,llen,lpos);
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(this_irq);
++ //todo:
++ interrupt_status = I2S_INTERRUPT_STATUS_REG;
++if((llen<lpos)||llen==0) HAL_I2S_DISABLE_I2S();
++
++#ifndef CONFIG_I2S_USE_DMA
++ I2S_RIGHT_TRANSMIT_DATA_REG=0;
++
++ if ((lpos<=llen) && (interrupt_status & I2S_TXBF_L_EMPTY_FLAG)){
++ switch(sample_size){
++ case 16:
++ I2S_LEFT_TRANSMIT_DATA_REG=(*((u16*)(&lbuffer[lpos])))<<16;lpos+=2;
++ break;
++ case 32:
++ I2S_LEFT_TRANSMIT_DATA_REG=*((u32*)(&lbuffer[lpos]));lpos+=4;
++ break;
++ }
++
++ if(lpos>llen){
++ // Disable Left Channel's Transmit Buffer Interrupt Sources
++ I2S_INTERRUPT_ENABLE_REG &= ~(I2S_TXBF_L_EMPTY_FLAG | I2S_TXBF_L_UR_FLAG);
++ lpos=llen=0;
++ }
++ }
++#endif //!CONFIG_I2S_USE_DMA
++
++
++ if (llen>=lpos && (interrupt_status & I2S_TXBF_L_UR_FLAG)){
++ // Clear I2S interrupt status
++ i2s_err_lur++;
++ if(i2s_err_lur>10)
++ I2S_INTERRUPT_ENABLE_REG &= ~(I2S_TXBF_L_UR_FLAG);
++// HAL_I2S_DISABLE_I2S();
++
++ printk("%s: Left Channel Tx Underrun!,llen=%d, lpos=%d, interrupt_status=%.8x,i2s_err_lur=%d\n",__FUNCTION__,llen,lpos,interrupt_status,i2s_err_lur);
++ }
++ I2S_INTERRUPT_STATUS_REG &= 0xf0;
++
++
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq);
++
++ return IRQ_HANDLED;
++}
++
++
++
++//=================================================================================
++static int proc_read_i2s(char *buf, char **start, off_t offset,
++ int count, int *eof, void *data)
++{
++ int len=0;
++ DEBUG_PRINT("%s:\n",__FUNCTION__);
++ len += sprintf(buf, "sampling_rate=%d\n"
++ "sample_size=%d\n"
++ ,sampling_rate,sample_size);
++ *eof = 1;
++ return len;
++}
++
++static proc_write_i2s(struct file *file, const char *buffer, unsigned long count, void *data){
++ int len=0;
++ DEBUG_PRINT("%s: sample size %d, sampling rate %d, count=%d\n",__FUNCTION__,sample_size,sampling_rate,count);
++
++ //is buffer free?
++ if(lpos!=llen){
++ printk("%s: buffer not free\n");
++ return -EBUSY;
++ }
++ if(sampling_rate!=32000&&sampling_rate!=44100&&sampling_rate!=48000){
++ printk("%s: invalid sampling rate(%d)\n",sampling_rate);
++ return -EFAULT;
++ }
++ if(sample_size!=16&&sample_size!=32){
++ printk("%s: invalid sample size(%d)\n",sample_size);
++ return -EFAULT;
++ }
++
++ //copy the raw data to local buffer
++ if(count>BUFSIZE) len=BUFSIZE;
++ else len=count;
++
++ if(copy_from_user(lbuffer,buffer,len)){
++ return -EFAULT;
++ }
++ llen=len;
++ lpos=0;
++ i2s_err_lur=0;
++
++ str8100_i2s_init(sampling_rate,I2S_DATA_32_BIT, I2S_MASTER_MODE, I2S_I2S_MODE, I2S_CLOCK_256S_MODE);
++
++#ifdef CONFIG_I2S_USE_DMA
++ /*
++ * Configure DMA for hardware handshake for I2S
++ * Note the DMA is NOT enabled after invoking the following function, but the specified
++ * DMA channels are enabled!!
++ */
++ i2s_wm8759_dma_right_tx_channel = 1;
++
++ I2s_WM8759_Configure_DMA_Hardware_Handshake();
++
++#endif //CONFIG_I2S_USE_DMA
++ //fill the tx left/right registers
++
++ switch(sample_size){
++ case 16:
++ I2S_LEFT_TRANSMIT_DATA_REG=(*((u16*)(&lbuffer[lpos])))<<16;lpos+=2;
++ break;
++ case 32:
++ I2S_LEFT_TRANSMIT_DATA_REG=*((u32*)(&lbuffer[lpos]));lpos+=4;
++ break;
++ }
++
++ I2S_RIGHT_TRANSMIT_DATA_REG=0;
++
++#ifdef CONFIG_I2S_USE_DMA
++ /*
++ * Enable I2S's interrupt sources
++ * Note for DMA hardware handshake, we only need to enable Left/Right Channel's
++ * Transmit Buffer Underrun.
++ */
++#ifdef DEBUG
++ I2S_INTERRUPT_ENABLE_REG |= (I2S_TXBF_L_UR_FLAG);
++#else
++ I2S_INTERRUPT_ENABLE_REG |= (I2S_TXBF_R_UR_FLAG | I2S_TXBF_L_UR_FLAG);
++#endif
++#else //CONFIG_I2S_USE_DMA
++#ifdef DEBUG
++ I2S_INTERRUPT_ENABLE_REG |= (I2S_TXBF_L_UR_FLAG | I2S_TXBF_L_EMPTY_FLAG);
++#else
++ I2S_INTERRUPT_ENABLE_REG |= (I2S_TXBF_R_UR_FLAG | I2S_TXBF_L_UR_FLAG | I2S_TXBF_R_EMPTY_FLAG | I2S_TXBF_L_EMPTY_FLAG);
++#endif
++#endif //CONFIG_I2S_USE_DMA
++
++ // Enable CPU interrupt
++ local_irq_enable();
++
++#ifdef CONFIG_I2S_USE_DMA
++ /*
++ * Note DMA must be enabled first before I2S is enabled
++ */
++ HAL_DMAC_ENABLE();
++#endif //CONFIG_I2S_USE_DMA
++ HAL_I2S_ENABLE_I2S();
++
++
++ while (1){
++ local_irq_disable();
++ if (lpos>llen||llen==0){
++ // Disable I2S
++ HAL_I2S_DISABLE_I2S();
++ break;
++ }
++ local_irq_enable();
++ }
++ DEBUG_PRINT("%s: exit. i2s_err_lur=%d\n",__FUNCTION__,i2s_err_lur);
++
++ local_irq_enable();
++
++ return len;
++
++debug:
++ HAL_I2S_DISABLE_I2S();
++ return count;
++}
++
++static void __exit i2s_exit_module(void){
++ printk("%s:\n",__FUNCTION__);
++ remove_proc_entry("str8100/i2s", NULL);
++ free_irq(INTC_I2S_BIT_INDEX, NULL);
++#ifdef CONFIG_I2S_USE_DMA
++ free_irq(INTC_GDMAC_TC_BIT_INDEX, NULL);
++ free_irq(INTC_GDMAC_ERROR_BIT_INDEX, NULL);
++#endif //CONFIG_I2S_USE_DMA
++ if(lbuffer) {
++ pci_free_consistent(NULL, BUFSIZE, lbuffer, lbuffer_p);
++ lbuffer=lbuffer_p=NULL;
++ }
++}
++
++static int __init i2s_init_module(void)
++{
++
++ u32 ret;
++
++ printk("%s:\n",__FUNCTION__);
++#ifdef CONFIG_I2S_USE_DMA
++ printk("%s: DMA Enabled...\n",__FUNCTION__);
++#endif //CONFIG_I2S_USE_DMA
++
++ star_i2s_proc_entry = create_proc_entry("str8100/i2s", S_IFREG | S_IRUGO, NULL);
++ if(!star_i2s_proc_entry){
++ return -EBUSY;
++ }
++ star_i2s_proc_entry->read_proc=proc_read_i2s;
++ star_i2s_proc_entry->write_proc=proc_write_i2s;
++
++ lbuffer = pci_alloc_consistent(NULL, BUFSIZE, &lbuffer_p);
++ if(!lbuffer){
++ printk("%s: alloc lbuffer failed.\n",__FUNCTION__);
++ goto exit1;
++ }
++
++ str8100_set_interrupt_trigger (INTC_I2S_BIT_INDEX,INTC_LEVEL_TRIGGER,INTC_ACTIVE_LOW);
++ if ((ret=request_irq(INTC_I2S_BIT_INDEX, str8100_i2s_irq_handler, 0, "i2s", NULL))){
++ printk("%s: request_irq %d failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,INTC_I2S_BIT_INDEX,ret,-EBUSY);
++ goto exit1;
++ }
++
++#ifdef CONFIG_I2S_USE_DMA
++ str8100_set_interrupt_trigger (INTC_GDMAC_TC_BIT_INDEX,INTC_LEVEL_TRIGGER,INTC_ACTIVE_HIGH);
++ if ((ret=request_irq(INTC_GDMAC_TC_BIT_INDEX, str8100_dma_tc_irq_handler, 0, "dma tc", NULL))){
++ printk("%s: request_irq %d failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,INTC_GDMAC_TC_BIT_INDEX,ret,-EBUSY);
++ goto exit1;
++ }
++ str8100_set_interrupt_trigger (INTC_GDMAC_ERROR_BIT_INDEX,INTC_LEVEL_TRIGGER,INTC_ACTIVE_HIGH);
++ if ((ret=request_irq(INTC_GDMAC_ERROR_BIT_INDEX, str8100_dma_err_irq_handler, 0, "dma error", NULL))){
++ printk("%s: request_irq %d failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,INTC_GDMAC_ERROR_BIT_INDEX,ret,-EBUSY);
++ goto exit1;
++ }
++#endif //CONFIG_I2S_USE_DMA
++
++ return 0;
++exit1:
++ i2s_exit_module();
++ return -EBUSY;
++}
++
++module_init(i2s_init_module);
++module_exit(i2s_exit_module);
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_demo_i2s_wm8772_config.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_demo_i2s_wm8772_config.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_demo_i2s_wm8772_config.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_demo_i2s_wm8772_config.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,924 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++//Options
++#define DEBUG
++#define I2S_FULL_DUPLEX
++#define I2S_WM8772_DMAC_LLP_TEST
++#define I2S_WM8772_DMAC_LLP_NUM 3
++#define I2S_WM8772_BUFFER_SIZE (48 * 1 * 2 * 100)
++#define I2S_TIMING I2S_I2S_MODE
++//#define I2S_TIMING I2S_RJF_MODE
++//#define I2S_TIMING I2S_LJF_MODE
++#define DATA_WIDTH I2S_DATA_32_BIT
++//#define DATA_WIDTH I2S_DATA_16_BIT
++#define I2S_MODE I2S_MASTER_MODE
++//#define I2S_MODE I2S_SLAVE_MODE
++#define I2S_SCLK_MODE I2S_CLOCK_256S_MODE
++//#define I2S_SCLK_MODE I2S_CLOCK_CONTINUOUS_MODE
++//*******************
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++
++#include <linux/kernel.h> /* printk() */
++#include <linux/errno.h> /* error codes */
++#include <linux/types.h> /* size_t */
++#include <linux/proc_fs.h>
++#include <linux/interrupt.h>
++#include <linux/pci.h>
++
++#include <asm/system.h> /* cli(), *_flags */
++#include <asm/uaccess.h> /* copy_*_user */
++
++#include <mach/star_powermgt.h>
++#include <mach/star_misc.h>
++#include <mach/star_i2s.h>
++#include <mach/star_demo_dma.h>
++
++MODULE_AUTHOR("Mac Lin");
++MODULE_LICENSE("Dual BSD/GPL");
++
++
++//Debug = left only
++
++static u32 sampling_rate=44100;
++
++module_param(sampling_rate, int, 0);
++MODULE_PARM_DESC(gpio, "sampling_rate");
++
++//#define DMA_TRANSFER_MAX_BYTE (0xfff<<(sample_size>>4))
++//#define BUFSIZE (0xfff<<4) //twice the 32-bit DMA transfer byte size
++
++static u8* buffer=NULL;
++static u8* buffer_p=NULL;
++static DMAC_LLP_T* desc=NULL;
++static DMAC_LLP_T* desc_p=NULL;
++
++static u8* lbuffer=NULL;
++static u8* lbuffer_p=NULL;
++static DMAC_LLP_T* lb_txd=NULL;
++static DMAC_LLP_T* lb_txd_p=NULL;
++static DMAC_LLP_T* lb_rxd=NULL;
++static DMAC_LLP_T* lb_rxd_p=NULL;
++
++static u8* rbuffer=NULL;
++static u8* rbuffer_p=NULL;
++static DMAC_LLP_T* rb_txd=NULL;
++static DMAC_LLP_T* rb_txd_p=NULL;
++static DMAC_LLP_T* rb_rxd=NULL;
++static DMAC_LLP_T* rb_rxd_p=NULL;
++
++static DMAC_LLP_T* i2s_left_tx_channel_dma_llp_desc=NULL;
++static DMAC_LLP_T* i2s_left_rx_channel_dma_llp_desc=NULL;
++static DMAC_LLP_T* i2s_right_tx_channel_dma_llp_desc=NULL;
++static DMAC_LLP_T* i2s_right_rx_channel_dma_llp_desc=NULL;
++
++static u8* i2s_left_channel_llp_buf[I2S_WM8772_DMAC_LLP_NUM];
++static u8* i2s_right_channel_llp_buf[I2S_WM8772_DMAC_LLP_NUM];
++
++
++static u32 i2s_err_lur=0;
++
++static u32 debug=0;
++#define DEBUG_PRINT(arg...) if(debug) printk(arg);
++
++static u32 i2s_wm8772_dma_left_tx_channel = 0;
++static u32 i2s_wm8772_dma_right_tx_channel = 1;
++static u32 i2s_wm8772_dma_left_rx_channel = 2;
++static u32 i2s_wm8772_dma_right_rx_channel = 3;
++
++
++#if (I2S_WM8772_DMAC_LLP_NUM >= 3)
++#define I2S_WM8772_DMAC_LLP_RING_TEST
++#endif
++#define BUFSIZE (I2S_WM8772_DMAC_LLP_NUM*I2S_WM8772_BUFFER_SIZE*4)
++
++#define I2S_BASE_ADDR SYSPA_I2S_BASE_ADDR
++#define i2s_dmac_llp_num I2S_WM8772_DMAC_LLP_NUM
++//=================================================================================
++//
++
++/******************************************************************************
++ *
++ * FUNCTION: I2s_Configure_WM8772
++ * PURPOSE:
++ *
++ ******************************************************************************/
++void I2s_Configure_WM8772(u32 interface_format, u32 word_length, u32 data_interface_mode)
++{
++ u16 reg_data;
++
++
++ /*
++ * The current configuration of W571C161 DAC are:
++ * 1. MODE : External hardware setting control mode
++ * 2. COM1 = 1, COM2 = 0 : 16-bit I2S
++ * 3. COM3 = 0 : De-emphasis filter off
++ * 4. I2S Level 2 (Slave Mode) : How to configure it
++ */
++
++ /*
++ * Configure register R31 for reset
++ */
++#if 1
++ reg_data = (0x1F << 9) | /* Register address value : 0x1F */
++ (0x1FF);
++#else
++ reg_data = (0xF << 9) | /* Register address value : 0xF */
++ (0x1FF);
++#endif
++
++ I2s_Gpio_SSP_Write(reg_data);
++
++ /*
++ * Configure register R2
++ */
++ reg_data = (0x2 << 9) | /* Register address value : 0x2 */
++#if 1
++// (0x5 << 5) | /* Right Channel Output Mixer Status : right channel data */
++ (0x9 << 5) | /* Right Channel Output Mixer Status : right channel data */
++ /* Left Channel Output Mixer Status : left channel data */
++#else
++ (0x2 << 7) | /* Right Channel Output Mixer Status : right channel data */
++ (0x1 << 5) | /* Left Channel Output Mixer Status : left channel data */
++#endif
++ (0x0 << 4) | /* IZM : disable */
++ (0x0 << 3) | /* ATC : right channels use right attenuations */
++ (0x0 << 2) | /* PDWNALL : disable */
++ (0x0 << 1) | /* DEEMPALL : normal */
++ (0x0 << 0); /* Soft Mute Select : normal */
++
++ I2s_Gpio_SSP_Write(reg_data);
++
++ /*
++ * Configure register R12
++ */
++ reg_data = (0xC << 9) | /* Register address value : 0xC */
++ (0x1 << 6) | /* Disable the MUTE decoded circuit used by DZFM */
++// (0x0 << 6) | /* Enable the MUTE decoded circuit used by DZFM */
++ (0x0 << 2) | /* Normal operation */
++ (0x0 << 1) | /* Normal operation */
++ (0x0 << 0); /* Normal operation */
++
++ I2s_Gpio_SSP_Write(reg_data);
++
++
++ /*
++ * Configure register R9
++ */
++ reg_data = (0x9 << 9) | /* Register address value : 0x9 */
++ (0x0 << 8) | /* Channel 3L/R De-emphasis Status : No de-emphasis */
++ (0x0 << 7) | /* Channel 2L/R De-emphasis Status : No de-emphasis */
++ (0x0 << 6) | /* Channel 1L/R De-emphasis Status : No de-emphasis */
++ (0x1 << 5) | /* Channel 3L/R Play Status : Mute */
++ (0x1 << 4) | /* Channel 2L/R Play Status : Mute */
++ (0x0 << 3) | /* Channel 1L/R Play Status : play */
++ (0x3 << 1) | /* DZFM[1:0] : Channel 3 */
++ (0x1 << 0); /* ZCD : disabled */
++
++ I2s_Gpio_SSP_Write(reg_data);
++
++
++ /*
++ * Configure register R3 for audio data interface format
++ */
++ reg_data = (0x3 << 9) | /* Register address value : 0x3 */
++ (0x0 << 6) | /* Phase : normal */
++ (0x0 << 4) | /* Input Word Length : 16-bit(0x0 << 4) ; 32-bit(0x3 <<4) */
++#if 0
++ (0x1 << 3) | /* BCK Polarity : invert : for DSP mode only ????? */
++#else
++ (0x0 << 3) | /* BCK Polarity : normal */
++#endif
++
++#if 0
++ (0x1 << 2) | /* LRC Polarity : invert */
++#else
++ (0x0 << 2) | /* LRC Polarity : normal */
++#endif
++ (0x0 << 0); /* Interface Format : right justified mode */
++
++ if (interface_format == I2S_RJF_MODE)
++ {
++ reg_data |= 0;
++ }
++ else if (interface_format == I2S_LJF_MODE)
++ {
++ reg_data |= 1;
++ }
++ else if (interface_format == I2S_I2S_MODE)
++ {
++ reg_data |= 2;
++ }
++ else
++ {
++ printk("\nI2S: Incorrect selected interface mode: DSP mode!\n");
++
++ reg_data |= 3;
++ }
++
++ /*
++ * 16-bit data for I2S_RJF_MODE
++ */
++ if (interface_format == I2S_RJF_MODE)
++ {
++ // 16-bit data
++ reg_data |= (0 << 4);
++ }
++ else
++ {
++ if (word_length == I2S_DATA_16_BIT)
++ {
++ reg_data |= (0 << 4);
++ }
++ else if (word_length == I2S_DATA_32_BIT)
++ {
++ reg_data |= (3 << 4);
++ }
++ }
++
++ I2s_Gpio_SSP_Write(reg_data);
++
++
++ /*
++ * Configure register R10
++ */
++ reg_data = (0xA << 9) | /* Register address value : 0xA */
++ (0x2 << 6) | /* Frequency Ratio = MCLK/LRC : 256 */
++ //(0x3 << 6) | /* Frequency Ratio = MCLK/LRC : 384 */
++ //(0x0 << 6) | /* Frequency Ratio = MCLK/LRC : 128 */
++ (0x0 << 5) | /* Data Interface Mode : Level 2 (Slave mode) */
++ (0x0 << 4) | /* All Channel Power Down : play */
++ (0x1 << 3) | /* Channel 3 L/R Play Status : power down */
++ (0x1 << 2) | /* Channel 2 L/R Play Status : power down */
++ (0x0 << 1) | /* Channel 1 L/R Play Status : play */
++#if 0
++ (0x1 << 0); /* ADC deactive */
++#else
++ (0x0 << 0); /* ADC active */
++#endif
++
++ if (data_interface_mode == I2S_SLAVE_MODE)
++ {
++ /*
++ * Equuleus's I2S is in Slave mode, so WM8772 will be in Master mode
++ */
++ reg_data |= (0x1 << 5);
++ }
++
++ I2s_Gpio_SSP_Write(reg_data);
++
++
++ /*
++ * Configure register R11?????
++ */
++ reg_data = (0xB << 9) | /* Register address value : 0xB */
++ (0x0 << 8); /* 128x oversampling */
++
++ I2s_Gpio_SSP_Write(reg_data);
++
++
++ /*
++ * Configure register R12
++ */
++ reg_data = (0xC << 9) | /* Register address value : 0xC */
++ (0x0 << 3); /* Highpass filter enabled */
++
++ I2s_Gpio_SSP_Write(reg_data);
++
++ return;
++}
++
++//=================================================================================
++//
++
++static DMAC_HARDWARE_HANDSHAKE_OBJ_T i2s_wm8772_dma_right_tx;
++static DMAC_HARDWARE_HANDSHAKE_OBJ_T i2s_wm8772_dma_right_rx;
++static DMAC_HARDWARE_HANDSHAKE_OBJ_T i2s_wm8772_dma_left_tx;
++static DMAC_HARDWARE_HANDSHAKE_OBJ_T i2s_wm8772_dma_left_rx;
++
++void I2s_Configure_WM8772_DMA_Hardware_Handshake(void)
++{
++ u32 ii,tot_size;
++ /*
++ * Initialize DMAC's LLP descriptors
++ */
++ i2s_left_tx_channel_dma_llp_desc=lb_txd;
++ i2s_left_rx_channel_dma_llp_desc=lb_rxd;
++ i2s_right_tx_channel_dma_llp_desc=rb_txd;
++ i2s_right_rx_channel_dma_llp_desc=rb_rxd;
++
++ for (ii = 0; ii < I2S_WM8772_DMAC_LLP_NUM; ii++)
++ {
++ memset ((void *)&i2s_left_tx_channel_dma_llp_desc[ii], 0x0, sizeof (i2s_left_tx_channel_dma_llp_desc[ii]));
++ memset ((void *)&i2s_left_rx_channel_dma_llp_desc[ii], 0x0, sizeof (i2s_left_rx_channel_dma_llp_desc[ii]));
++
++ memset ((void *)&i2s_right_tx_channel_dma_llp_desc[ii], 0x0, sizeof (i2s_right_tx_channel_dma_llp_desc[ii]));
++ memset ((void *)&i2s_right_rx_channel_dma_llp_desc[ii], 0x0, sizeof (i2s_right_rx_channel_dma_llp_desc[ii]));
++ }
++
++//1. *****************************************************************************
++ /*
++ * Configure DMA's channel setting for I2S's Left Channel Tx
++ * Specially pay attention to the settings of src_width, dst_width, and src_burst_size
++ */
++ for (ii = 0; ii < I2S_WM8772_DMAC_LLP_NUM; ii++)
++ {
++ i2s_left_tx_channel_dma_llp_desc[ii].SrcAddr = i2s_left_channel_llp_buf[ii];
++
++ i2s_left_tx_channel_dma_llp_desc[ii].DstAddr = (I2S_BASE_ADDR + 0xC8);
++
++#ifdef I2S_WM8772_DMAC_LLP_RING_TEST
++ i2s_left_tx_channel_dma_llp_desc[ii].LLP = (ii != (I2S_WM8772_DMAC_LLP_NUM - 1)) ? (DMAC_LLP_T *)&lb_txd_p[ii+1] : (DMAC_LLP_T *)&lb_txd_p[1];
++#else
++ i2s_left_tx_channel_dma_llp_desc[ii].LLP = (ii != (I2S_WM8772_DMAC_LLP_NUM - 1)) ? (DMAC_LLP_T *)&lb_txd_p[ii+1] : (DMAC_LLP_T *)(0);
++#endif
++
++ tot_size = Hal_Dmac_Get_Channel_Transfer_Unit_Number(I2S_WM8772_BUFFER_SIZE * 4, DMAC_CH_SRC_WIDTH_32_BITS);
++
++ i2s_left_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.tot_size = tot_size; /* TOT_SIZE */
++ i2s_left_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.dst_sel = DMAC_CH_DST_SEL_M0; /* DST_SEL */
++ i2s_left_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.src_sel = DMAC_CH_SRC_SEL_M1; /* SRC_SEL */
++ i2s_left_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.dstad_ctl = DMAC_CH_DSTAD_CTL_FIX; /* DSTAD_CTL */
++ i2s_left_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.srcad_ctl = DMAC_CH_SRCAD_CTL_INC; /* SRCAD_CTL */
++ i2s_left_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.dst_width = DMAC_CH_DST_WIDTH_32_BITS; /* DST_WIDTH */
++ i2s_left_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.src_width = DMAC_CH_SRC_WIDTH_32_BITS; /* SRC_WIDTH */
++
++#ifdef I2S_WM8772_DMAC_LLP_RING_TEST
++ i2s_left_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.tc_status_mask = (DMAC_CH_TC_MASK_ENABLE); /* TC_MASK */
++#else
++ i2s_left_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.tc_status_mask = ((ii != (I2S_WM8772_DMAC_LLP_NUM - 1)) ? (DMAC_CH_TC_MASK_ENABLE) : (DMAC_CH_TC_MASK_DISABLE)); /* TC_MASK */
++#endif
++ }
++
++ i2s_wm8772_dma_left_tx.channel_id = DMAC_CH_ID(i2s_wm8772_dma_left_tx_channel);
++ i2s_wm8772_dma_left_tx.target_select = DMAC_HW_HAND_SHAKE_I2S_TX_LEFT_ID;
++
++ i2s_wm8772_dma_left_tx.src_addr = i2s_left_tx_channel_dma_llp_desc[0].SrcAddr;
++ i2s_wm8772_dma_left_tx.dst_addr = i2s_left_tx_channel_dma_llp_desc[0].DstAddr;
++
++ i2s_wm8772_dma_left_tx.src_master = DMAC_CH_SRC_SEL_M1;
++ i2s_wm8772_dma_left_tx.dst_master = DMAC_CH_DST_SEL_M0;
++
++ i2s_wm8772_dma_left_tx.srcad_ctl = DMAC_CH_SRCAD_CTL_INC;
++ i2s_wm8772_dma_left_tx.dstad_ctl = DMAC_CH_DSTAD_CTL_FIX;
++
++ i2s_wm8772_dma_left_tx.src_width = DMAC_CH_SRC_WIDTH_32_BITS;
++ i2s_wm8772_dma_left_tx.dst_width = DMAC_CH_DST_WIDTH_32_BITS;
++
++
++ // Note here the total number of bytes is specified!!
++ i2s_wm8772_dma_left_tx.transfer_bytes = I2S_WM8772_BUFFER_SIZE * 4;
++
++ i2s_wm8772_dma_left_tx.src_burst_size = DMAC_CH_SRC_BURST_SIZE_1;
++
++ i2s_wm8772_dma_left_tx.llp_addr = (i2s_dmac_llp_num == 1) ? 0 : (u32)i2s_left_tx_channel_dma_llp_desc[0].LLP;
++
++ Hal_Dmac_Configure_DMA_Handshake(&i2s_wm8772_dma_left_tx);
++//2. *****************************************************************************
++ /*
++ * Configure DMA's channel setting for I2S's Right Channel Tx
++ * Specially pay attention to the settings of src_width, dst_width, and src_burst_size
++ */
++ for (ii = 0; ii < I2S_WM8772_DMAC_LLP_NUM; ii++)
++ {
++ i2s_right_tx_channel_dma_llp_desc[ii].SrcAddr = i2s_right_channel_llp_buf[ii];
++
++ i2s_right_tx_channel_dma_llp_desc[ii].DstAddr = (I2S_BASE_ADDR + 0xC4);
++
++#ifdef I2S_WM8772_DMAC_LLP_RING_TEST
++ i2s_right_tx_channel_dma_llp_desc[ii].LLP = (ii != (I2S_WM8772_DMAC_LLP_NUM - 1)) ? (DMAC_LLP_T *)&rb_txd_p[ii+1] : (DMAC_LLP_T *)&rb_txd_p[1];
++#else
++ i2s_right_tx_channel_dma_llp_desc[ii].LLP = (ii != (I2S_WM8772_DMAC_LLP_NUM - 1)) ? (DMAC_LLP_T *)&rb_txd_p[ii + 1] : (DMAC_LLP_T *)(0);
++#endif
++
++ tot_size = Hal_Dmac_Get_Channel_Transfer_Unit_Number(I2S_WM8772_BUFFER_SIZE * 4, DMAC_CH_SRC_WIDTH_32_BITS);
++
++ i2s_right_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.tot_size = tot_size; /* TOT_SIZE */
++ i2s_right_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.dst_sel = DMAC_CH_DST_SEL_M0; /* DST_SEL */
++ i2s_right_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.src_sel = DMAC_CH_SRC_SEL_M1; /* SRC_SEL */
++ i2s_right_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.dstad_ctl = DMAC_CH_DSTAD_CTL_FIX; /* DSTAD_CTL */
++ i2s_right_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.srcad_ctl = DMAC_CH_SRCAD_CTL_INC; /* SRCAD_CTL */
++ i2s_right_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.dst_width = DMAC_CH_DST_WIDTH_32_BITS; /* DST_WIDTH */
++ i2s_right_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.src_width = DMAC_CH_SRC_WIDTH_32_BITS; /* SRC_WIDTH */
++
++#ifdef I2S_WM8772_DMAC_LLP_RING_TEST
++ i2s_right_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.tc_status_mask = (DMAC_CH_TC_MASK_ENABLE); /* TC_MASK */
++#else
++ i2s_right_tx_channel_dma_llp_desc[ii].Ctrl_TotSize.tc_status_mask = ((ii != (I2S_WM8772_DMAC_LLP_NUM - 1)) ? (DMAC_CH_TC_MASK_ENABLE) : (DMAC_CH_TC_MASK_DISABLE)); /* TC_MASK */
++#endif
++ }
++
++
++ i2s_wm8772_dma_right_tx.channel_id = DMAC_CH_ID(i2s_wm8772_dma_right_tx_channel);
++ i2s_wm8772_dma_right_tx.target_select = DMAC_HW_HAND_SHAKE_I2S_TX_RIGHT_ID;
++
++ i2s_wm8772_dma_right_tx.src_addr = i2s_right_tx_channel_dma_llp_desc[0].SrcAddr;
++ i2s_wm8772_dma_right_tx.dst_addr = i2s_right_tx_channel_dma_llp_desc[0].DstAddr;
++
++ i2s_wm8772_dma_right_tx.src_master = DMAC_CH_SRC_SEL_M1;
++ i2s_wm8772_dma_right_tx.dst_master = DMAC_CH_DST_SEL_M0;
++
++ i2s_wm8772_dma_right_tx.srcad_ctl = DMAC_CH_SRCAD_CTL_INC;
++ i2s_wm8772_dma_right_tx.dstad_ctl = DMAC_CH_DSTAD_CTL_FIX;
++
++ i2s_wm8772_dma_right_tx.src_width = DMAC_CH_SRC_WIDTH_32_BITS;
++ i2s_wm8772_dma_right_tx.dst_width = DMAC_CH_DST_WIDTH_32_BITS;
++
++ // Note here the total number of bytes is specified!!
++ i2s_wm8772_dma_right_tx.transfer_bytes = I2S_WM8772_BUFFER_SIZE * 4;
++
++ i2s_wm8772_dma_right_tx.src_burst_size = DMAC_CH_SRC_BURST_SIZE_1;
++
++ i2s_wm8772_dma_right_tx.llp_addr = (i2s_dmac_llp_num == 1) ? 0 : (u32)i2s_right_tx_channel_dma_llp_desc[0].LLP;
++
++ Hal_Dmac_Configure_DMA_Handshake(&i2s_wm8772_dma_right_tx);
++
++
++//3. *****************************************************************************
++ /*
++ * Configure DMA's channel setting for I2S's Left Channel Rx
++ * Specially pay attention to the settings of src_width, dst_width, and src_burst_size
++ */
++ for (ii = 0; ii < I2S_WM8772_DMAC_LLP_NUM; ii++)
++ {
++ i2s_left_rx_channel_dma_llp_desc[ii].SrcAddr = (I2S_BASE_ADDR + 0xD0);
++
++ i2s_left_rx_channel_dma_llp_desc[ii].DstAddr = i2s_left_channel_llp_buf[ii];
++
++#ifdef I2S_WM8772_DMAC_LLP_RING_TEST
++ i2s_left_rx_channel_dma_llp_desc[ii].LLP = (ii != (I2S_WM8772_DMAC_LLP_NUM - 1)) ? (DMAC_LLP_T *)&lb_rxd_p[ii + 1] : (DMAC_LLP_T *)&lb_rxd_p[1];
++#else
++ i2s_left_rx_channel_dma_llp_desc[ii].LLP = (ii != (I2S_WM8772_DMAC_LLP_NUM - 1)) ? (DMAC_LLP_T *)&lb_rxd_p[ii + 1] : (DMAC_LLP_T *)(0);
++#endif
++
++ tot_size = Hal_Dmac_Get_Channel_Transfer_Unit_Number(I2S_WM8772_BUFFER_SIZE * 4, DMAC_CH_SRC_WIDTH_32_BITS);
++
++ i2s_left_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.tot_size = tot_size; /* TOT_SIZE */
++ i2s_left_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.dst_sel = DMAC_CH_DST_SEL_M1; /* DST_SEL */
++ i2s_left_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.src_sel = DMAC_CH_SRC_SEL_M0; /* SRC_SEL */
++ i2s_left_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.dstad_ctl = DMAC_CH_DSTAD_CTL_INC; /* DSTAD_CTL */
++ i2s_left_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.srcad_ctl = DMAC_CH_SRCAD_CTL_FIX; /* SRCAD_CTL */
++ i2s_left_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.dst_width = DMAC_CH_DST_WIDTH_32_BITS; /* DST_WIDTH */
++ i2s_left_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.src_width = DMAC_CH_SRC_WIDTH_32_BITS; /* SRC_WIDTH */
++
++#ifdef I2S_WM8772_DMAC_LLP_RING_TEST
++ i2s_left_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.tc_status_mask = (DMAC_CH_TC_MASK_ENABLE); /* TC_MASK */
++#else
++ i2s_left_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.tc_status_mask = ((ii != (I2S_WM8772_DMAC_LLP_NUM - 1)) ? (DMAC_CH_TC_MASK_ENABLE) : (DMAC_CH_TC_MASK_DISABLE)); /* TC_MASK */
++#endif
++ }
++
++ i2s_wm8772_dma_left_rx.channel_id = DMAC_CH_ID(i2s_wm8772_dma_left_rx_channel);
++ i2s_wm8772_dma_left_rx.target_select = DMAC_HW_HAND_SHAKE_I2S_RX_LEFT_ID;
++
++ i2s_wm8772_dma_left_rx.src_addr = i2s_left_rx_channel_dma_llp_desc[0].SrcAddr;
++ i2s_wm8772_dma_left_rx.dst_addr = i2s_left_rx_channel_dma_llp_desc[0].DstAddr;
++
++ i2s_wm8772_dma_left_rx.src_master = DMAC_CH_SRC_SEL_M0;
++ i2s_wm8772_dma_left_rx.dst_master = DMAC_CH_DST_SEL_M1;
++
++ i2s_wm8772_dma_left_rx.srcad_ctl = DMAC_CH_SRCAD_CTL_FIX;
++ i2s_wm8772_dma_left_rx.dstad_ctl = DMAC_CH_DSTAD_CTL_INC;
++
++ i2s_wm8772_dma_left_rx.src_width = DMAC_CH_SRC_WIDTH_32_BITS;
++ i2s_wm8772_dma_left_rx.dst_width = DMAC_CH_DST_WIDTH_32_BITS;
++
++ // Note here the total number of bytes is specified!!
++ i2s_wm8772_dma_left_rx.transfer_bytes = I2S_WM8772_BUFFER_SIZE * 4;
++
++ i2s_wm8772_dma_left_rx.src_burst_size = DMAC_CH_SRC_BURST_SIZE_1;
++
++ i2s_wm8772_dma_left_rx.llp_addr = (i2s_dmac_llp_num == 1) ? 0 : (u32)i2s_left_rx_channel_dma_llp_desc[0].LLP;
++
++ Hal_Dmac_Configure_DMA_Handshake(&i2s_wm8772_dma_left_rx);
++
++//4. *****************************************************************************
++ /*
++ * Configure DMA's channel setting for I2S's Right Channel Rx
++ * Specially pay attention to the settings of src_width, dst_width, and src_burst_size
++ */
++ for (ii = 0; ii < I2S_WM8772_DMAC_LLP_NUM; ii++)
++ {
++ i2s_right_rx_channel_dma_llp_desc[ii].SrcAddr = (I2S_BASE_ADDR + 0xCC);
++
++ i2s_right_rx_channel_dma_llp_desc[ii].DstAddr = i2s_right_channel_llp_buf[ii];
++
++#ifdef I2S_WM8772_DMAC_LLP_RING_TEST
++ i2s_right_rx_channel_dma_llp_desc[ii].LLP = (ii != (I2S_WM8772_DMAC_LLP_NUM - 1)) ? (DMAC_LLP_T *)&rb_rxd_p[ii + 1] : (DMAC_LLP_T *)&rb_rxd_p[1];
++#else
++ i2s_right_rx_channel_dma_llp_desc[ii].LLP = (ii != (I2S_WM8772_DMAC_LLP_NUM - 1)) ? (DMAC_LLP_T *)&rb_rxd_p[ii + 1] : (DMAC_LLP_T *)(0);
++#endif
++
++ tot_size = Hal_Dmac_Get_Channel_Transfer_Unit_Number(I2S_WM8772_BUFFER_SIZE * 4, DMAC_CH_SRC_WIDTH_32_BITS);
++
++ i2s_right_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.tot_size = tot_size; /* TOT_SIZE */
++ i2s_right_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.dst_sel = DMAC_CH_DST_SEL_M1; /* DST_SEL */
++ i2s_right_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.src_sel = DMAC_CH_SRC_SEL_M0; /* SRC_SEL */
++ i2s_right_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.dstad_ctl = DMAC_CH_DSTAD_CTL_INC; /* DSTAD_CTL */
++ i2s_right_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.srcad_ctl = DMAC_CH_SRCAD_CTL_FIX; /* SRCAD_CTL */
++ i2s_right_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.dst_width = DMAC_CH_DST_WIDTH_32_BITS; /* DST_WIDTH */
++ i2s_right_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.src_width = DMAC_CH_SRC_WIDTH_32_BITS; /* SRC_WIDTH */
++
++#ifdef I2S_WM8772_DMAC_LLP_RING_TEST
++ i2s_right_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.tc_status_mask = (DMAC_CH_TC_MASK_ENABLE); /* TC_MASK */
++#else
++ i2s_right_rx_channel_dma_llp_desc[ii].Ctrl_TotSize.tc_status_mask = ((ii != (I2S_WM8772_DMAC_LLP_NUM - 1)) ? (DMAC_CH_TC_MASK_ENABLE) : (DMAC_CH_TC_MASK_DISABLE)); /* TC_MASK */
++#endif
++ }
++
++ i2s_wm8772_dma_right_rx.channel_id = DMAC_CH_ID(i2s_wm8772_dma_right_rx_channel);
++ i2s_wm8772_dma_right_rx.target_select = DMAC_HW_HAND_SHAKE_I2S_RX_RIGHT_ID;
++
++ i2s_wm8772_dma_right_rx.src_addr = i2s_right_rx_channel_dma_llp_desc[0].SrcAddr;
++ i2s_wm8772_dma_right_rx.dst_addr = i2s_right_rx_channel_dma_llp_desc[0].DstAddr;
++
++ i2s_wm8772_dma_right_rx.src_master = DMAC_CH_SRC_SEL_M0;
++ i2s_wm8772_dma_right_rx.dst_master = DMAC_CH_DST_SEL_M1;
++
++ i2s_wm8772_dma_right_rx.srcad_ctl = DMAC_CH_SRCAD_CTL_FIX;
++ i2s_wm8772_dma_right_rx.dstad_ctl = DMAC_CH_DSTAD_CTL_INC;
++
++ i2s_wm8772_dma_right_rx.src_width = DMAC_CH_SRC_WIDTH_32_BITS;
++ i2s_wm8772_dma_right_rx.dst_width = DMAC_CH_DST_WIDTH_32_BITS;
++
++ // Note here the total number of bytes is specified!!
++ i2s_wm8772_dma_right_rx.transfer_bytes = I2S_WM8772_BUFFER_SIZE * 4;
++
++ i2s_wm8772_dma_right_rx.src_burst_size = DMAC_CH_SRC_BURST_SIZE_1;
++
++ i2s_wm8772_dma_right_rx.llp_addr = (i2s_dmac_llp_num == 1) ? 0 : (u32)i2s_right_rx_channel_dma_llp_desc[0].LLP;
++
++ Hal_Dmac_Configure_DMA_Handshake(&i2s_wm8772_dma_right_rx);
++//*****************************************************************************
++ return;
++}
++
++
++//=================================================================================
++//
++
++extern void str8100_set_interrupt_trigger(unsigned int, unsigned int, unsigned int);
++
++static irqreturn_t str8100_dma_tc_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs)
++{
++ u32 dma_tc_status,tot_size;
++ u32 len;
++//printk("%s: this_irq=%d\n",__FUNCTION__,this_irq);
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(this_irq);
++ //todo:
++
++ HAL_DMAC_READ_TERMINAL_COUNT_INTERRUPT_STATUS(dma_tc_status);
++printk("%s: this_irq=%d, dma_tc_status=%.8x\n",__FUNCTION__,this_irq,dma_tc_status);
++
++#ifdef I2S_WM8772_DMAC_LLP_RING_TEST
++ u32 i;
++ /*
++ * For LLP ring test, the TC interrupt shoule not happen!!
++ */
++ for(i=0;i<8;i++)
++ if (dma_tc_status & DMAC_CH_ID(i)){
++ HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(DMAC_CH_ID(i));
++ printk("%s: channel %d: Error!! there should be no tc irq happened!!\n",__FUNCTION__,i);
++ }
++
++#else
++ /*
++ * For this case, it's recommended to set I2S_WM8772_DMAC_LLP_NUM = 1
++ */
++ /*
++ * For DMA's Tx for I2S Left Channel
++ */
++ if (dma_tc_status & DMAC_CH_ID(i2s_wm8772_dma_left_tx_channel))
++ {
++ HAL_DMAC_DISABLE_CHANNEL(i2s_wm8772_dma_left_tx_channel);
++
++ HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(DMAC_CH_ID(i2s_wm8772_dma_left_tx_channel));
++
++ /*
++ * Re-initialize DMA's channel for Left_Tx
++ */
++ DMAC_CH_SRC_ADDR(i2s_wm8772_dma_left_tx_channel) = i2s_left_tx_channel_dma_llp_desc[0].SrcAddr;
++
++ DMAC_CH_DST_ADDR(i2s_wm8772_dma_left_tx_channel) = i2s_left_tx_channel_dma_llp_desc[0].DstAddr;
++
++ /*
++ * Note this macro DMAC_CH_SIZE is to configure TOT_SIZE field which is the total transfer
++ * number of source transfer width!
++ */
++ tot_size = Hal_Dmac_Get_Channel_Transfer_Unit_Number(I2S_WM8772_BUFFER_SIZE * 4, DMAC_CH_SRC_WIDTH_32_BITS);
++
++ DMAC_CH_SIZE(i2s_wm8772_dma_left_tx_channel) = tot_size & 0x0FFF;
++
++ HAL_DMAC_ENABLE_CHANNEL(i2s_wm8772_dma_left_tx_channel);
++ }
++
++
++ /*
++ * For DMA's Tx for I2S Right Channel
++ */
++ if (dma_tc_status & DMAC_CH_ID(i2s_wm8772_dma_right_tx_channel))
++ {
++ HAL_DMAC_DISABLE_CHANNEL(i2s_wm8772_dma_right_tx_channel);
++
++ HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(DMAC_CH_ID(i2s_wm8772_dma_right_tx_channel));
++
++ /*
++ * Re-initialize DMA's channel for Right_Tx
++ */
++ DMAC_CH_SRC_ADDR(i2s_wm8772_dma_right_tx_channel) = i2s_right_tx_channel_dma_llp_desc[0].SrcAddr;
++
++ DMAC_CH_DST_ADDR(i2s_wm8772_dma_right_tx_channel) = i2s_right_tx_channel_dma_llp_desc[0].DstAddr;
++
++ /*
++ * Note this macro DMAC_CH_SIZE is to configure TOT_SIZE field which is the total transfer
++ * number of source transfer width!
++ */
++ tot_size = Hal_Dmac_Get_Channel_Transfer_Unit_Number(I2S_WM8772_BUFFER_SIZE * 4, DMAC_CH_SRC_WIDTH_32_BITS);
++
++ DMAC_CH_SIZE(i2s_wm8772_dma_right_tx_channel) = tot_size & 0x0FFF;
++
++ HAL_DMAC_ENABLE_CHANNEL(i2s_wm8772_dma_right_tx_channel);
++ }
++
++
++ /*
++ * For DMA's Rx for I2S Left Channel
++ */
++ if (dma_tc_status & DMAC_CH_ID(i2s_wm8772_dma_left_rx_channel))
++ {
++ HAL_DMAC_DISABLE_CHANNEL(i2s_wm8772_dma_left_rx_channel);
++
++ HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(DMAC_CH_ID(i2s_wm8772_dma_left_rx_channel));
++
++ /*
++ * Re-initialize DMA's channel for Left_Rx
++ */
++ DMAC_CH_SRC_ADDR(i2s_wm8772_dma_left_rx_channel) = i2s_left_rx_channel_dma_llp_desc[0].SrcAddr;
++
++ DMAC_CH_DST_ADDR(i2s_wm8772_dma_left_rx_channel) = i2s_left_rx_channel_dma_llp_desc[0].DstAddr;
++
++ /*
++ * Note this macro DMAC_CH_SIZE is to configure TOT_SIZE field which is the total transfer
++ * number of source transfer width!
++ */
++ tot_size = Hal_Dmac_Get_Channel_Transfer_Unit_Number(I2S_WM8772_BUFFER_SIZE * 4, DMAC_CH_SRC_WIDTH_32_BITS);
++
++ DMAC_CH_SIZE(i2s_wm8772_dma_left_rx_channel) = tot_size & 0x0FFF;
++
++ HAL_DMAC_ENABLE_CHANNEL(i2s_wm8772_dma_left_rx_channel);
++ }
++
++
++ /*
++ * For DMA's Rx for I2S Right Channel
++ */
++ if (dma_tc_status & DMAC_CH_ID(i2s_wm8772_dma_right_rx_channel))
++ {
++ HAL_DMAC_DISABLE_CHANNEL(i2s_wm8772_dma_right_rx_channel);
++
++ HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(DMAC_CH_ID(i2s_wm8772_dma_right_rx_channel));
++
++ /*
++ * Re-initialize DMA's channel for Right_Rx
++ */
++ DMAC_CH_SRC_ADDR(i2s_wm8772_dma_right_rx_channel) = i2s_right_rx_channel_dma_llp_desc[0].SrcAddr;
++
++ DMAC_CH_DST_ADDR(i2s_wm8772_dma_right_rx_channel) = i2s_right_rx_channel_dma_llp_desc[0].DstAddr;
++
++ /*
++ * Note this macro DMAC_CH_SIZE is to configure TOT_SIZE field which is the total transfer
++ * number of source transfer width!
++ */
++ tot_size = Hal_Dmac_Get_Channel_Transfer_Unit_Number(I2S_WM8772_BUFFER_SIZE * 4, DMAC_CH_SRC_WIDTH_32_BITS);
++
++ DMAC_CH_SIZE(i2s_wm8772_dma_right_rx_channel) = tot_size & 0x0FFF;
++
++ HAL_DMAC_ENABLE_CHANNEL(i2s_wm8772_dma_right_rx_channel);
++ }
++#endif
++
++
++
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq);
++
++ return IRQ_HANDLED;
++}
++
++
++static irqreturn_t str8100_i2s_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs)
++{
++ u32 interrupt_status;
++ DEBUG_PRINT("%s: this_irq=%d, I2S_INTERRUPT_STATUS_REG=0x%.8x\n",__FUNCTION__,this_irq,I2S_INTERRUPT_STATUS_REG);
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(this_irq);
++ //todo:
++ interrupt_status = I2S_INTERRUPT_STATUS_REG;
++
++ I2S_RIGHT_TRANSMIT_DATA_REG=0;
++
++
++ if ((interrupt_status & (I2S_RXBF_R_FULL_FLAG | I2S_RXBF_L_FULL_FLAG | I2S_TXBF_R_EMPTY_FLAG | I2S_TXBF_L_EMPTY_FLAG))){
++ printk("%s: Error! wrong i2s empty/full flag\n",__FUNCTION__);
++
++ }
++
++ if ((interrupt_status & (I2S_RXBF_R_OR_FLAG | I2S_RXBF_L_OR_FLAG |I2S_TXBF_R_UR_FLAG | I2S_TXBF_L_UR_FLAG))){
++ // Clear I2S interrupt status
++ i2s_err_lur++;
++ if(i2s_err_lur>10)
++ I2S_INTERRUPT_ENABLE_REG &= ~(I2S_TXBF_L_UR_FLAG);
++// HAL_I2S_DISABLE_I2S();
++
++ printk("%s: Left Channel Tx Underrun!, interrupt_status=%.8x,i2s_err_lur=%d\n",__FUNCTION__,interrupt_status,i2s_err_lur);
++ }
++ I2S_INTERRUPT_STATUS_REG &= 0xf0;
++
++
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq);
++
++ return IRQ_HANDLED;
++}
++
++
++
++//=================================================================================
++
++static void i2s_exit_module(void){
++ printk("%s:\n",__FUNCTION__);
++ remove_proc_entry("str8100/i2s", NULL);
++ free_irq(INTC_I2S_BIT_INDEX, NULL);
++ free_irq(INTC_GDMAC_TC_BIT_INDEX, NULL);
++ free_irq(INTC_GDMAC_ERROR_BIT_INDEX, NULL);
++ if(buffer) {
++ pci_free_consistent(NULL, BUFSIZE*2, buffer, buffer_p);
++ buffer=buffer_p=NULL;
++ lbuffer=lbuffer_p=rbuffer=rbuffer_p=NULL;
++ }
++ if(desc) {
++ pci_free_consistent(NULL, I2S_WM8772_DMAC_LLP_NUM*sizeof(DMAC_LLP_T)*4 , desc, desc_p);
++ desc=desc_p=NULL;
++ lb_txd=lb_txd_p=lb_rxd=lb_rxd_p=NULL;
++ rb_txd=rb_txd_p=rb_rxd=rb_rxd_p=NULL;
++ }
++}
++
++static int __init i2s_init_module(void)
++{
++
++ u32 ret;
++ u32 ii;
++
++ printk("%s:\n",__FUNCTION__);
++
++ buffer = pci_alloc_consistent(NULL, BUFSIZE*2, &buffer_p);
++ if(!buffer){
++ printk("%s: alloc buffer failed.\n",__FUNCTION__);
++ goto exit1;
++ }
++ lbuffer=buffer;
++ lbuffer_p=buffer_p;
++ rbuffer=lbuffer+BUFSIZE;
++ rbuffer_p=lbuffer_p+BUFSIZE;
++
++ desc = pci_alloc_consistent(NULL, I2S_WM8772_DMAC_LLP_NUM*sizeof(DMAC_LLP_T)*4 , &desc_p);
++ if(!desc){
++ printk("%s: alloc buffer for desc failed.\n",__FUNCTION__);
++ goto exit1;
++ }
++ lb_txd=desc;
++ lb_txd_p=desc_p;
++ lb_rxd=desc+I2S_WM8772_DMAC_LLP_NUM;
++ lb_rxd_p=desc_p+I2S_WM8772_DMAC_LLP_NUM;
++
++ rb_txd=desc+I2S_WM8772_DMAC_LLP_NUM*2;
++ rb_txd_p=desc_p+I2S_WM8772_DMAC_LLP_NUM*2;
++ rb_rxd=desc+I2S_WM8772_DMAC_LLP_NUM*3;
++ rb_rxd_p=desc_p+I2S_WM8772_DMAC_LLP_NUM*3;
++
++
++ str8100_set_interrupt_trigger (INTC_I2S_BIT_INDEX,INTC_LEVEL_TRIGGER,INTC_ACTIVE_LOW);
++ if ((ret=request_irq(INTC_I2S_BIT_INDEX, str8100_i2s_irq_handler, 0, "i2s", NULL))){
++ printk("%s: request_irq %d failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,INTC_I2S_BIT_INDEX,ret,-EBUSY);
++ goto exit1;
++ }
++
++ str8100_set_interrupt_trigger (INTC_GDMAC_TC_BIT_INDEX,INTC_LEVEL_TRIGGER,INTC_ACTIVE_HIGH);
++ if ((ret=request_irq(INTC_GDMAC_TC_BIT_INDEX, str8100_dma_tc_irq_handler, 0, "dma tc", NULL))){
++ printk("%s: request_irq %d failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,INTC_GDMAC_TC_BIT_INDEX,ret,-EBUSY);
++ goto exit1;
++ }
++ str8100_set_interrupt_trigger (INTC_GDMAC_ERROR_BIT_INDEX,INTC_LEVEL_TRIGGER,INTC_ACTIVE_HIGH);
++ if ((ret=request_irq(INTC_GDMAC_ERROR_BIT_INDEX, str8100_dma_err_irq_handler, 0, "dma error", NULL))){
++ printk("%s: request_irq %d failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,INTC_GDMAC_ERROR_BIT_INDEX,ret,-EBUSY);
++ goto exit1;
++ }
++
++ /*
++ * Initialize GPIO pins for COM1/COM2/COM3
++ */
++ I2s_Gpio_SSP_Initialise();
++
++ str8100_i2s_init(sampling_rate,DATA_WIDTH, I2S_MODE, I2S_TIMING, I2S_SCLK_MODE);
++
++ /*
++ * Configure Wolfson's WM8772 ADC/DAC
++ */
++ I2s_Configure_WM8772(I2S_TIMING, DATA_WIDTH, I2S_MODE);
++#ifdef I2S_FULL_DUPLEX
++ /*
++ * To support I2S full duplex mode, GPIOA[3] will be used as I2S_DR pin.
++ * It means GPIOA[3] should be as input pin.
++ */
++ MISC_GPIOA_PIN_ENABLE_REG &= ~(0x1 << 3);
++
++ GPIOA_DIRECTION_REG &= ~(0x1 << 3);
++#endif
++
++ I2S_RIGHT_TRANSMIT_DATA_REG=0;
++ I2S_LEFT_TRANSMIT_DATA_REG=0;
++ ii=I2S_RIGHT_RECEIVE_DATA_REG;
++ ii=I2S_LEFT_RECEIVE_DATA_REG;
++
++ /*
++ * Initialize DMAC related configuration
++ */
++
++ i2s_left_channel_llp_buf[0] = lbuffer_p;
++ i2s_right_channel_llp_buf[0] = rbuffer_p;
++ memset ((void *)&lbuffer[0], 0x0, I2S_WM8772_BUFFER_SIZE * 4);
++ memset ((void *)&rbuffer[0], 0x0, I2S_WM8772_BUFFER_SIZE * 4);
++ for (ii = 1; ii < I2S_WM8772_DMAC_LLP_NUM; ii++)
++ {
++ i2s_left_channel_llp_buf[ii] = i2s_left_channel_llp_buf[ii - 1] + (I2S_WM8772_BUFFER_SIZE * 4);
++ i2s_right_channel_llp_buf[ii] = i2s_right_channel_llp_buf[ii - 1] + (I2S_WM8772_BUFFER_SIZE * 4);
++ memset ((void *)&lbuffer[ii*I2S_WM8772_BUFFER_SIZE*4], 0x0, I2S_WM8772_BUFFER_SIZE * 4);
++ memset ((void *)&rbuffer[ii*I2S_WM8772_BUFFER_SIZE*4], 0x0, I2S_WM8772_BUFFER_SIZE * 4);
++ }
++
++ i2s_wm8772_dma_left_tx_channel = 0;
++
++ i2s_wm8772_dma_right_tx_channel = 1;
++
++ i2s_wm8772_dma_left_rx_channel = 2;
++
++ i2s_wm8772_dma_right_rx_channel = 3;
++
++
++ I2s_Configure_WM8772_DMA_Hardware_Handshake();
++
++
++ /*
++ * Enable I2S's interrupt sources
++ * Note for DMA hardware handshake, we only need to enable Left/Right Channel's
++ * Transmit Buffer Underrun.
++ */
++ I2S_INTERRUPT_ENABLE_REG |= (I2S_RXBF_R_OR_FLAG | I2S_RXBF_L_OR_FLAG | I2S_TXBF_R_UR_FLAG | I2S_TXBF_L_UR_FLAG);
++
++ // Enable CPU interrupt
++ local_irq_enable();
++
++ /*
++ * Note DMA must be enabled first before I2S is enabled
++ */
++ HAL_DMAC_ENABLE();
++ HAL_I2S_ENABLE_I2S();
++ printk("%s: exit successfully\n",__FUNCTION__);
++ return 0;
++
++exit1:
++ HAL_I2S_DISABLE_I2S();
++ i2s_exit_module();
++ printk("%s: exit errornous\n",__FUNCTION__);
++ return -EBUSY;
++}
++
++module_init(i2s_init_module);
++module_exit(i2s_exit_module);
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_demo_pcm_legerity_config_2phone.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_demo_pcm_legerity_config_2phone.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_demo_pcm_legerity_config_2phone.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_demo_pcm_legerity_config_2phone.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,921 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++//Options
++//#define DEBUG_PRINT
++//=================================================================================
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++
++#include <linux/kernel.h> /* printk() */
++#include <linux/errno.h> /* error codes */
++#include <linux/types.h> /* size_t */
++#include <linux/proc_fs.h>
++#include <linux/interrupt.h>
++#include <linux/pci.h>
++#include <linux/wait.h> //wait queue
++
++#include <asm/system.h> /* cli(), *_flags */
++#include <asm/uaccess.h> /* copy_*_user */
++
++#include <mach/star_spi.h>
++#include <mach/star_pcm.h>
++#include <mach/star_dmac.h>
++#include <mach/star_demo_dma.h>
++
++#include <sound/pcm.h>
++#include <mach/star_i2s.h>
++
++#define u_int32 u32
++#define u_int16 u16
++#define u_int8 u8
++
++extern void Pcm_Initial_Legerity_Le88221(void);
++
++#define Sys_Interrupt_Disable_Save_Flags(_p) local_irq_save(*(_p))
++//#define Sys_Interrupt_Disable_Save_Flags local_irq_save
++#define Sys_Interrupt_Restore_Flags local_irq_restore
++
++#define Hal_Timer_Timer3_Delay(_p) mdelay(_p/1000)
++//int debug = 0;
++#ifdef DEBUG_PRINT
++#undef DEBUG_PRINT
++//#define DEBUG_PRINT(arg...) if(debug) printk(arg);
++#define DEBUG_PRINT printk
++#else
++//#define DEBUG_PRINT(arg...) if(debug) printk(arg);
++#define DEBUG_PRINT(arg...) printk(KERN_DEBUG arg);
++#endif
++
++
++
++/*
++ * public variable declarations
++ */
++PCM_OBJECT_T pcm_object;
++PCM_CHANNEL_OBJECT_T pcm_channel_object;
++
++static DMAC_HARDWARE_HANDSHAKE_OBJ_T pcm_tx_data0_dma_legerity;
++static DMAC_HARDWARE_HANDSHAKE_OBJ_T pcm_rx_data0_dma_legerity;
++//static DMAC_HARDWARE_HANDSHAKE_OBJ_T pcm_tx_data1_dma_legerity;
++//static DMAC_HARDWARE_HANDSHAKE_OBJ_T pcm_rx_data1_dma_legerity;
++
++static u_int32 pcm_tx_data0_dma_channel_num = 2;
++//static u_int32 pcm_tx_data1_dma_channel_num = 3;
++static u_int32 pcm_rx_data0_dma_channel_num = 4;
++//static u_int32 pcm_rx_data1_dma_channel_num = 5;
++
++//#define BUFFER_SIZE (1 * 256)
++//#define BUFFER_SIZE (1 * 128)
++//#define BUFFER_SIZE (1 * PCM_LOG_PERIOD_SEC * 8000)
++#define BUFFER_SIZE 0xfff
++
++u_int32 *buffer0;
++u_int32 *buffer1;
++u_int32 *buffer2;
++u_int32 *buffer3;
++
++u_int32 *buffer_p0;
++u_int32 *buffer_p1;
++u_int32 *buffer_p2;
++u_int32 *buffer_p3;
++
++u_int32 *pcm_rx0_buffer_le88221;
++u_int32 *pcm_tx0_buffer_le88221;
++u_int32 *pcm_rx1_buffer_le88221;
++u_int32 *pcm_tx1_buffer_le88221;
++
++u_int32 *pcm_rx0_buffer_le88221_p;
++u_int32 *pcm_tx0_buffer_le88221_p;
++u_int32 *pcm_rx1_buffer_le88221_p;
++u_int32 *pcm_tx1_buffer_le88221_p;
++
++
++#define HAL_DMAC_WRITE_CHANNEL0_DESTINATION_ADDRESS(_p) DMAC_CH_DST_ADDR_REG(2) = (_p)
++#define HAL_DMAC_WRITE_CHANNEL1_DESTINATION_ADDRESS(_p) DMAC_CH_DST_ADDR_REG(3) = (_p)
++#define HAL_DMAC_WRITE_CHANNEL2_DESTINATION_ADDRESS(_p) DMAC_CH_DST_ADDR_REG(4) = (_p)
++#define HAL_DMAC_WRITE_CHANNEL3_DESTINATION_ADDRESS(_p) DMAC_CH_DST_ADDR_REG(5) = (_p)
++
++#define HAL_DMAC_WRITE_CHANNEL0_SOURCE_ADDRESS(_p) DMAC_CH_SRC_ADDR_REG(2) = (_p)
++#define HAL_DMAC_WRITE_CHANNEL1_SOURCE_ADDRESS(_p) DMAC_CH_SRC_ADDR_REG(3) = (_p)
++#define HAL_DMAC_WRITE_CHANNEL2_SOURCE_ADDRESS(_p) DMAC_CH_SRC_ADDR_REG(4) = (_p)
++#define HAL_DMAC_WRITE_CHANNEL3_SOURCE_ADDRESS(_p) DMAC_CH_SRC_ADDR_REG(5) = (_p)
++
++#define HAL_DMAC_WRITE_CHANNEL0_TRANSFER_SIZE(_p) DMAC_CH_SIZE_REG(2) = (_p)
++#define HAL_DMAC_WRITE_CHANNEL1_TRANSFER_SIZE(_p) DMAC_CH_SIZE_REG(3) = (_p)
++#define HAL_DMAC_WRITE_CHANNEL2_TRANSFER_SIZE(_p) DMAC_CH_SIZE_REG(4) = (_p)
++#define HAL_DMAC_WRITE_CHANNEL3_TRANSFER_SIZE(_p) DMAC_CH_SIZE_REG(5) = (_p)
++
++#define HAL_DMAC_ENABLE_CHANNEL0(_p) HAL_DMAC_ENABLE_CHANNEL(2)
++#define HAL_DMAC_ENABLE_CHANNEL1(_p) HAL_DMAC_ENABLE_CHANNEL(3)
++#define HAL_DMAC_ENABLE_CHANNEL2(_p) HAL_DMAC_ENABLE_CHANNEL(4)
++#define HAL_DMAC_ENABLE_CHANNEL3(_p) HAL_DMAC_ENABLE_CHANNEL(5)
++
++u_int32 rxbuf_full=0;
++u_int32 txbuf_empty=0;
++u_int32 rxbuf_overrun=0;
++u_int32 txbuf_underrun=0;
++
++u_int32 pcm_dma_ch0_tc_count = 0;
++u_int32 pcm_dma_ch2_tc_count = 0;
++u_int32 pcm_dma_ch1_tc_count = 0;
++u_int32 pcm_dma_ch3_tc_count = 0;
++
++/*
++ * For Legerity's Le88221
++ */
++#define CH0_TX_Le88221_DELAY (0)
++#define CH0_RX_Le88221_DELAY (0)
++
++#define CH1_TX_Le88221_DELAY (8)
++#define CH1_RX_Le88221_DELAY (8)
++
++#define CH2_TX_Le88221_DELAY (32)
++#define CH2_RX_Le88221_DELAY (32)
++
++#define CH3_TX_Le88221_DELAY (48)
++#define CH3_RX_Le88221_DELAY (48)
++
++
++
++
++static struct proc_dir_entry *star_pcm_proc_entry=NULL;
++static u8* txbuffer;
++//static u8* txbuffer_p;
++static u32 txlen=0;
++static u32 txpos=0;
++
++/******************************************************************************
++ *
++ * FUNCTION: Hal_Pcm_Initialize
++ * PURPOSE:
++ *
++ ******************************************************************************/
++void Hal_Pcm_Initialize(PCM_OBJECT_T *pPcm_Object)
++{
++ //u_int32 volatile tx_data0 = 0;
++ u_int32 volatile rx_data0 = 0;
++
++
++ // Enable PCM pins
++ HAL_MISC_ENABLE_PCM_PINS();
++
++ // Enable PCM clock
++ HAL_PWRMGT_ENABLE_PCM_CLOCK();
++
++/* if (p2s_reset_flag == 0)
++ {
++ Hal_Pwrmgt_Software_Reset(PWRMGT_P2S_SOFTWARE_RESET_BIT_INDEX);
++
++ p2s_reset_flag = 1;
++ }
++*/
++
++ /*
++ * Note PCM is NOT enabled after this function is invoked!!
++ */
++ PCM_CONFIGURATION_0_REG = pPcm_Object->config_0;
++ PCM_CONFIGURATION_1_REG = pPcm_Object->config_1;
++ PCM_CHANNEL_0_CONFIG_REG = pPcm_Object->channel_0_config;
++ PCM_CHANNEL_1_CONFIG_REG = pPcm_Object->channel_1_config;
++ PCM_CHANNEL_2_CONFIG_REG = pPcm_Object->channel_2_config;
++ PCM_CHANNEL_3_CONFIG_REG = pPcm_Object->channel_3_config;
++ PCM_INTERRUPT_ENABLE_REG = pPcm_Object->interrupt_config;
++
++/*
++ if (pPcm_Object->interrupt_config)
++ {
++ Hal_Intc_Register_Interrupt(&pPcm_Object->intc_obj);
++ }
++*/
++ rx_data0 = PCM_RX_DATA_63_32_REG;
++ rx_data0 = PCM_RX_DATA_31_0_REG;
++
++ // Clear spurious interrupt sources
++ PCM_INTERRUPT_STATUS_REG = PCM_RXBUF_OVERRUN_FG | PCM_TXBUF_UNDERRUN_FG;
++
++ // Disable PCM
++ HAL_PCM_DISABLE_PCM();
++}
++
++
++/******************************************************************************
++ *
++ * FUNCTION: Hal_Pcm_Is_Transmit_Buffer_Empty
++ * PURPOSE:
++ *
++ ******************************************************************************/
++u_int32 Hal_Pcm_Is_Transmit_Buffer_Empty(void)
++{
++ /*
++ * Return value :
++ * 1 : PCM Tx Transmit Buffer Empty
++ * 0 : PCM Tx Transmit Buffer Not Empty
++ */
++ return ((PCM_INTERRUPT_STATUS_REG & PCM_TXBUF_EMPTY_FG) ? 1 : 0);
++}
++
++
++/******************************************************************************
++ *
++ * FUNCTION: Hal_Pcm_Is_Receive_Buffer_Full
++ * PURPOSE:
++ *
++ ******************************************************************************/
++u_int32 Hal_Pcm_Is_Receive_Buffer_Full(void)
++{
++ /*
++ * Return value :
++ * 1 : PCM Rx Receive Buffer Full
++ * 0 : PCM Rx Receive Buffer Not Full
++ */
++ return ((PCM_INTERRUPT_STATUS_REG & PCM_RXBUF_FULL_FG) ? 1 : 0);
++}
++
++/******************************************************************************
++ *
++ * FUNCTION: Pcm_Configure_DMA_Hardware_Handshake_For_Legerity
++ * PURPOSE:
++ *
++ ******************************************************************************/
++void Pcm_Configure_DMA_Hardware_Handshake_For_Legerity(void)
++{
++
++ DEBUG_PRINT(" %s : ==>\n" ,__FUNCTION__);
++#if 1
++ /*
++ * Configure DMA's channel setting for PCM Transmit Data[31:0] Register
++ * Specially pay attention to the settings of src_width, dst_width, and src_burst_size
++ */
++
++ pcm_tx_data0_dma_legerity.channel_id = DMAC_CH_ID(pcm_tx_data0_dma_channel_num);//0
++ pcm_tx_data0_dma_legerity.target_select = DMAC_HW_HAND_SHAKE_PCM_TX0_ID;//0
++
++ pcm_tx_data0_dma_legerity.src_addr = (u_int32)pcm_tx0_buffer_le88221_p;//SCR
++ pcm_tx_data0_dma_legerity.dst_addr = (SYSPA_PCM_BASE_ADDR + 0x98);//DST
++
++ pcm_tx_data0_dma_legerity.src_master = DMAC_CH_SRC_SEL_M1;//1
++ pcm_tx_data0_dma_legerity.dst_master = DMAC_CH_DST_SEL_M0;//0
++
++ pcm_tx_data0_dma_legerity.srcad_ctl = DMAC_CH_SRCAD_CTL_INC;//0
++ pcm_tx_data0_dma_legerity.dstad_ctl = DMAC_CH_DSTAD_CTL_FIX;//2
++
++ pcm_tx_data0_dma_legerity.src_width = DMAC_CH_SRC_WIDTH_32_BITS;
++ pcm_tx_data0_dma_legerity.dst_width = DMAC_CH_DST_WIDTH_32_BITS;
++
++ // Note here the total number of bytes is specified!!
++ pcm_tx_data0_dma_legerity.transfer_bytes = BUFFER_SIZE * 4;
++
++ pcm_tx_data0_dma_legerity.src_burst_size = DMAC_CH_SRC_BURST_SIZE_1;//0
++
++ // Note this DMA's channel will be enabled when the following function is invoked!!
++ Hal_Dmac_Configure_DMA_Handshake(&pcm_tx_data0_dma_legerity);
++
++
++ /*
++ * Configure DMA's channel setting for PCM Receive Data[31:0] Register
++ * Specially pay attention to the settings of src_width, dst_width, and src_burst_size
++ */
++ pcm_rx_data0_dma_legerity.channel_id = DMAC_CH_ID(pcm_rx_data0_dma_channel_num);//2
++ pcm_rx_data0_dma_legerity.target_select = DMAC_HW_HAND_SHAKE_PCM_RX0_ID;//1
++
++ pcm_rx_data0_dma_legerity.src_addr = (SYSPA_PCM_BASE_ADDR + 0xA0);//SCR
++ pcm_rx_data0_dma_legerity.dst_addr = (u_int32)pcm_rx0_buffer_le88221_p;//DST
++
++ pcm_rx_data0_dma_legerity.src_master = DMAC_CH_SRC_SEL_M0;//0
++ pcm_rx_data0_dma_legerity.dst_master = DMAC_CH_DST_SEL_M1;//1
++
++ pcm_rx_data0_dma_legerity.srcad_ctl = DMAC_CH_SRCAD_CTL_FIX;//2
++ pcm_rx_data0_dma_legerity.dstad_ctl = DMAC_CH_DSTAD_CTL_INC;//0
++
++ pcm_rx_data0_dma_legerity.src_width = DMAC_CH_SRC_WIDTH_32_BITS;
++ pcm_rx_data0_dma_legerity.dst_width = DMAC_CH_DST_WIDTH_32_BITS;
++
++ // Note here the total number of bytes is specified!!
++ pcm_rx_data0_dma_legerity.transfer_bytes = BUFFER_SIZE * 4;
++
++ pcm_rx_data0_dma_legerity.src_burst_size = DMAC_CH_SRC_BURST_SIZE_1;
++
++ // Note this DMA's channel will be enabled when the following function is invoked!!
++ Hal_Dmac_Configure_DMA_Handshake(&pcm_rx_data0_dma_legerity);
++#endif
++
++
++#if 0
++ /*
++ * Configure DMA's channel setting for PCM Transmit Data[31:0] Register
++ * Specially pay attention to the settings of src_width, dst_width, and src_burst_size
++ */
++ pcm_tx_data1_dma_legerity.channel_id = DMAC_CH_ID(pcm_tx_data1_dma_channel_num);//1
++ pcm_tx_data1_dma_legerity.target_select = DMAC_HW_HAND_SHAKE_PCM_TX1_ID;
++
++ pcm_tx_data1_dma_legerity.src_addr = (u_int32)pcm_tx1_buffer_le88221_p;
++ pcm_tx_data1_dma_legerity.dst_addr = (SYSPA_PCM_BASE_ADDR + 0x9C);
++
++ pcm_tx_data1_dma_legerity.src_master = DMAC_CH_SRC_SEL_M1;
++ pcm_tx_data1_dma_legerity.dst_master = DMAC_CH_DST_SEL_M0;
++
++ pcm_tx_data1_dma_legerity.srcad_ctl = DMAC_CH_SRCAD_CTL_INC;
++ pcm_tx_data1_dma_legerity.dstad_ctl = DMAC_CH_DSTAD_CTL_FIX;
++
++ pcm_tx_data1_dma_legerity.src_width = DMAC_CH_SRC_WIDTH_32_BITS;
++ pcm_tx_data1_dma_legerity.dst_width = DMAC_CH_DST_WIDTH_32_BITS;
++
++ // Note here the total number of bytes is specified!!
++ pcm_tx_data1_dma_legerity.transfer_bytes = BUFFER_SIZE * 4;
++
++ pcm_tx_data1_dma_legerity.src_burst_size = DMAC_CH_SRC_BURST_SIZE_1;
++
++ Hal_Dmac_Configure_DMA_Handshake(&pcm_tx_data1_dma_legerity);
++
++
++
++ /*
++ * Configure DMA's channel setting for PCM Receive Data[31:0] Register
++ * Specially pay attention to the settings of src_width, dst_width, and src_burst_size
++ */
++ pcm_rx_data1_dma_legerity.channel_id = DMAC_CH_ID(pcm_rx_data1_dma_channel_num);//3
++ pcm_rx_data1_dma_legerity.target_select = DMAC_HW_HAND_SHAKE_PCM_RX1_ID;
++ pcm_rx_data1_dma_legerity.src_addr = (SYSPA_PCM_BASE_ADDR + 0xA4);
++ pcm_rx_data1_dma_legerity.dst_addr = (u_int32)pcm_rx1_buffer_le88221_p;
++
++ pcm_rx_data1_dma_legerity.src_master = DMAC_CH_SRC_SEL_M0;
++ pcm_rx_data1_dma_legerity.dst_master = DMAC_CH_DST_SEL_M1;
++
++ pcm_rx_data1_dma_legerity.srcad_ctl = DMAC_CH_SRCAD_CTL_FIX;
++ pcm_rx_data1_dma_legerity.dstad_ctl = DMAC_CH_DSTAD_CTL_INC;
++
++ pcm_rx_data1_dma_legerity.src_width = DMAC_CH_SRC_WIDTH_32_BITS;
++ pcm_rx_data1_dma_legerity.dst_width = DMAC_CH_DST_WIDTH_32_BITS;
++
++ // Note here the total number of bytes is specified!!
++ pcm_rx_data1_dma_legerity.transfer_bytes = BUFFER_SIZE * 4;
++
++ pcm_rx_data1_dma_legerity.src_burst_size = DMAC_CH_SRC_BURST_SIZE_1;
++
++ Hal_Dmac_Configure_DMA_Handshake(&pcm_rx_data1_dma_legerity);
++#endif
++
++ return;
++}
++
++#if 0
++static irqreturn_t str8100_pcm_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs)
++{
++ u_int32 volatile interrupt_status;
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(this_irq);
++#if 1
++ PCM_INTERRUPT_STATUS_REG&=0xc0;
++
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq);
++
++ return IRQ_HANDLED;
++#endif
++ DEBUG_PRINT("%s: this_irq=%d, PCM_INTERRUPT_STATUS_REG=0x%.8x\n",__FUNCTION__,this_irq,PCM_INTERRUPT_STATUS_REG);
++
++ // Get PCM interrupt status
++ HAL_PCM_READ_INTERRUPT_STATUS(interrupt_status);
++ if (interrupt_status & PCM_RXBUF_FULL_FG){
++ rxbuf_full++;
++ DEBUG_PRINT("%s: rx buf full\n",__FUNCTION__);
++ }
++
++ if (interrupt_status & PCM_TXBUF_EMPTY_FG){
++ txbuf_empty++;
++ DEBUG_PRINT("%s: tx buf empty\n",__FUNCTION__);
++ }
++ if (interrupt_status & PCM_RXBUF_OVERRUN_FG){
++ // Clear PCM interrupt status
++ HAL_PCM_CLEAR_INTERRUPT_STATUS(PCM_RXBUF_OVERRUN_FG);
++
++ rxbuf_overrun++;
++ DEBUG_PRINT("%s: rx buf overrun\n",__FUNCTION__);
++ }
++
++ if (interrupt_status & PCM_TXBUF_UNDERRUN_FG){
++ // Clear PCM interrupt status
++ HAL_PCM_CLEAR_INTERRUPT_STATUS(PCM_TXBUF_UNDERRUN_FG);
++
++ txbuf_underrun++;
++ DEBUG_PRINT("%s: tx buf underrun\n",__FUNCTION__);
++ }
++ PCM_INTERRUPT_STATUS_REG&=0xc0;
++
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq);
++
++ return IRQ_HANDLED;
++}
++#endif
++
++#ifdef CONFIG_SND_STAR_I2S_WM8759
++#define I2S_CHANNEL_NUM 2
++extern DMAC_HARDWARE_HANDSHAKE_OBJ_T i2s_wm8759_dma_handshake_tx[I2S_CHANNEL_NUM];
++struct snd_star_i2s_wm8759_pcm_priv {
++ struct snd_star_i2s_wm8759_priv *card_priv;
++ spinlock_t lock;
++ struct timer_list timer;
++ unsigned int buffer_size_in_bytes;
++ unsigned int period_size_in_bytes;
++ unsigned int pcm_bps; /* bytes per second */
++ unsigned int pcm_jiffie; /* bytes per one jiffie */
++
++ unsigned int pcm_irq_pos[I2S_CHANNEL_NUM]; /* IRQ position */
++ unsigned int pcm_buf_pos[I2S_CHANNEL_NUM]; /* position in buffer */
++
++ u32 period_count_in_buffer; //(buffer_size/period_size)
++ u32 desc_count; //period_count_in_buffer*channels
++
++ u32 desc_size_in_bytes; //desc_count*sizeof(DMAC_LLP_T);
++ DMAC_LLP_T* desc; //vir addr of desc buffer allocated
++ DMAC_LLP_T* desc_p; //phy addr of desc buffer allocated
++
++ struct snd_pcm_substream *substream;
++};
++#endif
++
++static DECLARE_WAIT_QUEUE_HEAD(wg);
++static int swap_flag=0;
++static int call_swap_buffer(void)
++{
++ //current->pid, current->comm);
++ //printk(KERN_INFO "swap_flag=%d ...\n",swap_flag);
++
++ //wake up swap buffer
++ swap_flag=1;
++ wake_up_interruptible(&wg);
++ return 0;
++
++}
++
++
++static int swap_buffer_thread(void *data)
++{
++ int i;
++ u_int32 *swap_buffer,*swap_buffer_p;
++ for(;;){
++ //printk(KERN_INFO "swap buffer start \n");
++ if(pcm_rx0_buffer_le88221==buffer0){
++ //printk("rx change to buffer1 \n");
++ swap_buffer=buffer2;
++ swap_buffer_p=buffer_p2;
++ }else if(pcm_rx0_buffer_le88221==buffer1){
++ //printk("rx change to buffer2 \n");
++ swap_buffer=buffer0;
++ swap_buffer_p=buffer_p0;
++
++ }else{
++ //printk("rx change to buffer0 \n");
++ swap_buffer=buffer1;
++ swap_buffer_p=buffer_p1;
++ }
++ for(i=0;i<BUFFER_SIZE;i++)
++ swap_buffer[i] = \
++ ((swap_buffer[i] >> 8) & 0x000000FF) | \
++ ((swap_buffer[i] << 8) & 0x0000FF00);
++
++ //printk("swap buffer end \n");
++ if(signal_pending(current))
++ break;
++ wait_event_interruptible(wg, swap_flag !=0);
++ swap_flag=0;
++ }
++
++ return 1;
++}
++
++//static irqreturn_t str8100_dma_tc_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs)
++static irqreturn_t str8100_dma_tc_irq_handler(int this_irq, void *dev_id)
++{
++ u_int32 volatile dma_tc_status;
++ u32 i;
++
++ DEBUG_PRINT("%s: this_irq=%d,tc_status=0x%.8x\n",__FUNCTION__,this_irq,((DMAC_INT_TC_STATUS_REG) & 0xFF) );
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(this_irq);
++ HAL_DMAC_READ_TERMINAL_COUNT_INTERRUPT_STATUS(dma_tc_status);
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_GDMAC_TC_BIT_INDEX);
++ HAL_DMAC_READ_TERMINAL_COUNT_INTERRUPT_STATUS(dma_tc_status);
++
++#ifdef CONFIG_SND_STAR_I2S_WM8759
++ if (dma_tc_status & DMAC_CH_ID(0) || dma_tc_status & DMAC_CH_ID(1)) // WM8759
++ {
++ for(i=0;i<I2S_CHANNEL_NUM;i++)
++ {
++ struct snd_pcm_substream *substream=(struct snd_pcm_substream *)i2s_wm8759_dma_handshake_tx[i].private_data;
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ struct snd_star_i2s_wm8759_pcm_priv *dpcm = (struct snd_star_i2s_wm8759_pcm_priv *)runtime->private_data;
++ HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(DMAC_CH_ID(i2s_wm8759_dma_handshake_tx[i].channel_num));
++ dma_tc_status &= ~(DMAC_CH_ID(i2s_wm8759_dma_handshake_tx[i].channel_num));
++
++ //currently assume period size (in frames) is the DMA totsize
++ dpcm->pcm_irq_pos[i] += dpcm->period_size_in_bytes/runtime->channels;
++ dpcm->pcm_buf_pos[i] += dpcm->period_size_in_bytes/runtime->channels;
++ dpcm->pcm_buf_pos[i] %= dpcm->buffer_size_in_bytes/runtime->channels;
++
++ if (dpcm->pcm_irq_pos[i] >= (dpcm->period_size_in_bytes/runtime->channels)) {
++ dpcm->pcm_irq_pos[i] %= (dpcm->period_size_in_bytes/runtime->channels);
++ snd_pcm_period_elapsed(dpcm->substream);
++ }
++ }
++ }
++#endif
++
++ //DMA Rx reg 0
++ if (dma_tc_status & DMAC_CH_ID(pcm_rx_data0_dma_channel_num))
++ {
++ HAL_DMAC_DISABLE_CHANNEL(pcm_rx_data0_dma_channel_num);
++ HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(DMAC_CH_ID(pcm_rx_data0_dma_channel_num));
++ dma_tc_status &= ~(DMAC_CH_ID(pcm_rx_data0_dma_channel_num));
++
++ //make pcm ch0 to ch1, and vice versa
++ if(pcm_rx0_buffer_le88221==buffer0){
++ //printk("rx change to buffer1 \n");
++ pcm_rx0_buffer_le88221=buffer1;
++ pcm_rx0_buffer_le88221_p=buffer_p1;
++
++ }
++ else if(pcm_rx0_buffer_le88221==buffer1){
++ //printk("rx change to buffer2 \n");
++ pcm_rx0_buffer_le88221=buffer2;
++ pcm_rx0_buffer_le88221_p=buffer_p2;
++
++ }else{
++ //printk("rx change to buffer0 \n");
++ pcm_rx0_buffer_le88221=buffer0;
++ pcm_rx0_buffer_le88221_p=buffer_p0;
++ }
++
++ // Re-initialize DMA's channel for Rx
++ HAL_DMAC_WRITE_CHANNEL2_DESTINATION_ADDRESS((u_int32)pcm_rx0_buffer_le88221_p);
++ HAL_DMAC_WRITE_CHANNEL2_SOURCE_ADDRESS(SYSPA_PCM_BASE_ADDR + 0xA0);
++ HAL_DMAC_WRITE_CHANNEL2_TRANSFER_SIZE(BUFFER_SIZE);
++ HAL_DMAC_ENABLE_CHANNEL2();
++ call_swap_buffer();
++ }
++
++ //DMA Tx reg 0
++ if (dma_tc_status & DMAC_CH_ID(pcm_tx_data0_dma_channel_num))
++ {
++ HAL_DMAC_DISABLE_CHANNEL(pcm_tx_data0_dma_channel_num);
++ HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(DMAC_CH_ID(pcm_tx_data0_dma_channel_num));
++ dma_tc_status &= ~(DMAC_CH_ID(pcm_tx_data0_dma_channel_num));
++
++ //swap buffer
++ if(pcm_tx0_buffer_le88221==buffer2) {
++ //printk("tx change to buffer0 \n");
++ pcm_tx0_buffer_le88221=buffer0;
++ pcm_tx0_buffer_le88221_p=buffer_p0;
++ }
++ else if(pcm_tx0_buffer_le88221==buffer1){
++ //printk("tx change to buffer2 \n");
++ pcm_tx0_buffer_le88221=buffer2;
++ pcm_tx0_buffer_le88221_p=buffer_p2;
++ }
++ else{
++ //printk("tx change to buffer1 \n");
++ pcm_tx0_buffer_le88221=buffer1;
++ pcm_tx0_buffer_le88221_p=buffer_p1;
++ }
++
++ // Re-initialize DMA's channel for Tx
++ HAL_DMAC_WRITE_CHANNEL0_SOURCE_ADDRESS((u_int32)pcm_tx0_buffer_le88221_p);
++ HAL_DMAC_WRITE_CHANNEL0_DESTINATION_ADDRESS(SYSPA_PCM_BASE_ADDR + 0x98);
++ HAL_DMAC_WRITE_CHANNEL0_TRANSFER_SIZE(BUFFER_SIZE);
++ HAL_DMAC_ENABLE_CHANNEL0();
++ }
++
++ /*
++ * If there is any bit set, it means something wrong!!
++ */
++ if (dma_tc_status)
++ {
++ // Something wrong because spurious interrupt happens!!
++ printk("Something wrong because spurious interrupt happens(%.8x)!!\n",dma_tc_status);
++ }
++
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq);
++
++ return IRQ_HANDLED;
++}
++
++void pcm_init(void){
++ u32 flags;
++ //u32 tmp;
++ local_irq_save(flags);
++ /*
++ * Check CLK_OUT_SEL_Pin for 8.192 MHz
++ */
++ DEBUG_PRINT("%s:\n",__FUNCTION__);
++// HAL_MISC_DISABLE_SPI_SERIAL_FLASH_BANK_ACCESS();
++ HAL_PWRMGT_CONFIGURE_CLOCK_OUT_PIN(10, 0);
++
++ /*
++ * For IDL Case:
++ * UDCLK : 4.096 MHz
++ * PCMCLK : 2.048 MHz = 4.096/(1 + 1)
++ * FSYNCCLK : 8 KHz = 2048000/(255 + 1)
++ */
++ pcm_object.config_0 = ((/*clock_rate_ctrl*/1 & 0x7) << 0) | /* Configure master clock rate */
++ (0 << 12) | /* Disable loopback mode */
++ (1 << 13) | /* Enable master mode */
++ (0 << 14) | /* Select IDL mode */
++ /*(1 << 24) | */ /* Enable PCM data swap */
++ (0 << 24) | /* Disable PCM data swap */
++ (0 << 31); /* Disable PCM */
++
++ /*
++ * Note FSYNC_WIDE will be ignored when the PCM is configured as Slave or as Master
++ * with GCI mode
++ */
++ pcm_object.config_1 = ((0 & 0x1) << 15); /* Select FSYNC mode , 0 : short FSYNC, 1 : long FSYNC */
++
++
++ /*
++ * Configure the settings of PCM's channel
++ */
++ pcm_object.channel_0_config = ((CH0_TX_Le88221_DELAY & 0x7F) << 0) |
++ ((CH0_RX_Le88221_DELAY & 0x7F) << 8) |
++ ((PCM_DATA_BIT_8 & 0x1) << 22) |
++ (1 << 23); /* Enable this channel */
++
++ pcm_object.channel_1_config = ((CH1_TX_Le88221_DELAY & 0x7F) << 0) |
++ ((CH1_RX_Le88221_DELAY & 0x7F) << 8) |
++ ((PCM_DATA_BIT_8 & 0x1) << 22) |
++ (1 << 23); /* Enable this channel */
++
++ pcm_object.channel_2_config = ((CH2_TX_Le88221_DELAY & 0x7F) << 0) |
++ ((CH2_RX_Le88221_DELAY & 0x7F) << 8) |
++ ((0 & 0x1) << 22) |
++ (0 << 23); /* Disable this channel */
++
++ pcm_object.channel_3_config = ((CH3_TX_Le88221_DELAY & 0x7F) << 0) |
++ ((CH3_RX_Le88221_DELAY & 0x7F) << 8) |
++ ((0 & 0x1) << 22) |
++ (0 << 23); /* Disable this channel */
++
++
++ // Enable PCM's interrupt sources
++// pcm_object.interrupt_config = 0;
++ pcm_object.interrupt_config = PCM_RXBUF_OVERRUN_FG | PCM_TXBUF_UNDERRUN_FG;
++// pcm_object.interrupt_config |=PCM_RXBUF_FULL_FG|PCM_TXBUF_EMPTY_FG;
++
++
++
++ // Initialize PCM's setting
++ Hal_Pcm_Initialize(&pcm_object);
++
++
++ // Disable PCM interrupt since GDMA hardware handshake interrupt will be used.
++ //HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_PCM_BIT_INDEX);
++
++ // Initialize GDMA hardware handshake for PCM
++ Pcm_Configure_DMA_Hardware_Handshake_For_Legerity();
++
++
++ /*
++ * PCM will start to transmit and receive data once PCM is enabled. To avoid
++ * PCM Transmit Buffer underrun, we have to put one transmit data into PCM
++ * Transmit Buffer before PCM is enabled!!
++ * Note PCM channel 0 is used.
++ */
++/*
++ PCM_TX_DATA_31_0_REG=0;
++ PCM_TX_DATA_63_32_REG=0;
++
++ tmp=PCM_RX_DATA_31_0_REG;
++ tmp=PCM_RX_DATA_63_32_REG;
++*/
++ HAL_PCM_CLEAR_INTERRUPT_STATUS((PCM_RXBUF_OVERRUN_FG | PCM_TXBUF_UNDERRUN_FG));//(0x4 | 0x8)=0xC
++
++/*{
++ u32 dma_ch;
++ for (dma_ch = 0; dma_ch < DMAC_MAX_CHANNEL_NUM; dma_ch++)
++ {
++ HAL_DMAC_CLEAR_ERROR_ABORT_INTERRUPT_STATUS(DMAC_CH_ID(dma_ch));
++ HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(DMAC_CH_ID(dma_ch));
++ }
++}
++*/
++ HAL_DMAC_ENABLE();
++ HAL_PCM_ENABLE_PCM();
++
++ /*
++ * Configure Legerity's Le88221 MPI Interface
++ */
++ Pcm_Initial_Legerity_Le88221();
++ local_irq_restore(flags);
++
++
++ DEBUG_PRINT("%s: end =>\n",__FUNCTION__);
++
++}
++
++//=================================================================================
++static int proc_read_pcm(char *buf, char **start, off_t offset,
++ int count, int *eof, void *data)
++{
++ int len=0;
++ DEBUG_PRINT("%s:\n",__FUNCTION__);
++ len += sprintf(buf, "test\n"
++ "test\n");
++ *eof = 1;
++ return len;
++}
++
++static int proc_write_pcm(struct file *file, const char *buffer, unsigned long count, void *data){
++ int len=0;
++ DEBUG_PRINT("%s: count=%ld\n",__FUNCTION__,count);
++ pcm_init();
++
++ return count;
++ //is buffer free?
++ if(txpos!=txlen){
++ printk("%s: buffer not free\n",__FUNCTION__);
++ return -EBUSY;
++ }
++
++ //copy the raw data to local buffer
++ if(count>BUFFER_SIZE) len=BUFFER_SIZE;
++ else len=count;
++
++ if(copy_from_user(txbuffer,buffer,len)){
++ return -EFAULT;
++ }
++ txlen=len;
++ txpos=0;
++
++ //Initialization
++
++ // Enable CPU interrupt
++ local_irq_enable();
++
++ /*
++ * Note DMA must be enabled first before PCM is enabled
++ */
++ HAL_DMAC_ENABLE();
++
++
++ while (1){
++ local_irq_disable();
++ if (txpos>txlen||txlen==0){
++ // Disable PCM
++
++ break;
++ }
++ local_irq_enable();
++ }
++ DEBUG_PRINT("%s: exit. \n",__FUNCTION__);
++
++ local_irq_enable();
++
++ return len;
++
++//debug:
++
++// return count;
++}
++
++static void __exit pcm_exit_module(void){
++ printk("%s:\n",__FUNCTION__);
++ remove_proc_entry("str8100/pcm", NULL);
++ free_irq(INTC_PCM_BIT_INDEX, NULL);
++ free_irq(INTC_GDMAC_TC_BIT_INDEX, NULL);
++ free_irq(INTC_GDMAC_ERROR_BIT_INDEX, NULL);
++/* if(txbuffer) {
++ pci_free_consistent(NULL, BUFFER_SIZE*4, txbuffer, txbuffer_p);
++ txbuffer=txbuffer_p=NULL;
++ }
++*/
++#if 1
++ if(buffer0) {
++ pci_free_consistent(NULL, BUFFER_SIZE*4, buffer0, *buffer_p0);
++ buffer0=buffer_p0=NULL;
++ }
++
++ if(buffer1) {
++ pci_free_consistent(NULL, BUFFER_SIZE*4, buffer1, *buffer_p1);
++ buffer1=buffer_p1=NULL;
++ }
++ if(buffer2) {
++ pci_free_consistent(NULL, BUFFER_SIZE*4, buffer2, *buffer_p2);
++ buffer2=buffer_p2=NULL;
++ }
++
++ if(buffer3) {
++ pci_free_consistent(NULL, BUFFER_SIZE*4, buffer3, *buffer_p3);
++ buffer3=buffer_p3=NULL;
++ }
++#else
++ printk("%s:buffers not freed yet!!!\n",__FUNCTION__);
++#endif
++}
++
++extern void str8100_set_interrupt_trigger(unsigned int, unsigned int, unsigned int);
++static int __init pcm_init_module(void)
++{
++
++ u32 ret;
++
++ printk("%s:\n",__FUNCTION__);
++
++ star_pcm_proc_entry = create_proc_entry("str8100/pcm", S_IFREG | S_IRUGO, NULL);
++ if(!star_pcm_proc_entry){
++ return -EBUSY;
++ }
++ star_pcm_proc_entry->read_proc=proc_read_pcm;
++ star_pcm_proc_entry->write_proc=proc_write_pcm;
++
++/*
++ txbuffer = pci_alloc_consistent(NULL, BUFFER_SIZE, &txbuffer_p);
++ if(!txbuffer){
++ printk("%s: alloc txbuffer failed.\n",__FUNCTION__);
++ goto exit1;
++ }
++*/
++ buffer0 = pci_alloc_consistent(NULL, BUFFER_SIZE*4, &buffer_p0);
++ if(!buffer0){
++ printk("%s: alloc buffer0 failed.\n",__FUNCTION__);
++ goto exit1;
++ }
++ buffer1 = pci_alloc_consistent(NULL, BUFFER_SIZE*4, &buffer_p1);
++ if(!buffer1){
++ printk("%s: alloc buffer1 failed.\n",__FUNCTION__);
++ goto exit1;
++ }
++ buffer2 = pci_alloc_consistent(NULL, BUFFER_SIZE*4, &buffer_p2);
++ if(!buffer2){
++ printk("%s: alloc buffer2 failed.\n",__FUNCTION__);
++ goto exit1;
++ }
++ buffer3 = pci_alloc_consistent(NULL, BUFFER_SIZE*4, &buffer_p3);
++ if(!buffer3){
++ printk("%s: alloc buffer3 failed.\n",__FUNCTION__);
++ goto exit1;
++ }
++ DEBUG_PRINT("%s: buffers allocated... \n",__FUNCTION__);
++
++ pcm_rx0_buffer_le88221=buffer0;
++ pcm_tx0_buffer_le88221=buffer1;
++ //pcm_rx1_buffer_le88221=buffer2;
++ //pcm_tx1_buffer_le88221=buffer3;
++
++ pcm_rx0_buffer_le88221_p=buffer_p0;
++ pcm_tx0_buffer_le88221_p=buffer_p1;
++ //pcm_rx1_buffer_le88221_p=buffer_p2;
++ //pcm_tx1_buffer_le88221_p=buffer_p3;
++/*
++ str8100_set_interrupt_trigger (INTC_PCM_BIT_INDEX,INTC_LEVEL_TRIGGER,INTC_ACTIVE_LOW);
++ if((ret=request_irq(INTC_PCM_BIT_INDEX, str8100_pcm_irq_handler, 0, "pcm", NULL))){
++ printk("%s: request_irq %d failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,INTC_PCM_BIT_INDEX,ret,-EBUSY);
++ goto exit1;
++ }
++*/
++ str8100_set_interrupt_trigger (INTC_GDMAC_TC_BIT_INDEX,INTC_LEVEL_TRIGGER,INTC_ACTIVE_HIGH);
++ if ((ret=request_irq(INTC_GDMAC_TC_BIT_INDEX, str8100_dma_tc_irq_handler, 0, "dma tc", NULL))){
++ printk("%s: request_irq %d failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,INTC_GDMAC_TC_BIT_INDEX,ret,-EBUSY);
++ goto exit1;
++ }
++ str8100_set_interrupt_trigger (INTC_GDMAC_ERROR_BIT_INDEX,INTC_LEVEL_TRIGGER,INTC_ACTIVE_HIGH);
++ if ((ret=request_irq(INTC_GDMAC_ERROR_BIT_INDEX, str8100_dma_err_irq_handler, 0, "dma error", NULL))){
++ printk("%s: request_irq %d failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,INTC_GDMAC_ERROR_BIT_INDEX,ret,-EBUSY);
++ goto exit1;
++ }
++ kernel_thread(swap_buffer_thread, NULL, CLONE_KERNEL);
++
++ //pcm_init();
++
++ return 0;
++exit1:
++ //pcm_exit_module();
++ return -EBUSY;
++}
++
++module_init(pcm_init_module);
++module_exit(pcm_exit_module);
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_dma.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_dma.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_dma.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_dma.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,878 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/pci.h>
++#include <asm/io.h>
++#include <asm/delay.h>
++#include <mach/star_intc.h>
++#include <mach/star_dmac.h>
++
++//#define DMA_DEBUG
++//#define STR8100_DMA_TEST
++
++#define DMA_CHANNEL_MAX_ID 6 // channel 0 ~ 6
++
++#define DMA_XFER_MAX_Q_LEN 32
++#define DMA_BUSY_MAX_Q_LEN 7
++
++#define ADDR_16BIT_ALIGN_MASK 0x1
++#define ADDR_32BIT_ALIGN_MASK 0x3
++
++#define DMA_LEN_SHIFT_8BIT_WIDTH 0
++#define DMA_LEN_SHIFT_16BIT_WIDTH 1
++#define DMA_LEN_SHIFT_32BIT_WIDTH 2
++#define DMA_MAX_LEN_8BIT_WIDTH 0xfff
++#define DMA_MAX_LEN_16BIT_WIDTH (0xfff << 1)
++#define DMA_MAX_LEN_32BIT_WIDTH (0xfff << 2)
++
++#define DMA_COPY_BUSY_WAIT_CHANNEL 7
++#define DMA_COPY_BUSY_WAIT_LOOP 1000
++
++static u32 dma_burst_size = DMAC_CH_SRC_BURST_SIZE_32;
++
++#define DEFAULT_CH_PRIORITY DMAC_CH_PRIORITY_3
++#define DEFAULT_CH_BURST_SIZE DMAC_CH_SRC_BURST_SIZE_128
++#define DEFAULT_CH_SRC_WIDTH DMAC_CH_SRC_WIDTH_8BIT
++#define DEFAULT_CH_DST_WIDTH DMAC_CH_SRC_WIDTH_8BIT
++#define DEFAULT_CH_MODE DMAC_CH_MODE_NORMAL
++#define DEFAULT_CH_SRC_ADDR_CTL DMAC_CH_SRC_ADDR_CTL_INC
++#define DEFAULT_CH_DST_ADDR_CTL DMAC_CH_DST_ADDR_CTL_INC
++#define DEFAULT_CH_DST_SEL DMAC_DST_SEL_MASTER0
++#define DEFAULT_CH_SRC_SEL DMAC_SRC_SEL_MASTER0
++
++#define DEFAULT_DMA_CH_CTL \
++ ((0xf << DMAC_CH_HHST_SEL_BIT_INDEX) | \
++ (DEFAULT_CH_PRIORITY << DMAC_CH_PRIORITY_BIT_INDEX) | \
++ (DEFAULT_CH_BURST_SIZE << DMAC_CH_SRC_BURST_SIZE_BIT_INDEX) | \
++ (DEFAULT_CH_SRC_WIDTH << DMAC_CH_SRC_WIDTH_BIT_INDEX) | \
++ (DEFAULT_CH_DST_WIDTH << DMAC_CH_DST_WIDTH_BIT_INDEX) | \
++ (DEFAULT_CH_MODE << DMAC_CH_MODE_BIT_INDEX) | \
++ (DEFAULT_CH_SRC_ADDR_CTL << DMAC_CH_SRC_ADDR_CTL_BIT_INDEX) | \
++ (DEFAULT_CH_DST_ADDR_CTL << DMAC_CH_DST_ADDR_CTL_BIT_INDEX) | \
++ (DEFAULT_CH_DST_SEL << DMAC_CH_DST_SEL_BIT_INDEX) | \
++ (DEFAULT_CH_SRC_SEL << DMAC_CH_SRC_SEL_BIT_INDEX))
++
++#define DMA_CH_CTL_8BIT_WIDTH \
++ ((0xf << DMAC_CH_HHST_SEL_BIT_INDEX) | \
++ (DMAC_CH_PRIORITY_3 << DMAC_CH_PRIORITY_BIT_INDEX) | \
++ (dma_burst_size << DMAC_CH_SRC_BURST_SIZE_BIT_INDEX) | \
++ (DMAC_CH_SRC_WIDTH_8BIT << DMAC_CH_SRC_WIDTH_BIT_INDEX) | \
++ (DMAC_CH_DST_WIDTH_8BIT << DMAC_CH_DST_WIDTH_BIT_INDEX) | \
++ (DMAC_CH_MODE_NORMAL << DMAC_CH_MODE_BIT_INDEX) | \
++ (DMAC_CH_SRC_ADDR_CTL_INC << DMAC_CH_SRC_ADDR_CTL_BIT_INDEX) | \
++ (DMAC_CH_DST_ADDR_CTL_INC << DMAC_CH_DST_ADDR_CTL_BIT_INDEX) | \
++ (DMAC_DST_SEL_MASTER0 << DMAC_CH_DST_SEL_BIT_INDEX) | \
++ (DMAC_SRC_SEL_MASTER1 << DMAC_CH_SRC_SEL_BIT_INDEX))
++
++#define DMA_CH_CTL_16BIT_WIDTH \
++ ((0xf << DMAC_CH_HHST_SEL_BIT_INDEX) | \
++ (DMAC_CH_PRIORITY_3 << DMAC_CH_PRIORITY_BIT_INDEX) | \
++ (dma_burst_size << DMAC_CH_SRC_BURST_SIZE_BIT_INDEX) | \
++ (DMAC_CH_SRC_WIDTH_16BIT << DMAC_CH_SRC_WIDTH_BIT_INDEX) | \
++ (DMAC_CH_DST_WIDTH_16BIT << DMAC_CH_DST_WIDTH_BIT_INDEX) | \
++ (DMAC_CH_MODE_NORMAL << DMAC_CH_MODE_BIT_INDEX) | \
++ (DMAC_CH_SRC_ADDR_CTL_INC << DMAC_CH_SRC_ADDR_CTL_BIT_INDEX) | \
++ (DMAC_CH_DST_ADDR_CTL_INC << DMAC_CH_DST_ADDR_CTL_BIT_INDEX) | \
++ (DMAC_DST_SEL_MASTER0 << DMAC_CH_DST_SEL_BIT_INDEX) | \
++ (DMAC_SRC_SEL_MASTER1 << DMAC_CH_SRC_SEL_BIT_INDEX))
++
++
++#define DMA_CH_CTL_32BIT_WIDTH \
++ ((0xf << DMAC_CH_HHST_SEL_BIT_INDEX) | \
++ (DMAC_CH_PRIORITY_3 << DMAC_CH_PRIORITY_BIT_INDEX) | \
++ (dma_burst_size << DMAC_CH_SRC_BURST_SIZE_BIT_INDEX) | \
++ (DMAC_CH_SRC_WIDTH_32BIT << DMAC_CH_SRC_WIDTH_BIT_INDEX) | \
++ (DMAC_CH_DST_WIDTH_32BIT << DMAC_CH_DST_WIDTH_BIT_INDEX) | \
++ (DMAC_CH_MODE_NORMAL << DMAC_CH_MODE_BIT_INDEX) | \
++ (DMAC_CH_SRC_ADDR_CTL_INC << DMAC_CH_SRC_ADDR_CTL_BIT_INDEX) | \
++ (DMAC_CH_DST_ADDR_CTL_INC << DMAC_CH_DST_ADDR_CTL_BIT_INDEX) | \
++ (DMAC_DST_SEL_MASTER0 << DMAC_CH_DST_SEL_BIT_INDEX) | \
++ (DMAC_SRC_SEL_MASTER1 << DMAC_CH_SRC_SEL_BIT_INDEX))
++
++typedef struct
++{
++ struct list_head lh;
++ dma_xfer_t *xfer;
++ dma_llp_descr_t *llp_descr;
++ u32 llp_descr_dma;
++ int done_status;
++} dma_job_t;
++
++
++static u8 dma_dev;
++static spinlock_t dma_lock;
++static u8 dma_busy;
++static u8 dma_busy_q_len;
++static unsigned int dma_xfer_q_len;
++static unsigned int dma_done_q_len;
++static struct list_head dma_xfer_q;
++static struct list_head dma_done_q;
++static dma_job_t *dma_running_job[DMA_CHANNEL_MAX_ID + 1];
++
++static void *dma_mem_pool;
++static u32 dma_mem_pool_dma;
++
++static dma_job_t dma_job_pool[DMA_XFER_MAX_Q_LEN];
++static struct list_head dma_job_q;
++static spinlock_t dma_job_q_lock;
++
++static void dma_process_xfer_job(void *data);
++static void dma_process_done_job(void *data);
++
++// Eileen , for linux kernel 2.6.24 , 20080424
++//old : static DECLARE_WORK(dma_xfer_task, dma_process_xfer_job, (void *)&dma_xfer_q);
++//old : static DECLARE_WORK(dma_done_task, dma_process_done_job, (void *)&dma_done_q);
++static DECLARE_WORK(dma_xfer_task, dma_process_xfer_job);
++static DECLARE_WORK(dma_done_task, dma_process_done_job);
++
++static int dma_job_q_init(void)
++{
++ int i;
++
++ dma_mem_pool = (void *)pci_alloc_consistent(NULL,
++ (DMA_XFER_MAX_Q_LEN * MAX_DMA_VEC * sizeof(dma_llp_descr_t)),
++ &dma_mem_pool_dma);
++
++ if (dma_mem_pool == NULL) {
++ return -1;
++ }
++
++ INIT_LIST_HEAD(&dma_job_q);
++ for (i = 0; i < DMA_XFER_MAX_Q_LEN; i++) {
++ INIT_LIST_HEAD(&dma_job_pool[i].lh);
++ dma_job_pool[i].llp_descr = (dma_llp_descr_t *)(dma_mem_pool + (i * (MAX_DMA_VEC * sizeof(dma_llp_descr_t))));
++ dma_job_pool[i].llp_descr_dma = dma_mem_pool_dma + (i * (MAX_DMA_VEC * sizeof(dma_llp_descr_t)));
++ list_add_tail(&dma_job_pool[i].lh, &dma_job_q);
++ }
++
++ return 0;
++}
++
++static dma_job_t *dma_job_alloc(void)
++{
++ dma_job_t *job;
++ unsigned long flags;
++
++ spin_lock_irqsave(&dma_job_q_lock, flags);
++ if (list_empty(&dma_job_q)) {
++ job = NULL;
++ } else {
++ job = list_entry(dma_job_q.next, dma_job_t, lh);
++ list_del_init(&job->lh);
++ }
++ spin_unlock_irqrestore(&dma_job_q_lock, flags);
++
++ return job;
++}
++
++static void dma_job_free(dma_job_t *job)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&dma_job_q_lock, flags);
++ list_add(&job->lh, &dma_job_q);
++ spin_unlock_irqrestore(&dma_job_q_lock, flags);
++}
++
++#ifdef DMA_DEBUG
++void dma_dump_reg(void)
++{
++ printk("DMAC_BASE_ADDR+0x000: 0x%08x\n", DMAC_INT_STATUS_REG);
++ printk("DMAC_BASE_ADDR+0x004: 0x%08x\n", DMAC_INT_TC_STATUS_REG);
++ printk("DMAC_BASE_ADDR+0x008: 0x%08x\n", DMAC_INT_TC_STATUS_CLR_REG);
++ printk("DMAC_BASE_ADDR+0x00C: 0x%08x\n", DMAC_INT_ERR_STATUS_REG);
++ printk("DMAC_BASE_ADDR+0x010: 0x%08x\n", DMAC_INT_ERR_STATUS_CLR_REG);
++ printk("DMAC_BASE_ADDR+0x014: 0x%08x\n", DMAC_TC_STATUS_REG);
++ printk("DMAC_BASE_ADDR+0x018: 0x%08x\n", DMAC_ERR_STATUS_REG);
++ printk("DMAC_BASE_ADDR+0x01C: 0x%08x\n", DMAC_CH_ENABLE_STATUS_REG);
++ printk("DMAC_BASE_ADDR+0x020: 0x%08x\n", DMAC_CH_BUSY_STATUS_REG);
++ printk("DMAC_BASE_ADDR+0x024: 0x%08x\n", DMAC_CSR_REG);
++ printk("DMAC_BASE_ADDR+0x028: 0x%08x\n", DMAC_SYNC_REG);
++ printk("DMAC_BASE_ADDR+0x100: 0x%08x\n", DMAC_CH0_CSR_REG);
++ printk("DMAC_BASE_ADDR+0x104: 0x%08x\n", DMAC_CH0_CFG_REG);
++ printk("DMAC_BASE_ADDR+0x108: 0x%08x\n", DMAC_CH0_SRC_ADDR_REG);
++ printk("DMAC_BASE_ADDR+0x10C: 0x%08x\n", DMAC_CH0_DST_ADDR_REG);
++ printk("DMAC_BASE_ADDR+0x110: 0x%08x\n", DMAC_CH0_LLP_REG);
++ printk("DMAC_BASE_ADDR+0x114: 0x%08x\n", DMAC_CH0_SIZE_REG);
++ printk("DMAC_BASE_ADDR+0x120: 0x%08x\n", DMAC_CH1_CSR_REG);
++ printk("DMAC_BASE_ADDR+0x124: 0x%08x\n", DMAC_CH1_CFG_REG);
++ printk("DMAC_BASE_ADDR+0x128: 0x%08x\n", DMAC_CH1_SRC_ADDR_REG);
++ printk("DMAC_BASE_ADDR+0x12C: 0x%08x\n", DMAC_CH1_DST_ADDR_REG);
++ printk("DMAC_BASE_ADDR+0x130: 0x%08x\n", DMAC_CH1_LLP_REG);
++ printk("DMAC_BASE_ADDR+0x134: 0x%08x\n", DMAC_CH1_SIZE_REG);
++ printk("DMAC_BASE_ADDR+0x140: 0x%08x\n", DMAC_CH2_CSR_REG);
++ printk("DMAC_BASE_ADDR+0x144: 0x%08x\n", DMAC_CH2_CFG_REG);
++ printk("DMAC_BASE_ADDR+0x148: 0x%08x\n", DMAC_CH2_SRC_ADDR_REG);
++ printk("DMAC_BASE_ADDR+0x14C: 0x%08x\n", DMAC_CH2_DST_ADDR_REG);
++ printk("DMAC_BASE_ADDR+0x150: 0x%08x\n", DMAC_CH2_LLP_REG);
++ printk("DMAC_BASE_ADDR+0x154: 0x%08x\n", DMAC_CH2_SIZE_REG);
++ printk("DMAC_BASE_ADDR+0x160: 0x%08x\n", DMAC_CH3_CSR_REG);
++ printk("DMAC_BASE_ADDR+0x164: 0x%08x\n", DMAC_CH3_CFG_REG);
++ printk("DMAC_BASE_ADDR+0x168: 0x%08x\n", DMAC_CH3_SRC_ADDR_REG);
++ printk("DMAC_BASE_ADDR+0x16C: 0x%08x\n", DMAC_CH3_DST_ADDR_REG);
++ printk("DMAC_BASE_ADDR+0x170: 0x%08x\n", DMAC_CH3_LLP_REG);
++ printk("DMAC_BASE_ADDR+0x174: 0x%08x\n", DMAC_CH3_SIZE_REG);
++ printk("DMAC_BASE_ADDR+0x180: 0x%08x\n", DMAC_CH4_CSR_REG);
++ printk("DMAC_BASE_ADDR+0x184: 0x%08x\n", DMAC_CH4_CFG_REG);
++ printk("DMAC_BASE_ADDR+0x188: 0x%08x\n", DMAC_CH4_SRC_ADDR_REG);
++ printk("DMAC_BASE_ADDR+0x18C: 0x%08x\n", DMAC_CH4_DST_ADDR_REG);
++ printk("DMAC_BASE_ADDR+0x190: 0x%08x\n", DMAC_CH4_LLP_REG);
++ printk("DMAC_BASE_ADDR+0x194: 0x%08x\n", DMAC_CH4_SIZE_REG);
++ printk("DMAC_BASE_ADDR+0x1A0: 0x%08x\n", DMAC_CH5_CSR_REG);
++ printk("DMAC_BASE_ADDR+0x1A4: 0x%08x\n", DMAC_CH5_CFG_REG);
++ printk("DMAC_BASE_ADDR+0x1A8: 0x%08x\n", DMAC_CH5_SRC_ADDR_REG);
++ printk("DMAC_BASE_ADDR+0x1AC: 0x%08x\n", DMAC_CH5_DST_ADDR_REG);
++ printk("DMAC_BASE_ADDR+0x1B0: 0x%08x\n", DMAC_CH5_LLP_REG);
++ printk("DMAC_BASE_ADDR+0x1B4: 0x%08x\n", DMAC_CH5_SIZE_REG);
++ printk("DMAC_BASE_ADDR+0x1C0: 0x%08x\n", DMAC_CH6_CSR_REG);
++ printk("DMAC_BASE_ADDR+0x1C4: 0x%08x\n", DMAC_CH6_CFG_REG);
++ printk("DMAC_BASE_ADDR+0x1C8: 0x%08x\n", DMAC_CH6_SRC_ADDR_REG);
++ printk("DMAC_BASE_ADDR+0x1CC: 0x%08x\n", DMAC_CH6_DST_ADDR_REG);
++ printk("DMAC_BASE_ADDR+0x1D0: 0x%08x\n", DMAC_CH6_LLP_REG);
++ printk("DMAC_BASE_ADDR+0x1D4: 0x%08x\n", DMAC_CH6_SIZE_REG);
++ printk("DMAC_BASE_ADDR+0x1E0: 0x%08x\n", DMAC_CH7_CSR_REG);
++ printk("DMAC_BASE_ADDR+0x1E4: 0x%08x\n", DMAC_CH7_CFG_REG);
++ printk("DMAC_BASE_ADDR+0x1E8: 0x%08x\n", DMAC_CH7_SRC_ADDR_REG);
++ printk("DMAC_BASE_ADDR+0x1EC: 0x%08x\n", DMAC_CH7_DST_ADDR_REG);
++ printk("DMAC_BASE_ADDR+0x1F0: 0x%08x\n", DMAC_CH7_LLP_REG);
++ printk("DMAC_BASE_ADDR+0x1F4: 0x%08x\n", DMAC_CH7_SIZE_REG);
++}
++#endif
++
++static inline void dma_copy_busy_wait(void *dst, const void *src, size_t len, unsigned long dma_len_shift)
++{
++ int err = 0;
++ int i;
++
++ len = (len >> dma_len_shift);
++
++ while ((DMAC_CH_BUSY_STATUS_REG & 0xFF) & (1 << DMA_COPY_BUSY_WAIT_CHANNEL)) {
++ udelay(1);
++ }
++
++ DMAC_CH_SRC_ADDR_REG(DMA_COPY_BUSY_WAIT_CHANNEL) = (u32)virt_to_phys((void *)src);
++ DMAC_CH_DST_ADDR_REG(DMA_COPY_BUSY_WAIT_CHANNEL) = (u32)virt_to_phys((void *)dst);
++ DMAC_CH_SIZE_REG(DMA_COPY_BUSY_WAIT_CHANNEL) = (u32)len;
++
++#ifdef DMA_DEBUG
++ dma_dump_reg();
++#endif
++
++ // enable the channel
++ DMAC_CH_CSR_REG(DMA_COPY_BUSY_WAIT_CHANNEL) |= 0x1;
++
++ for (i = 0; i < DMA_COPY_BUSY_WAIT_LOOP; i++) {
++ if (DMAC_TC_STATUS_REG & (1 << DMA_COPY_BUSY_WAIT_CHANNEL)) {
++ break;
++ }
++ if (DMAC_ERR_STATUS_REG & (1 << DMA_COPY_BUSY_WAIT_CHANNEL)) {
++ err = 1;
++ break;
++ }
++ udelay(1);
++ }
++
++ // disable the channel
++ DMAC_CH_CSR_REG(DMA_COPY_BUSY_WAIT_CHANNEL) &= ~0x1;
++
++ if (err || (i == DMA_COPY_BUSY_WAIT_LOOP)) {
++ if (err) {
++ // clear the ERROR status
++ DMAC_INT_ERR_STATUS_CLR_REG |= (1 << DMA_COPY_BUSY_WAIT_CHANNEL);
++ }
++ memcpy(dst, src, (len << dma_len_shift));
++ } else {
++ // clear the TC status
++ DMAC_INT_TC_STATUS_CLR_REG |= (1 << DMA_COPY_BUSY_WAIT_CHANNEL);
++ }
++}
++
++void dma_memcpy_busy_wait(void *dst, const void *src, size_t len)
++{
++ void *pdst = dst;
++ const void *psrc = src;
++ unsigned long dma_len_shift;
++ unsigned long dma_max_len;
++ unsigned long flags;
++
++#ifdef DMA_DEBUG
++ printk("dst: 0x%08x\n", (u32)dst);
++ printk("src: 0x%08x\n", (u32)src);
++ printk("len: 0x%08x\n", (u32)len);
++ printk("pdst: 0x%08x\n", (u32)pdst);
++ printk("psrc: 0x%08x\n", (u32)psrc);
++#endif
++
++ local_irq_save(flags);
++
++ // Eileen , for linux kernel 2.6.24 , 20080424
++ // old : consistent_sync((void *)src, len, PCI_DMA_TODEVICE);
++ // old : consistent_sync((void *)dst, len, PCI_DMA_FROMDEVICE);
++ dma_cache_maint((void *)src, len, PCI_DMA_TODEVICE);
++ dma_cache_maint((void *)dst, len, PCI_DMA_FROMDEVICE);
++
++ if ((((u32)psrc & ADDR_32BIT_ALIGN_MASK) == 0) &&
++ (((u32)pdst & ADDR_32BIT_ALIGN_MASK) == 0) &&
++ ((len & 3) == 0)) {
++ dma_len_shift = DMA_LEN_SHIFT_32BIT_WIDTH;
++ dma_max_len = DMA_MAX_LEN_32BIT_WIDTH;
++ DMAC_CH_CSR_REG(DMA_COPY_BUSY_WAIT_CHANNEL) = DMA_CH_CTL_32BIT_WIDTH;
++ } else if ((((u32)psrc & ADDR_16BIT_ALIGN_MASK) == 0) &&
++ (((u32)pdst & ADDR_16BIT_ALIGN_MASK) == 0) &&
++ ((len & 1) == 0)) {
++ dma_len_shift = DMA_LEN_SHIFT_16BIT_WIDTH;
++ dma_max_len = DMA_MAX_LEN_16BIT_WIDTH;
++ DMAC_CH_CSR_REG(DMA_COPY_BUSY_WAIT_CHANNEL) = DMA_CH_CTL_16BIT_WIDTH;
++ } else {
++ dma_len_shift = DMA_LEN_SHIFT_8BIT_WIDTH;
++ dma_max_len = DMA_MAX_LEN_8BIT_WIDTH;
++ DMAC_CH_CSR_REG(DMA_COPY_BUSY_WAIT_CHANNEL) = DMA_CH_CTL_8BIT_WIDTH;
++ }
++
++ while (len) {
++ if (len > dma_max_len) {
++ dma_copy_busy_wait(pdst, psrc, dma_max_len, dma_len_shift);
++ pdst += dma_max_len;
++ psrc += dma_max_len;
++ len -= dma_max_len;
++ } else {
++ dma_copy_busy_wait(pdst, psrc, len, dma_len_shift);
++ len = 0;
++ }
++ }
++
++ local_irq_restore(flags);
++}
++EXPORT_SYMBOL(dma_memcpy_busy_wait);
++
++void dma_copy(dma_xfer_t *dma_xfer)
++{
++ dma_job_t *dma_job;
++ u32 size_shift = 0;
++ unsigned long flags;
++ int i;
++
++ if (dma_xfer_q_len > DMA_XFER_MAX_Q_LEN) {
++ dma_xfer->dma_end_io(dma_xfer, DMAC_RESPONSE_ERR);
++ return;
++ }
++
++ dma_job = dma_job_alloc();
++ if (dma_job == NULL) {
++ dma_xfer->dma_end_io(dma_xfer, DMAC_RESPONSE_ERR);
++ return;
++ }
++
++ memset(dma_job->llp_descr, 0, (dma_xfer->nr_vec * sizeof(dma_llp_descr_t)));
++ for (i = 0; i < dma_xfer->nr_vec; i++) {
++ // Eileen , for linux kernel 2.6.24 , 20080424
++ //old : consistent_sync((void *)dma_xfer->vec[i].src_addr, dma_xfer->vec[i].size, PCI_DMA_TODEVICE);
++ //old : consistent_sync((void *)dma_xfer->vec[i].dst_addr, dma_xfer->vec[i].size, PCI_DMA_FROMDEVICE);
++ dma_cache_maint((void *)dma_xfer->vec[i].src_addr, dma_xfer->vec[i].size, PCI_DMA_TODEVICE);
++ dma_cache_maint((void *)dma_xfer->vec[i].dst_addr, dma_xfer->vec[i].size, PCI_DMA_FROMDEVICE);
++ dma_job->llp_descr[i].src_addr = (u32)virt_to_phys((void *)dma_xfer->vec[i].src_addr);
++ dma_job->llp_descr[i].dst_addr = (u32)virt_to_phys((void *)dma_xfer->vec[i].dst_addr);
++ dma_job->llp_descr[i].dst_sel = dma_xfer->vec[i].dst_sel;
++ dma_job->llp_descr[i].src_sel = dma_xfer->vec[i].src_sel;
++ dma_job->llp_descr[i].dst_addr_ctl = dma_xfer->vec[i].dst_sel;
++ dma_job->llp_descr[i].src_addr_ctl = dma_xfer->vec[i].src_sel;
++ dma_job->llp_descr[i].dst_width = dma_xfer->vec[i].dst_width;
++ dma_job->llp_descr[i].src_width = dma_xfer->vec[i].src_width;
++ if (dma_xfer->vec[i].src_width == DMAC_CH_DST_WIDTH_32BIT) {
++ size_shift = 2;
++ } else if (dma_xfer->vec[i].src_width == DMAC_CH_DST_WIDTH_16BIT) {
++ size_shift = 1;
++ } else {
++ size_shift = 0;
++ }
++ dma_job->llp_descr[i].tot_size = (dma_xfer->vec[i].size >> size_shift) & 0xFFF;
++ if (i == (dma_xfer->nr_vec - 1)) {
++ dma_job->llp_descr[i].llp = 0;
++ dma_job->llp_descr[i].tc_mask = 0;
++ } else {
++ dma_job->llp_descr[i].llp = (u32)(dma_job->llp_descr_dma + ((i + 1) * sizeof(dma_llp_descr_t)));
++ dma_job->llp_descr[i].tc_mask = 1;
++ }
++#ifdef DMA_DEBUG
++ printk("in src_addr: 0x%08x\n", dma_xfer->vec[i].src_addr);
++ printk("in dst_addr: 0x%08x\n", dma_xfer->vec[i].dst_addr);
++ printk("src_addr: 0x%08x\n", dma_job->llp_descr[i].src_addr);
++ printk("dst_addr: 0x%08x\n", dma_job->llp_descr[i].dst_addr);
++ printk("llp: 0x%08x\n", dma_job->llp_descr[i].llp);
++ printk("tot_size: 0x%08x\n", dma_job->llp_descr[i].tot_size);
++ printk("dst_sel: 0x%08x\n", dma_job->llp_descr[i].dst_sel);
++ printk("src_sel: 0x%08x\n", dma_job->llp_descr[i].src_sel);
++ printk("dst_addr_ctl: 0x%08x\n", dma_job->llp_descr[i].dst_addr_ctl);
++ printk("src_addr_ctl: 0x%08x\n", dma_job->llp_descr[i].src_addr_ctl);
++ printk("dst_width: 0x%08x\n", dma_job->llp_descr[i].dst_width);
++ printk("src_width: 0x%08x\n", dma_job->llp_descr[i].src_width);
++ printk("tc_mask: 0x%08x\n", dma_job->llp_descr[i].tc_mask);
++#endif
++ }
++
++ dma_job->xfer = dma_xfer;
++ dma_job->done_status = 0;
++
++ spin_lock_irqsave(&dma_lock, flags);
++ list_add_tail(&dma_job->lh, &dma_xfer_q);
++ dma_xfer_q_len++;
++ spin_unlock_irqrestore(&dma_lock, flags);
++
++ if (!dma_busy) {
++ schedule_work(&dma_xfer_task);
++ }
++}
++EXPORT_SYMBOL(dma_copy);
++
++static void dma_process_xfer_job(void *data)
++{
++ struct list_head *l, *t;
++ dma_job_t *dma_job;
++ unsigned long csr_reg;
++ int i;
++ unsigned long flags;
++
++ if (dma_busy) {
++ return;
++ }
++
++ spin_lock_irqsave(&dma_lock, flags);
++ list_for_each_safe(l, t, &dma_xfer_q) {
++ dma_job = list_entry(l, dma_job_t, lh);
++ for (i = 0; i <= 6; i++) {
++ if (dma_running_job[i] != NULL) {
++ continue;
++ }
++ printk("Insert dma xfer to channel(%d)\n", i);
++ list_del_init(&dma_job->lh);
++ dma_running_job[i] = dma_job;
++ dma_xfer_q_len--;
++ dma_busy_q_len++;
++ csr_reg = DMAC_CH_CSR_REG(i);
++ if (dma_job->llp_descr[0].tc_mask) {
++ csr_reg |= (1 << 31);
++ } else {
++ csr_reg &= ~(1 << 31);
++ }
++ csr_reg &= ~(DMAC_CH_SRC_WIDTH_MASK << DMAC_CH_SRC_WIDTH_BIT_INDEX);
++ csr_reg &= ~(DMAC_CH_DST_WIDTH_MASK << DMAC_CH_DST_WIDTH_BIT_INDEX);
++ csr_reg &= ~(DMAC_CH_SRC_ADDR_CTL_MASK << DMAC_CH_SRC_ADDR_CTL_BIT_INDEX);
++ csr_reg &= ~(DMAC_CH_DST_ADDR_CTL_MASK << DMAC_CH_DST_ADDR_CTL_BIT_INDEX);
++ csr_reg |=
++ ((dma_job->llp_descr[0].src_width << DMAC_CH_SRC_WIDTH_BIT_INDEX) |
++ (dma_job->llp_descr[0].dst_width << DMAC_CH_DST_WIDTH_BIT_INDEX) |
++ (dma_job->llp_descr[0].src_addr_ctl << DMAC_CH_SRC_ADDR_CTL_BIT_INDEX) |
++ (dma_job->llp_descr[0].dst_addr_ctl << DMAC_CH_DST_ADDR_CTL_BIT_INDEX) |
++ (dma_job->llp_descr[0].src_sel << DMAC_CH_SRC_SEL_BIT_INDEX) |
++ (dma_job->llp_descr[0].dst_sel << DMAC_CH_DST_SEL_BIT_INDEX));
++ DMAC_CH_CSR_REG(i) = csr_reg;
++
++#if 0
++ if (dma_job->llp_descr[0].tc_mask) {
++ DMAC_CH_CFG_REG(i) |= 0x1;
++ } else {
++ DMAC_CH_CFG_REG(i) &= ~0x1;
++ }
++#endif
++
++ DMAC_CH_SRC_ADDR_REG(i) = dma_job->llp_descr[0].src_addr;
++ DMAC_CH_DST_ADDR_REG(i) = dma_job->llp_descr[0].dst_addr;
++ DMAC_CH_LLP_REG(i) = dma_job->llp_descr[0].llp;
++ DMAC_CH_SIZE_REG(i) = dma_job->llp_descr[0].tot_size;
++ HAL_DMAC_ENABLE_CHANNEL(i);
++ break;
++#ifdef DMA_DEBUG
++ //dma_dump_reg();
++#endif
++ }
++ if (dma_busy_q_len == DMA_BUSY_MAX_Q_LEN) {
++ dma_busy = 1;
++ break;
++ }
++ }
++ spin_unlock_irqrestore(&dma_lock, flags);
++}
++
++static void dma_process_done_job(void *data)
++{
++ dma_job_t *dma_job;
++ struct list_head *l, *t;
++ unsigned long flags;
++
++ spin_lock_irqsave(&dma_lock, flags);
++ list_for_each_safe(l, t, &dma_done_q) {
++ dma_job = list_entry(l, dma_job_t, lh);
++ list_del_init(&dma_job->lh);
++ dma_done_q_len--;
++ spin_unlock_irqrestore(&dma_lock, flags);
++ dma_job->xfer->dma_end_io(dma_job->xfer, dma_job->done_status);
++ dma_job_free(dma_job);
++ spin_lock_irqsave(&dma_lock, flags);
++ }
++ spin_unlock_irqrestore(&dma_lock, flags);
++}
++// Eileen , for linux kernel 2.6.24 , 20080424
++//old : irqreturn_t dma_tc_isr(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t dma_tc_isr(int irq, void *dev_id)
++{
++ dma_job_t *dma_job;
++ u32 tc_status;
++ int i;
++
++ tc_status = DMAC_INT_TC_STATUS_REG;
++
++ for (i = 0; i <= 6; i++) {
++ if (tc_status & (1 << i)) {
++ HAL_DMAC_DISABLE_CHANNEL(i);
++ dma_job = dma_running_job[i];
++ if (dma_job) {
++ dma_running_job[i] = NULL;
++ dma_job->done_status = DMAC_RESPONSE_OK;
++ list_add_tail(&dma_job->lh, &dma_done_q);
++ dma_done_q_len++;
++ dma_busy_q_len--;
++ if (dma_busy) {
++ dma_busy = 0;
++ }
++ schedule_work(&dma_done_task);
++ if (dma_xfer_q_len) {
++ schedule_work(&dma_xfer_task);
++ }
++ }
++ DMAC_INT_TC_STATUS_CLR_REG |= (1 << i);
++ break;
++ }
++ }
++
++ return IRQ_HANDLED;
++}
++
++// Eileen ,for linux kernel 2.6.24 , 20080424
++//irqreturn_t dma_err_isr(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t dma_err_isr(int irq, void *dev_id)
++{
++ dma_job_t *dma_job;
++ u32 err_status;
++ int i;
++
++ err_status = DMAC_INT_ERR_STATUS_REG;
++
++ for (i = 0; i <= 6; i++) {
++ if (err_status & (1 << i)) {
++ HAL_DMAC_DISABLE_CHANNEL(i);
++ dma_job = dma_running_job[i];
++ if (dma_job) {
++ dma_running_job[i] = NULL;
++ dma_job->done_status = DMAC_RESPONSE_ERR;
++ list_add_tail(&dma_job->lh, &dma_done_q);
++ dma_done_q_len++;
++ dma_busy_q_len--;
++ if (dma_busy) {
++ dma_busy = 0;
++ }
++ schedule_work(&dma_done_task);
++ if (dma_xfer_q_len) {
++ schedule_work(&dma_xfer_task);
++ }
++ }
++ DMAC_INT_ERR_STATUS_CLR_REG |= (1 << i);
++ break;
++ }
++ }
++
++ return IRQ_HANDLED;
++}
++
++void dma_channel_init(void)
++{
++ int i;
++
++ // disable the channel
++ DMAC_CH_CSR_REG(DMA_COPY_BUSY_WAIT_CHANNEL) &= ~0x1;
++ DMAC_CH_CFG_REG(DMA_COPY_BUSY_WAIT_CHANNEL) = 0x7;
++
++ for (i = 0; i <= 6; i++) {
++ HAL_DMAC_DISABLE_CHANNEL(i);
++ DMAC_CH_CSR_REG(i) = DEFAULT_DMA_CH_CTL;
++ DMAC_CH_CFG_REG(i) &= ~0x3;
++ }
++
++ return;
++}
++
++static int dma_init(void)
++{
++ int retval;
++
++ HAL_PWRMGT_ENABLE_DMA_CLOCK();
++
++ // Master0 & Master1 in Little Endian Mode, DMA Controller Enable
++ DMAC_CSR_REG = 0x1;
++
++ if (dma_job_q_init() != 0) {
++ return -EFAULT;
++ }
++
++ dma_channel_init();
++
++#ifdef DMA_DEBUG
++ dma_dump_reg();
++#endif
++
++ spin_lock_init(&dma_lock);
++ INIT_LIST_HEAD(&dma_xfer_q);
++ INIT_LIST_HEAD(&dma_done_q);
++
++ // Eileen , for linux kernel 2.6.24 , 20080424
++ //retval = request_irq(INTC_GDMAC_TC_BIT_INDEX, &dma_tc_isr, SA_INTERRUPT, "STAR DMA TC ISR", &dma_dev);
++ retval = request_irq(INTC_GDMAC_TC_BIT_INDEX, &dma_tc_isr, IRQF_DISABLED, "STAR DMA TC ISR", &dma_dev);
++ if (retval) {
++ printk("%s: unable to get IRQ %d (irqval=%d).\n", "STAR DMA", INTC_GDMAC_TC_BIT_INDEX, retval);
++ return retval;
++ }
++ // Eileen , for linux kernel 2.6.24 , 20080424
++ // old : retval = request_irq(INTC_GDMAC_ERROR_BIT_INDEX, &dma_err_isr, SA_INTERRUPT, "STAR DMA ERR ISR", &dma_dev);
++ retval = request_irq(INTC_GDMAC_ERROR_BIT_INDEX, &dma_err_isr, IRQF_DISABLED, "STAR DMA ERR ISR", &dma_dev);
++ if (retval) {
++ printk("%s: unable to get IRQ %d (irqval=%d).\n", "STAR DMA", INTC_GDMAC_ERROR_BIT_INDEX, retval);
++ free_irq(INTC_GDMAC_TC_BIT_INDEX, &dma_dev);
++ return retval;
++ }
++
++ return 0;
++}
++
++// Eileen , for linux kernel 2.6.24 , 20080425
++#ifdef STR8100_DMA_TEST
++ static int str8100_dmacopy_busywait_test(void);
++ static int str8100_dmacopy_llp_test(void);
++#endif
++
++
++static int __init str8100_dma_init(void)
++{
++ int retval;
++
++ printk("STR8100 DMA driver init\n");
++ retval = dma_init();
++#ifdef STR8100_DMA_TEST
++ if (retval == 0) {
++ // Eileen , for linux kernel 2.6.24 , 20080425
++ //move : static int str8100_dmacopy_busywait_test(void);
++ //move : static int str8100_dmacopy_llp_test(void);
++ (void)str8100_dmacopy_busywait_test();
++ (void)str8100_dmacopy_llp_test();
++ }
++#endif
++ return retval;
++}
++
++static void __exit str8100_dma_exit(void)
++{
++ return;
++}
++
++module_init(str8100_dma_init);
++module_exit(str8100_dma_exit);
++
++#ifdef STR8100_DMA_TEST
++#define MEMSIZE_K 64
++#define MEMSIZE (MEMSIZE_K*1024)
++
++static int str8100_dmacopy_busywait_test(void)
++{
++ u8 *src;
++ u8 *dst;
++ int i;
++ int sjiffies;
++ int err_cnt = 0;
++
++ src = kmalloc(MEMSIZE, GFP_KERNEL);
++ if (!src) goto out;
++ dst = kmalloc(MEMSIZE, GFP_KERNEL);
++ if (!dst) {
++ kfree(src);
++ goto out;
++ }
++
++ memset(src, 0xA9, MEMSIZE);
++ memset(dst, 0, MEMSIZE);
++
++ printk("STR8100 DMA Busy Wait Testing...\n");
++
++ sjiffies = jiffies;
++ for (i = 0; i < 1024; i++) {
++ dma_memcpy_busy_wait(dst, src, MEMSIZE);
++ }
++
++ printk("STR8100 DMA Busy Wait Testing end\n");
++ if (memcmp(src, dst, MEMSIZE) == 0) {
++ printk("STR8100 DMA Busy Wait Testing success\n");
++ printk("STR8100 DMA Busy Wait Testing speed: %dMB/s\n", (u32)((MEMSIZE_K) * HZ/(jiffies - sjiffies)));
++ } else {
++ printk("STR8100 DMA Busy Wait Testing failed\n");
++ for (i = 0; i < MEMSIZE; i++) {
++ if (src[i] != dst[i]) {
++ err_cnt++;
++ }
++ }
++ printk("err_cnt: %d\n", err_cnt);
++ }
++
++ kfree(src);
++ kfree(dst);
++
++out:
++ return 0;
++}
++
++#define NUM_DMA_XFER 32
++#define NUM_DMA_VEC 32
++#define NUM_BYTES_PER_VEC 1024
++
++static dma_xfer_t dma_xfer_test[NUM_DMA_XFER];
++static u32 dma_xfer_finished;
++
++static u8 *src_vec[NUM_DMA_XFER];
++static u8 *dst_vec[NUM_DMA_XFER];
++
++extern void dma_copy(dma_xfer_t *dma_xfer);
++extern void dma_dump_reg(void);
++
++static void dma_copy_end(dma_xfer_t *dma_xfer, int err)
++{
++ int i;
++ int idx;
++
++ idx = (int)dma_xfer->private;
++ dma_xfer_finished++;
++
++ if (err) {
++ printk("STR8100 DMA Testing failed!!\n");
++ } else {
++ for (i = 0; i < NUM_DMA_VEC; i++) {
++ if (memcmp((src_vec[idx] + i * NUM_BYTES_PER_VEC), (dst_vec[idx] + i * NUM_BYTES_PER_VEC), NUM_BYTES_PER_VEC) == 0) {
++ printk("STR8100 DMA Testing success on xfer idx:%d started at offset: %04d:\n", idx, i * NUM_BYTES_PER_VEC);
++ } else {
++ int j;
++ u8 *psrc;
++ u8 *pdst;
++
++ psrc = src_vec[idx] + i * NUM_BYTES_PER_VEC;
++ pdst = dst_vec[idx] + i * NUM_BYTES_PER_VEC;
++
++ printk("STR8100 DMA Testing error started at offset: %04d\n", i * NUM_BYTES_PER_VEC);
++
++ for (j = 0; j < NUM_BYTES_PER_VEC; j++) {
++ if ((j % 16) == 0) {
++ printk("\n %08x: ", (u32)(psrc + j));
++ }
++ if (((j % 16) != 0) && ((j % 4) == 0)) {
++ printk(" ");
++ }
++ printk("%02x", psrc[j]);
++ }
++ printk("\n");
++
++ for (j = 0; j < NUM_BYTES_PER_VEC; j++) {
++ if ((j % 16) == 0) {
++ printk("\n %08x: ", (u32)(pdst + j));
++ }
++ if (((j % 16) != 0) && ((j % 4) == 0)) {
++ printk(" ");
++ }
++ printk("%02x", pdst[j]);
++ }
++ printk("\n");
++ }
++ }
++ }
++
++ if (dma_xfer_finished == NUM_DMA_XFER) {
++ for (i = 0; i < NUM_DMA_XFER; i++) {
++ kfree(src_vec[i]);
++ kfree(dst_vec[i]);
++ }
++ }
++}
++
++static int str8100_dmacopy_llp_test(void)
++{
++ int i, j;
++
++ for (i = 0; i < NUM_DMA_XFER; i++) {
++ src_vec[i] = kmalloc(MEMSIZE, GFP_KERNEL);
++ if (!src_vec[i]) goto err_out;
++ dst_vec[i] = kmalloc(MEMSIZE, GFP_KERNEL);
++ if (!dst_vec[i]) goto err_out;
++ memset(src_vec[i], 0xA9, MEMSIZE);
++ memset(dst_vec[i], 0x00, MEMSIZE);
++ printk("dmacopy_llp src_vec[%d]: 0x%08x\n", i, (u32)src_vec[i]);
++ printk("dmacopy_llp dst_vec[%d]: 0x%08x\n", i, (u32)dst_vec[i]);
++ }
++
++ for (i = 0; i < NUM_DMA_XFER; i++) {
++ dma_xfer_test[i].nr_vec = NUM_DMA_VEC;
++ dma_xfer_test[i].dma_end_io = dma_copy_end;
++ dma_xfer_test[i].private = (void *)i;
++ for (j = 0; j < NUM_DMA_VEC; j++) {
++ dma_xfer_test[i].vec[j].src_addr = (u32)(src_vec[i] + (j * NUM_BYTES_PER_VEC));
++ dma_xfer_test[i].vec[j].dst_addr = (u32)(dst_vec[i] + (j * NUM_BYTES_PER_VEC));
++ dma_xfer_test[i].vec[j].size = NUM_BYTES_PER_VEC;
++ dma_xfer_test[i].vec[j].dst_sel = 0;
++ dma_xfer_test[i].vec[j].src_sel = 0;
++ dma_xfer_test[i].vec[j].dst_addr_ctl = 0;
++ dma_xfer_test[i].vec[j].src_addr_ctl = 0;
++ dma_xfer_test[i].vec[j].dst_width = DMAC_CH_DST_WIDTH_8BIT;
++ dma_xfer_test[i].vec[j].src_width = DMAC_CH_SRC_WIDTH_8BIT;
++ }
++ }
++
++ printk("STR8100 DMA Testing ...\n");
++
++ for (i = 0; i < NUM_DMA_XFER; i++) {
++ dma_copy(&dma_xfer_test[i]);
++ }
++
++ return 0;
++
++err_out:
++ for (i = 0; i < NUM_DMA_XFER; i++) {
++ if (src_vec[i])
++ kfree(src_vec[i]);
++ if (dst_vec[i])
++ kfree(dst_vec[i]);
++ }
++ return 0;
++}
++
++#endif // STR8100_DMA_TEST
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_gpio.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_gpio.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_gpio.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_gpio.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,855 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/miscdevice.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/sched.h>
++#include <linux/proc_fs.h>
++#include <linux/interrupt.h>
++
++#include <asm/irq.h>
++#include <asm/uaccess.h>
++#include <mach/hardware.h>
++#include <asm/mach-types.h>
++
++#include <mach/star_powermgt.h>
++#include <mach/star_intc.h>
++#include <mach/star_misc.h>
++#include <mach/star_gpio.h>
++
++#ifdef CONFIG_STR8100_GPIO_INTERRUPT
++
++#define MAX_GPIOA_LINE 32
++#define MAX_GPIOB_LINE 32
++#define PIN_INPUT 0
++#define PIN_OUTPUT 1
++
++#define PIN_TRIG_EDGE 0
++#define PIN_TRIG_LEVEL 1
++
++#define PIN_TRIG_SINGLE 0
++#define PIN_TRIG_BOTH 1
++
++#define PIN_TRIG_RISING 0
++#define PIN_TRIG_FALLING 1
++
++#define PIN_TRIG_HIGH 0
++#define PIN_TRIG_LOW 1
++void (*gpio_a_isr[MAX_GPIOA_LINE])(int i);
++void (*gpio_b_isr[MAX_GPIOB_LINE])(int i);
++
++#endif
++
++#if 0
++int __init_or_module gpio_direction_input(unsigned int);
++int __init_or_module gpio_direction_output(unsigned int, unsigned int);
++void gpio_set_value(unsigned int, unsigned int);
++int gpio_get_value(unsigned int);
++void str8100_gpio_a_set_edgeintr(void (*funcptr)(int), int, int, int);
++void str8100_gpio_b_set_edgeintr(void (*funcptr)(int),int,int, int);
++void str8100_gpio_a_set_levelintr(void (*funcptr)(int),int, int);
++void str8100_gpio_b_set_levelintr(void (*funcptr)(int),int, int);
++#endif
++
++/*
++ * str8100_gpio_a_in - read Data Input Register(RO) of GPIO A
++ * @data: the target to store content of register
++ */
++int str8100_gpio_a_datain(volatile __u32 *data)
++{
++ HAL_GPIOA_READ_DATA_IN_STATUS(*data);
++ return 0;
++}
++
++/*
++ * str8100_gpio_b_in - read Data Input Register(RO) of GPIO B
++ * @data: the target to store content of register
++ */
++int str8100_gpio_b_datain(volatile __u32 *data)
++{
++ HAL_GPIOB_READ_DATA_IN_STATUS(*data);
++ return 0;
++}
++
++/* str8100_gpio_a_out - write Data Output Register(RW) of GPIO A
++ * @data:
++ */
++int str8100_gpio_a_dataout(__u32 data)
++{
++ GPIOA_DATA_OUTPUT_REG = data;
++ return 0;
++}
++
++/*
++ * str8100_gpio_b_out - write Data Output Register(RW) of GPIO B
++ * @data:
++ */
++int str8100_gpio_b_out(__u32 data)
++{
++ GPIOB_DATA_OUTPUT_REG = data;
++ return 0;
++}
++
++/*
++ * str8100_gpio_a_read_direction - read Direction Register(RW) GPIO A
++ * @data:
++ */
++int str8100_gpio_a_read_direction(volatile __u32 *data)
++{
++ *data = GPIOA_DIRECTION_REG;
++ return 0;
++}
++
++/*
++ * str8100_gpio_b_read_direction - read Direction Register(RW) of GPIO B
++ * @data:
++ */
++int str8100_gpio_b_read_direction(volatile __u32 *data)
++{
++ *data = GPIOB_DIRECTION_REG;
++ return 0;
++}
++
++/*
++ * str8100_gpio_a_write_direction - write Direction Register(RW) of GPIO A
++ * @data:
++ */
++int str8100_gpio_a_write_direction(__u32 data)
++{
++ GPIOA_DIRECTION_REG = data;
++ return 0;
++}
++
++/*
++ * str8100_gpio_b_write_direction - write Direction Register(RW) of GPIO B
++ * @data:
++ */
++int str8100_gpio_b_write_direction(__u32 data)
++{
++ GPIOB_DIRECTION_REG = data;
++ return 0;
++}
++
++/*
++ * str8100_gpio_a_dataset - write Data Bit Set Register (W) of GPIO A
++ * @data:
++ *
++ * When write to this register and if some bits of GpioDataSet are 1,
++ * the corresponding bits in GpioDataOut register will be set to 1,
++ * and the others will not be changed.
++ */
++int str8100_gpio_a_dataset(__u32 data)
++{
++ GPIOA_DATA_BIT_SET_REG = data;
++ return 0;
++}
++
++/*
++ * str8100_gpio_b_dataset - write Data Bit Set Register (W) of GPIO B
++ * @data:
++ */
++int str8100_gpio_b_dataset(__u32 data)
++{
++ GPIOB_DATA_BIT_SET_REG = data;
++ return 0;
++}
++
++/*
++ * str8100_gpio_a_dataclear - write Data Bit Clear Register (W) of GPIO A
++ * @data:
++ *
++ * When write to this register and if some bits of GpioDataClear are 1,
++ * the corresponding bits in GpioDataOut register will be cleard,
++ * and the others will not be changed.
++ */
++int str8100_gpio_a_dataclear(__u32 data)
++{
++ GPIOA_DATA_BIT_CLEAR_REG = data;
++ return 0;
++}
++
++/*
++ * str8100_gpio_b_dataclear - write Data Bit Clear Register (W) of GPIO B
++ * @data:
++ */
++int str8100_gpio_b_dataclear(__u32 data)
++{
++ GPIOB_DATA_BIT_CLEAR_REG = data;
++ return 0;
++}
++/*
++Read String into Buffer, Max String buffer is 100
++*/
++ssize_t readstring(char *buff, const char *buf, size_t count){
++ int i=0;
++ if (count) {
++ char c;
++
++ for(i=0;i<count&&i<100;i++){
++ if (get_user(c, buf+i))
++ return -EFAULT;
++ buff[i] = c;
++ }
++ buff[i]=0;
++ }
++ return count;
++
++}
++
++#ifdef CONFIG_STR8100_GPIO_GENERIC_INTERFACE
++static int str8100_gpio_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
++{
++ int num = 0;
++
++ num += sprintf(page+num, "********** GPIO Group A **********\n");
++
++ num += sprintf(page+num, "GPIO IN : %08x \n", GPIOA_DATA_INPUT_REG);
++
++ num += sprintf(page+num, "GPIO Direction : %08x \n", GPIOA_DIRECTION_REG);
++
++#ifdef CONFIG_STR8100_GPIO_INTERRUPT
++ num += sprintf(page+num, "GPIO Interrupt Enable : %08x \n", GPIOA_INTERRUPT_ENABLE_REG);
++
++ num += sprintf(page+num, "GPIO Interrupt Raw : %08x \n", GPIOA_INTERRUPT_RAW_STATUS_REG);
++
++ num += sprintf(page+num, "GPIO Interrupt Trigger : %08x \n", GPIOA_INTERRUPT_TRIGGER_METHOD_REG);
++
++ num += sprintf(page+num, "GPIO Interrupt Both : %08x \n", GPIOA_INTERRUPT_TRIGGER_BOTH_EDGES_REG);
++
++ num += sprintf(page+num, "GPIO Interrupt RiseNeg : %08x \n", GPIOA_INTERRUPT_TRIGGER_TYPE_REG);
++
++ num += sprintf(page+num, "GPIO Interrupt MASKED : %08x \n", GPIOA_INTERRUPT_MASK_REG);
++
++ num += sprintf(page+num, "GPIO Interrupt MASKEDST: %08x \n", GPIOA_INTERRUPT_MASKED_STATUS_REG);
++#endif
++
++ num+= sprintf(page+num, "********** GPIO Group B **********\n");
++
++ num += sprintf(page+num, "GPIO IN : %08x \n", GPIOB_DATA_INPUT_REG);
++
++ num += sprintf(page+num, "GPIO Direction : %08x \n", GPIOB_DIRECTION_REG);
++
++#ifdef CONFIG_STR8100_GPIO_INTERRUPT
++ num += sprintf(page+num, "GPIO Interrupt Enable : %08x \n", GPIOB_INTERRUPT_ENABLE_REG);
++
++ num += sprintf(page+num, "GPIO Interrupt Raw : %08x \n", GPIOB_INTERRUPT_RAW_STATUS_REG);
++
++ num += sprintf(page+num, "GPIO Interrupt Trigger : %08x \n", GPIOB_INTERRUPT_TRIGGER_METHOD_REG);
++
++ num += sprintf(page+num, "GPIO Interrupt Both : %08x \n", GPIOB_INTERRUPT_TRIGGER_BOTH_EDGES_REG);
++
++ num += sprintf(page+num, "GPIO Interrupt RiseNeg : %08x \n", GPIOB_INTERRUPT_TRIGGER_TYPE_REG);
++
++ num += sprintf(page+num, "GPIO Interrupt MASKED : %08x \n", GPIOB_INTERRUPT_MASK_REG);
++
++ num += sprintf(page+num, "GPIO Interrupt MASKEDST: %08x \n", GPIOB_INTERRUPT_MASKED_STATUS_REG);
++#endif
++
++ return num;
++}
++#endif
++
++#ifdef CONFIG_STR8100_GPIO_INTERRUPT
++static irqreturn_t str8100_gpio_irq_handler(int this_irq, void *dev_id /*, struct pt_regs *regs */)
++{
++ unsigned int volatile status;
++ int i;
++
++ // Clean System irq status
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++
++ HAL_GPIOA_READ_INTERRUPT_MASKED_STATUS(status);
++ for (i = 0; i < MAX_GPIOA_LINE; i++) {
++ if (status & (1 << i)) { /* interrupt is detected and not masked */
++ if (gpio_a_isr[i] != NULL) {
++ gpio_a_isr[i](i);
++ }
++ }
++ }
++ HAL_GPIOA_CLEAR_INTERRUPT(status);
++
++ HAL_GPIOB_READ_INTERRUPT_MASKED_STATUS(status);
++ for (i = 0; i < MAX_GPIOB_LINE; i++) {
++ if (status & (1 << i)) { /* interrupt is detected and not masked */
++ if (gpio_b_isr[i] != NULL) {
++ gpio_b_isr[i](i);
++ }
++ }
++ }
++ HAL_GPIOB_CLEAR_INTERRUPT(status);
++
++ /* Unmask Intc Interrupt Status */
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++ return IRQ_HANDLED;
++}
++
++int intr_a_count=0;
++int intr_b_count=0;
++/*
++ * Setup GPIOA for Edge Trigger Interrupt mode
++ */
++void str8100_gpio_a_set_edgeintr(void (*funcptr)(int), int trig_both, int trig_rising, int gpio_pin)
++{
++ u32 gpio_index = (0x1 << gpio_pin);
++
++ if (gpio_pin >= 0 && gpio_pin < MAX_GPIOA_LINE) {
++ HAL_GPIOA_SET_DIRECTION_INPUT(gpio_index);
++
++ if (trig_both == PIN_TRIG_BOTH) {
++ /* Set Trigger Both */
++ HAL_GPIOA_SET_INTERRUPT_BOTH_EDGE_TRIGGER_MODE(gpio_index);
++ }
++ else if (trig_both == PIN_TRIG_SINGLE) {
++ /* Set Single Rising/Falling Edge Trigger */
++ if (trig_rising == PIN_TRIG_RISING) {
++ HAL_GPIOA_SET_INTERRUPT_SINGLE_RISING_EDGE_TRIGGER_MODE(gpio_index);
++ }
++ else if (trig_rising == PIN_TRIG_FALLING) {
++ HAL_GPIOA_SET_INTERRUPT_SINGLE_FALLING_EDGE_TRIGGER_MODE(gpio_index);
++ }
++ else {
++ printk("Trigger rising/falling error.\n");
++ return;
++ }
++ }
++ else
++ {
++ printk("Trigger both/single error.\n");
++ return;
++ }
++
++ gpio_a_isr[gpio_pin] = funcptr;
++
++ /* Enable Interrupt */
++ HAL_GPIOA_ENABLE_INTERRUPT(gpio_index);
++ }
++}
++
++/*
++ * Setup GPIOB for Edge Trigger Interrupt mode
++ */
++void str8100_gpio_b_set_edgeintr(void (*funcptr)(int),int trig_both,int trig_rising, int gpio_pin)
++{
++ u32 gpio_index = (0x1 << gpio_pin);
++
++ if (gpio_pin >= 0 && gpio_pin < MAX_GPIOA_LINE) {
++ HAL_GPIOB_SET_DIRECTION_INPUT(gpio_index);
++
++ if (trig_both == PIN_TRIG_BOTH) {
++ /* Set Trigger Both */
++ HAL_GPIOB_SET_INTERRUPT_BOTH_EDGE_TRIGGER_MODE(gpio_index);
++ }
++ else if (trig_both == PIN_TRIG_SINGLE) {
++ /* Set Single Rising/Falling Edge Trigger */
++ if (trig_rising == PIN_TRIG_RISING) {
++ HAL_GPIOB_SET_INTERRUPT_SINGLE_RISING_EDGE_TRIGGER_MODE(gpio_index);
++ }
++ else if (trig_rising == PIN_TRIG_FALLING) {
++ HAL_GPIOB_SET_INTERRUPT_SINGLE_FALLING_EDGE_TRIGGER_MODE(gpio_index);
++ }
++ else {
++ printk("Trigger rising/falling error.\n");
++ return;
++ }
++ }
++ else {
++ printk("Trigger both/single error.\n");
++ return;
++ }
++
++ gpio_b_isr[gpio_pin] = funcptr;
++
++ /* Enable Interrupt */
++ HAL_GPIOB_ENABLE_INTERRUPT(gpio_index);
++ }
++}
++
++/*
++ * Clear GPIOA Trigger Interrupt
++ */
++void str8100_gpio_a_clear_intr(int gpio_pin)
++{
++ if (gpio_pin >= 0 && gpio_pin < MAX_GPIOA_LINE) {
++ /* Unregister isr of GPIOA[gpio_pin] */
++ gpio_a_isr[gpio_pin] = NULL;
++ /* Disable Interrupt */
++ HAL_GPIOA_DISABLE_INTERRUPT(0x1 << gpio_pin);
++ }
++}
++
++/*
++ * Clear GPIOB Trigger Interrupt
++ */
++void str8100_gpio_b_clear_intr(int gpio_pin)
++{
++ if (gpio_pin >= 0 && gpio_pin < MAX_GPIOB_LINE) {
++ /* Unregister isr of GPIOB[gpio_pin] */
++ gpio_b_isr[gpio_pin] = NULL;
++ /* Disable Interrupt */
++ HAL_GPIOB_DISABLE_INTERRUPT(0x1 << gpio_pin);
++ }
++}
++
++/*
++ * Setup GPIOA for LEVEL Trigger Interrupt mode
++ */
++void str8100_gpio_a_set_levelintr(void (*funcptr)(int),int trig_level, int gpio_pin)
++{
++ u32 gpio_index = (0x1 << gpio_pin);
++
++ if (gpio_pin >= 0 && gpio_pin < MAX_GPIOA_LINE) {
++ HAL_GPIOA_SET_DIRECTION_INPUT(gpio_index);
++
++ /* Set Trigger High/Low */
++ if (trig_level == PIN_TRIG_HIGH) {
++ HAL_GPIOA_SET_INTERRUPT_HIGH_LEVEL_TRIGGER_MODE(gpio_index);
++ }
++ else if (trig_level == PIN_TRIG_LOW) {
++ HAL_GPIOA_SET_INTERRUPT_LOW_LEVEL_TRIGGER_MODE(gpio_index);
++ }
++ else {
++ printk("Trigger level error.\n");
++ return;
++ }
++
++ gpio_a_isr[gpio_pin] = funcptr;
++
++ /* Enable Interrupt */
++ HAL_GPIOA_ENABLE_INTERRUPT(gpio_index);
++ }
++}
++
++/*
++ * Setup GPIO for LEVEL Triggle Interrupt mode
++ */
++void str8100_gpio_b_set_levelintr(void (*funcptr)(int),int trig_level, int gpio_pin)
++{
++ u32 gpio_index = (0x1 << gpio_pin);
++
++ if (gpio_pin >= 0 && gpio_pin < MAX_GPIOB_LINE) {
++ HAL_GPIOB_SET_DIRECTION_INPUT(gpio_index);
++
++ /* Set Trigger High/Low */
++ if (trig_level == PIN_TRIG_HIGH) {
++ HAL_GPIOB_SET_INTERRUPT_HIGH_LEVEL_TRIGGER_MODE(gpio_index);
++ }
++ else if (trig_level == PIN_TRIG_LOW) {
++ HAL_GPIOB_SET_INTERRUPT_LOW_LEVEL_TRIGGER_MODE(gpio_index);
++ }
++ else {
++ printk("Trigger level error.\n");
++ return;
++ }
++
++ gpio_b_isr[gpio_pin] = funcptr;
++
++ /* Enable Interrupt */
++ HAL_GPIOB_ENABLE_INTERRUPT(gpio_index);
++ }
++}
++
++EXPORT_SYMBOL(str8100_gpio_a_set_edgeintr);
++EXPORT_SYMBOL(str8100_gpio_a_clear_intr);
++EXPORT_SYMBOL(str8100_gpio_a_set_levelintr);
++EXPORT_SYMBOL(str8100_gpio_b_set_edgeintr);
++EXPORT_SYMBOL(str8100_gpio_b_clear_intr);
++EXPORT_SYMBOL(str8100_gpio_b_set_levelintr);
++
++/*
++ * Display GPIO information at /proc/str9100/gpio
++ */
++
++#ifdef STR8100_GPIO_INTERRUPT_TEST
++void str8100_gpio_intr_test(int i)
++{
++ printk("GPIO Interrupt Service Single Active : %d \n",i);
++}
++#endif
++
++#endif
++
++#ifdef CONFIG_STR8100_GPIO_GENERIC_INTERFACE
++/***********************************************************************
++ * The STR8100 has GPIOA(32) and GPIOB(32) total 64 GPIO. For the
++ * generic GPIO interface, the GPIO pin number count from GPIOA to GPIOB.
++ * For example:
++ * 0 -> GPIOA[0]
++ * 1 -> GPIOA[1]
++ * ......
++ * 31 -> GPIOA[31]
++ * 32 -> GPIOB[0]
++ * 33 -> GPIOB[1]
++ * ......
++ * 63 -> GPIOB[31]
++ **********************************************************************/
++
++#define GPIOA_PIN_NO 32
++#define GPIOB_PIN_NO 32
++#define MAX_GPIO_NO (GPIOA_PIN_NO + GPIOB_PIN_NO)
++
++/*
++ * Configure the GPIO line as an input.
++ */
++int __init_or_module gpio_direction_input(unsigned int pin)
++{
++ volatile __u32 reg;
++ unsigned long flags;
++
++ if (pin >= MAX_GPIO_NO)
++ return -EINVAL;
++
++ local_irq_save(flags);
++
++ /* Clear register bit to set as input pin. */
++ if (pin < GPIOA_PIN_NO)
++ {
++ /* GPIOA */
++ reg = GPIOA_DIRECTION_REG;
++ reg &= ~(1 << pin);
++ GPIOA_DIRECTION_REG = reg;
++ }
++ else
++ {
++ /* GPIOB */
++ reg = GPIOB_DIRECTION_REG;
++ reg &= ~(1 << (pin - GPIOA_PIN_NO));
++ GPIOB_DIRECTION_REG = reg;
++ }
++
++ local_irq_restore(flags);
++
++ return 0;
++}
++//EXPORT_SYMBOL(gpio_direction_input);
++
++/*
++ * Configure the GPIO line as an output, with default state.
++ */
++int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state)
++{
++ volatile __u32 reg;
++ unsigned long flags;
++ if (pin >= MAX_GPIO_NO)
++ return -EINVAL;
++
++ local_irq_save(flags);
++
++ if (pin < GPIOA_PIN_NO)
++ {
++ /* GPIOA */
++ /* Set register bit to set as output pin. */
++ reg = GPIOA_DIRECTION_REG;
++ reg |= (1 << pin);
++ GPIOA_DIRECTION_REG = reg;
++
++ if (state)
++ GPIOA_DATA_BIT_SET_REG = (1 << pin);
++ else
++ GPIOA_DATA_BIT_CLEAR_REG = (1 << pin);
++
++ }
++ else
++ {
++ /* GPIOB */
++ /* Set register bit to set as output pin. */
++ reg = GPIOB_DIRECTION_REG;
++ reg |= (1 << (pin - GPIOA_PIN_NO));
++ GPIOB_DIRECTION_REG = reg;
++
++ if (state)
++ GPIOB_DATA_BIT_SET_REG = (1 << (pin - GPIOA_PIN_NO));
++ else
++ GPIOB_DATA_BIT_CLEAR_REG = (1 << (pin - GPIOA_PIN_NO));
++ }
++
++ local_irq_restore(flags);
++
++ return 0;
++}
++EXPORT_SYMBOL(gpio_direction_output);
++
++
++/*
++ * Set the state of an output GPIO line.
++ */
++void gpio_set_value(unsigned int pin, unsigned int state)
++{
++ if (pin >= MAX_GPIO_NO)
++ return;
++
++ if (pin < GPIOA_PIN_NO)
++ {
++ /* GPIOA */
++ if (state)
++ GPIOA_DATA_BIT_SET_REG = (1 << pin);
++ else
++ GPIOA_DATA_BIT_CLEAR_REG = (1 << pin);
++
++ }
++ else
++ {
++ /* GPIOB */
++ if (state)
++ GPIOB_DATA_BIT_SET_REG = (1 << (pin - GPIOA_PIN_NO));
++ else
++ GPIOB_DATA_BIT_CLEAR_REG = (1 << (pin - GPIOA_PIN_NO));
++ }
++}
++EXPORT_SYMBOL(gpio_set_value);
++
++
++/*
++ * Read the state of a GPIO line.
++ */
++int gpio_get_value(unsigned int pin)
++{
++ volatile __u32 reg;
++ bool bret = 0;
++
++ if (pin >= MAX_GPIO_NO)
++ return -EINVAL;
++
++ if (pin < GPIOA_PIN_NO)
++ {
++ /* GPIOA */
++ str8100_gpio_a_datain(®);
++ bret = (reg & (1 << pin)) != 0;
++ }
++ else
++ {
++ /* GPIOB */
++ str8100_gpio_b_datain(®);
++ bret = (reg & (1 << (pin - GPIOA_PIN_NO))) != 0;
++ }
++
++ return bret;
++}
++EXPORT_SYMBOL(gpio_get_value);
++
++
++/*
++ * Map GPIO line to IRQ number.
++ */
++int gpio_to_irq(unsigned int pin)
++{
++ return INTC_GPIO_EXTERNAL_INT_BIT_INDEX;
++}
++EXPORT_SYMBOL(gpio_to_irq);
++
++
++/*
++ * INVALID
++ */
++int irq_to_gpio(unsigned int irq)
++{
++ return -EINVAL;
++}
++EXPORT_SYMBOL(irq_to_gpio);
++
++#endif /* CONFIG_STR8100_GPIO_GENREIC_INTERFACE */
++
++#ifdef CONFIG_STR8100_GPIO_INTERRUPT
++static void gpio_a_isr_test(int i)
++{
++ unsigned int volatile status = 0;
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++ printk("gpio_a_isr_test, count:%d\n",intr_a_count+1);
++ status = GPIOA_INTERRUPT_MASKED_STATUS_REG;
++ HAL_GPIOA_CLEAR_INTERRUPT(status);
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++
++ intr_a_count++;
++ if (intr_a_count >= 4) {
++ str8100_gpio_a_clear_intr(i);
++ intr_a_count = 0;
++ }
++
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++}
++
++static void gpio_b_isr_test(int i)
++{
++ unsigned int volatile status = 0;
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++ printk("gpio_b_isr_test, count:%d\n",intr_b_count+1);
++ status = GPIOB_INTERRUPT_MASKED_STATUS_REG;
++ HAL_GPIOB_CLEAR_INTERRUPT(status);
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++
++ intr_b_count++;
++ if (intr_b_count >= 4) {
++ str8100_gpio_b_clear_intr(i);
++ intr_b_count = 0;
++ }
++
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++}
++#endif
++
++#ifdef CONFIG_STR8100_GPIO_GENERIC_INTERFACE
++static ssize_t str8100_gpio_write_proc(struct file *file, const char __user *buffer,
++ ssize_t count, void *data){
++ int pin = 0,state =0;
++ char read_buff[100],buf_cmd[100],buf_param1[100],buf_param2[100],buf_param3[100],buf_param4[100];
++ readstring((char *)read_buff,(const char *)buffer,count);
++ sscanf(read_buff,"%s %s %s %s %s\n",(char *)&buf_cmd,(char *)&buf_param1\
++ ,(char *)&buf_param2, (char *)&buf_param3, (char *)&buf_param4);
++ //printk("buf_cmd:%s buf_param1:%s buf_param2:%s buf_param2:%s \n", buf_cmd,buf_param1,buf_param2,buf_param3);
++ if(strcmp(buf_cmd,"direct") == 0)
++ if(strcmp(buf_param1,"input") == 0){
++ sscanf(buf_param2, "%d", &pin);
++ //printk("direction input pin=%d \n",pin);
++ gpio_direction_input(pin);
++ }
++ if(strcmp(buf_cmd,"direct") == 0)
++ if(strcmp(buf_param1,"output") == 0){
++ sscanf(buf_param2, "%d", &pin);
++ sscanf(buf_param3, "%d", &state);
++ //printk("direction output pin=%d state=%d \n",pin,state);
++ gpio_direction_output(pin,state);
++ }
++ if(strcmp(buf_cmd,"set") == 0)
++ if(strcmp(buf_param1,"value") == 0){
++ sscanf(buf_param2, "%d", &pin);
++ sscanf(buf_param3, "%d", &state);
++ printk("set value pin=%d state=%d \n",pin,state);
++ gpio_set_value(pin,state);
++ }
++ if(strcmp(buf_cmd,"get") == 0)
++ if(strcmp(buf_param1,"value") == 0){
++ sscanf(buf_param2, "%d", &pin);
++ state=gpio_get_value(pin);
++ printk("get value pin=%d state=%d \n",pin,state);
++ }
++
++#ifdef CONFIG_STR8100_GPIO_INTERRUPT
++ if(strcmp(buf_cmd,"trig") == 0){
++ if(strcmp(buf_param1,"edge") == 0){
++ if(strcmp(buf_param2,"both") == 0){
++ sscanf(buf_param3, "%d", &pin);
++ if (pin < GPIOA_PIN_NO)
++ str8100_gpio_a_set_edgeintr(&gpio_a_isr_test, 1, 0, pin);
++ else
++ str8100_gpio_b_set_edgeintr(&gpio_b_isr_test, 1, 0, pin-GPIOA_PIN_NO);
++ }
++ if(strcmp(buf_param2,"single") == 0){
++ if(strcmp(buf_param3,"rising") == 0){
++ sscanf(buf_param4, "%d", &pin);
++ if (pin < GPIOA_PIN_NO)
++ str8100_gpio_a_set_edgeintr(&gpio_a_isr_test, 0, 0, pin);
++ else
++ str8100_gpio_b_set_edgeintr(&gpio_b_isr_test, 0, 0, pin-GPIOA_PIN_NO);
++ }
++ if(strcmp(buf_param3,"falling") == 0){
++ sscanf(buf_param4, "%d", &pin);
++ if (pin < GPIOA_PIN_NO)
++ str8100_gpio_a_set_edgeintr(&gpio_a_isr_test, 0, 1, pin);
++ else
++ str8100_gpio_b_set_edgeintr(&gpio_b_isr_test, 0, 1, pin-GPIOA_PIN_NO);
++ }
++ }
++ }
++ if(strcmp(buf_param1,"level") == 0){
++ if(strcmp(buf_param2,"high") == 0){
++ sscanf(buf_param3, "%d", &pin);
++ if (pin < GPIOA_PIN_NO)
++ str8100_gpio_a_set_levelintr(&gpio_a_isr_test, 0, pin);
++ else
++ str8100_gpio_b_set_levelintr(&gpio_b_isr_test, 0, pin-GPIOA_PIN_NO);
++ }
++ if(strcmp(buf_param2,"low") == 0){
++ sscanf(buf_param3, "%d", &pin);
++ if (pin < GPIOA_PIN_NO)
++ str8100_gpio_a_set_levelintr(&gpio_a_isr_test, 1, pin);
++ else
++ str8100_gpio_b_set_levelintr(&gpio_b_isr_test, 1, pin-GPIOA_PIN_NO);
++ }
++ }
++ }
++#endif
++
++ return count;
++
++}
++
++static struct proc_dir_entry *proc_str8100_gpio;
++#endif
++extern void str8100_set_interrupt_trigger(unsigned int, unsigned int, unsigned int);
++
++int __init str8100_gpio_init(void)
++{
++#ifdef CONFIG_STR8100_GPIO_INTERRUPT
++ u32 i, ret;
++#endif
++
++ //proc_str8100_gpio = create_proc_read_entry("str8100/gpio", 0, NULL, str8100_gpio_proc, NULL) ;
++#ifdef CONFIG_STR8100_GPIO_GENERIC_INTERFACE
++ proc_str8100_gpio = create_proc_entry("str8100/gpio", S_IFREG | S_IRUGO, NULL) ;
++ proc_str8100_gpio->read_proc = str8100_gpio_proc;
++ proc_str8100_gpio->write_proc = str8100_gpio_write_proc;
++#endif
++
++#ifdef CONFIG_STR8100_GPIO_INTERRUPT
++ for (i = 0; i < MAX_GPIOA_LINE; i++) {
++ gpio_a_isr[i] = NULL;
++ }
++ for (i = 0; i < MAX_GPIOB_LINE; i++) {
++ gpio_b_isr[i] = NULL;
++ }
++
++ /* Clear All Interrupt Status */
++ HAL_GPIOA_CLEAR_INTERRUPT(0xFFFFFFFF);
++ HAL_GPIOB_CLEAR_INTERRUPT(0xFFFFFFFF);
++ str8100_set_interrupt_trigger(INTC_GPIO_EXTERNAL_INT_BIT_INDEX, INTC_EDGE_TRIGGER, INTC_RISING_EDGE);
++ ret = request_irq(INTC_GPIO_EXTERNAL_INT_BIT_INDEX, str8100_gpio_irq_handler, 0, "str8100_gpio", 0);
++ if (ret < 0) {
++ printk("request_irq fail : %d \n", ret);
++ return 0;
++ } else {
++ printk("GPIO interrupt handler install ok. \n");
++ }
++#endif
++#ifdef STR8100_GPIO_INTERRUPT_TEST
++ str8100_gpio_a_set_edgeintr(&str8100_gpio_intr_test, PIN_TRIG_SINGLE, PIN_TRIG_RISING, 0);
++ str8100_gpio_a_set_levelintr(&str8100_gpio_intr_test, PIN_TRIG_HIGH, 1);
++#endif
++
++ return 0;
++}
++
++void __exit str8100_gpio_exit(void)
++{
++ free_irq(INTC_GPIO_EXTERNAL_INT_BIT_INDEX, 0);
++}
++
++module_init(str8100_gpio_init);
++module_exit(str8100_gpio_exit);
++
++MODULE_LICENSE("GPL");
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_hsdma.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_hsdma.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_hsdma.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_hsdma.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,439 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/pci.h>
++#include <asm/io.h>
++#include <asm/delay.h>
++#include <mach/star_intc.h>
++#include <mach/star_hsdmac.h>
++
++//#define HSDMA_DEBUG
++#define STR8100_HSDMA_TEST
++
++#define HSDMA_MIN_XFER_SIZE 1024
++#define HSDMA_XFER_MAX_Q_LEN 32
++
++typedef struct
++{
++ struct list_head lh;
++ hsdma_xfer_t *xfer;
++ hsdma_llp_descr_t *llp_descr;
++ u32 llp_descr_dma;
++ int done_status;
++} hsdma_job_t;
++
++static u8 hsdma_dev;
++static spinlock_t hsdma_lock;
++static u8 hsdma_busy;
++static unsigned int hsdma_xfer_q_len;
++static unsigned int hsdma_done_q_len;
++static struct list_head hsdma_xfer_q;
++static struct list_head hsdma_done_q;
++static hsdma_job_t *hsdma_running_job;
++
++static void *hsdma_mem_pool;
++static u32 hsdma_mem_pool_dma;
++
++static hsdma_job_t hsdma_job_pool[HSDMA_XFER_MAX_Q_LEN];
++static struct list_head hsdma_job_q;
++static spinlock_t hsdma_job_q_lock;
++
++static void hsdma_process_xfer_job(void *data);
++static void hsdma_process_done_job(void *data);
++
++// Eileen , for linux kernel 2.6.24 , 20080425
++//static DECLARE_WORK(hsdma_xfer_task, hsdma_process_xfer_job, (void *)&hsdma_xfer_q);
++//static DECLARE_WORK(hsdma_done_task, hsdma_process_done_job, (void *)&hsdma_done_q);
++static DECLARE_WORK(hsdma_xfer_task, hsdma_process_xfer_job);
++static DECLARE_WORK(hsdma_done_task, hsdma_process_done_job);
++
++static int hsdma_job_q_init(void)
++{
++ int i;
++
++ hsdma_mem_pool = (void *)pci_alloc_consistent(NULL,
++ (HSDMA_XFER_MAX_Q_LEN * MAX_HSDMA_VEC * sizeof(hsdma_llp_descr_t)),
++ &hsdma_mem_pool_dma);
++
++ if (hsdma_mem_pool == NULL) {
++ return -1;
++ }
++
++ INIT_LIST_HEAD(&hsdma_job_q);
++ for (i = 0; i < HSDMA_XFER_MAX_Q_LEN; i++) {
++ INIT_LIST_HEAD(&hsdma_job_pool[i].lh);
++ hsdma_job_pool[i].llp_descr = (hsdma_llp_descr_t *)(hsdma_mem_pool + (i * (MAX_HSDMA_VEC * sizeof(hsdma_llp_descr_t))));
++ hsdma_job_pool[i].llp_descr_dma = hsdma_mem_pool_dma + (i * (MAX_HSDMA_VEC * sizeof(hsdma_llp_descr_t)));
++ list_add_tail(&hsdma_job_pool[i].lh, &hsdma_job_q);
++ }
++
++ return 0;
++}
++
++static hsdma_job_t *hsdma_job_alloc(void)
++{
++ hsdma_job_t *job;
++ unsigned long flags;
++
++ spin_lock_irqsave(&hsdma_job_q_lock, flags);
++ if (list_empty(&hsdma_job_q)) {
++ job = NULL;
++ } else {
++ job = list_entry(hsdma_job_q.next, hsdma_job_t, lh);
++ list_del_init(&job->lh);
++ }
++ spin_unlock_irqrestore(&hsdma_job_q_lock, flags);
++
++ return job;
++}
++
++static void hsdma_job_free(hsdma_job_t *job)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&hsdma_job_q_lock, flags);
++ list_add(&job->lh, &hsdma_job_q);
++ spin_unlock_irqrestore(&hsdma_job_q_lock, flags);
++}
++
++#ifdef HSDMA_DEBUG
++void hsdma_dump_reg(void)
++{
++ printk("HSDMAC_CONTROL_STATUS_REG: 0x%08x\n", HSDMAC_CONTROL_STATUS_REG);
++ printk("HSDMAC_MASTER0_ADDR_REG: 0x%08x\n", HSDMAC_MASTER0_ADDR_REG);
++ printk("HSDMAC_MASTER1_ADDR_REG: 0x%08x\n", HSDMAC_MASTER1_ADDR_REG);
++ printk("HSDMAC_LLP_REG: 0x%08x\n", HSDMAC_LLP_REG);
++ printk("HSDMAC_TOT_SIZE_REG: 0x%08x\n", HSDMAC_TOT_SIZE_REG);
++}
++#endif
++
++void hsdma_copy(hsdma_xfer_t *hsdma_xfer)
++{
++ hsdma_job_t *hsdma_job;
++ unsigned long flags;
++ int i;
++
++ if (hsdma_xfer_q_len > HSDMA_XFER_MAX_Q_LEN) {
++ hsdma_xfer->hsdma_end_io(hsdma_xfer, HSDMAC_RESPONSE_ERR);
++ return;
++ }
++
++ hsdma_job = hsdma_job_alloc();
++ if (hsdma_job == NULL) {
++ hsdma_xfer->hsdma_end_io(hsdma_xfer, HSDMAC_RESPONSE_ERR);
++ return;
++ }
++
++ memset(hsdma_job->llp_descr, 0, (hsdma_xfer->nr_vec * sizeof(hsdma_llp_descr_t)));
++ for (i = 0; i < hsdma_xfer->nr_vec; i++) {
++ if ((hsdma_xfer->vec[i].src_addr & 0x3) ||
++ (hsdma_xfer->vec[i].dst_addr & 0x3) ||
++ (hsdma_xfer->vec[i].size & 0x3)) {
++ hsdma_xfer->hsdma_end_io(hsdma_xfer, HSDMAC_RESPONSE_ERR);
++ hsdma_job_free(hsdma_job);
++ return;
++ }
++ hsdma_job->llp_descr[i].src_addr = (u32)virt_to_phys((void *)hsdma_xfer->vec[i].src_addr);
++ hsdma_job->llp_descr[i].dst_addr = (u32)virt_to_phys((void *)hsdma_xfer->vec[i].dst_addr);
++ hsdma_job->llp_descr[i].tot_size = (hsdma_xfer->vec[i].size >> 2) & 0xFFF;
++ hsdma_job->llp_descr[i].data_direction = hsdma_xfer->vec[i].data_direction;
++ if (i == (hsdma_xfer->nr_vec - 1)) {
++ hsdma_job->llp_descr[i].llp = 0;
++ hsdma_job->llp_descr[i].tc_mask = 0;
++ } else {
++ hsdma_job->llp_descr[i].llp = (u32)(hsdma_job->llp_descr_dma + ((i + 1) * sizeof(hsdma_llp_descr_t)));
++ hsdma_job->llp_descr[i].tc_mask = 1;
++ }
++ // Eileen , for linux kernel 2.6.24 , 20080425
++ //old : consistent_sync((void *)hsdma_xfer->vec[i].src_addr, hsdma_xfer->vec[i].size, PCI_DMA_TODEVICE);
++ //old : consistent_sync((void *)hsdma_xfer->vec[i].dst_addr, hsdma_xfer->vec[i].size, PCI_DMA_FROMDEVICE);
++ dma_cache_maint((void *)hsdma_xfer->vec[i].src_addr, hsdma_xfer->vec[i].size, PCI_DMA_TODEVICE);
++ dma_cache_maint((void *)hsdma_xfer->vec[i].dst_addr, hsdma_xfer->vec[i].size, PCI_DMA_FROMDEVICE);
++#ifdef HSDMA_DEBUG
++ printk("src_addr: 0x%08x\n", hsdma_job->llp_descr[i].src_addr);
++ printk("dst_addr: 0x%08x\n", hsdma_job->llp_descr[i].dst_addr);
++ printk("llp: 0x%08x\n", hsdma_job->llp_descr[i].llp);
++ printk("tot_size: 0x%08x\n", hsdma_job->llp_descr[i].tot_size);
++ printk("data_dir: 0x%08x\n", hsdma_job->llp_descr[i].data_direction);
++ printk("tc_mask: 0x%08x\n", hsdma_job->llp_descr[i].tc_mask);
++#endif
++ }
++
++ hsdma_job->xfer = hsdma_xfer;
++ hsdma_job->done_status = 0;
++
++ spin_lock_irqsave(&hsdma_lock, flags);
++ list_add_tail(&hsdma_job->lh, &hsdma_xfer_q);
++ hsdma_xfer_q_len++;
++ spin_unlock_irqrestore(&hsdma_lock, flags);
++
++ if (!hsdma_busy) {
++ schedule_work(&hsdma_xfer_task);
++ }
++}
++EXPORT_SYMBOL(hsdma_copy);
++
++static void hsdma_process_xfer_job(void *data)
++{
++ hsdma_job_t *hsdma_job;
++ unsigned long flags;
++
++ spin_lock_irqsave(&hsdma_lock, flags);
++ hsdma_job = list_entry(hsdma_xfer_q.next, hsdma_job_t, lh);
++ if (hsdma_job) {
++ list_del_init(&hsdma_job->lh);
++ hsdma_running_job = hsdma_job;
++ hsdma_xfer_q_len--;
++ hsdma_busy = 1;
++ if (hsdma_job->llp_descr[0].data_direction == HSDMAC_MASTER0_TO_MASTER1) {
++ HSDMAC_MASTER0_ADDR_REG = hsdma_job->llp_descr[0].src_addr;
++ HSDMAC_MASTER1_ADDR_REG = hsdma_job->llp_descr[0].dst_addr;
++ HSDMAC_TOT_SIZE_REG &= ~(0x1 << 29);
++ } else {
++ HSDMAC_MASTER0_ADDR_REG = hsdma_job->llp_descr[0].dst_addr;
++ HSDMAC_MASTER1_ADDR_REG = hsdma_job->llp_descr[0].src_addr;
++ HSDMAC_TOT_SIZE_REG |= (0x1 << 20);
++ }
++ HSDMAC_LLP_REG = (u32)hsdma_job->llp_descr[0].llp;
++ HSDMAC_TOT_SIZE_REG |= hsdma_job->llp_descr[0].tot_size;
++ if (hsdma_job->llp_descr[0].tc_mask) {
++ HSDMAC_TOT_SIZE_REG |= (0x1 << 28);
++ } else {
++ HSDMAC_TOT_SIZE_REG &= ~(0x1 << 28);
++ }
++ HAL_HSDMAC_ENABLE();
++ }
++ spin_unlock_irqrestore(&hsdma_lock, flags);
++}
++
++static void hsdma_process_done_job(void *data)
++{
++ hsdma_job_t *hsdma_job;
++ struct list_head *l, *t;
++ unsigned long flags;
++
++ spin_lock_irqsave(&hsdma_lock, flags);
++ list_for_each_safe(l, t, &hsdma_done_q) {
++ hsdma_job = list_entry(l, hsdma_job_t, lh);
++ list_del_init(&hsdma_job->lh);
++ hsdma_done_q_len--;
++ spin_unlock_irqrestore(&hsdma_lock, flags);
++ hsdma_job->xfer->hsdma_end_io(hsdma_job->xfer, hsdma_job->done_status);
++ hsdma_job_free(hsdma_job);
++ spin_lock_irqsave(&hsdma_lock, flags);
++ }
++ spin_unlock_irqrestore(&hsdma_lock, flags);
++}
++
++// Eileen , for linux kernel 2.6.24 , 20080425
++//old : irqreturn_t hsdma_isr(int irq, void *dev_id, struct pt_regs *regs)
++irqreturn_t hsdma_isr(int irq, void *dev_id)
++{
++ hsdma_job_t *hsdma_job;
++
++ hsdma_job = hsdma_running_job;
++ hsdma_running_job = NULL;
++ list_add_tail(&hsdma_job->lh, &hsdma_done_q);
++ hsdma_done_q_len++;
++
++ if (HSDMAC_CONTROL_STATUS_REG & (0x1 << 12)) {
++ hsdma_job->done_status = HSDMAC_RESPONSE_ERR;
++ } else {
++ hsdma_job->done_status = HSDMAC_RESPONSE_OK;
++ }
++
++ HAL_HSDMAC_DISABLE();
++
++ hsdma_busy = 0;
++
++ schedule_work(&hsdma_done_task);
++
++ if (hsdma_xfer_q_len) {
++ schedule_work(&hsdma_xfer_task);
++ }
++
++ return IRQ_HANDLED;
++}
++
++int hsdma_init(void)
++{
++ int retval;
++
++ // enable the HSDMA clock
++ HAL_PWRMGT_ENABLE_HSDMA_CLOCK();
++
++ // disable the HSDMA(normal mode, incremental address)
++ HSDMAC_CONTROL_STATUS_REG = 0x0;
++ HSDMAC_TOT_SIZE_REG = 0x10000000;
++
++ if (hsdma_job_q_init() != 0) {
++ return -EFAULT;
++ }
++
++ spin_lock_init(&hsdma_lock);
++ INIT_LIST_HEAD(&hsdma_xfer_q);
++ INIT_LIST_HEAD(&hsdma_done_q);
++
++ // Eileen , for linux kernel 2.6.24 , 20080425
++ //retval = request_irq(INTC_HSDMAC_BIT_INDEX, &hsdma_isr, SA_INTERRUPT, "STR8100 HSDMA", &hsdma_dev);
++ retval = request_irq(INTC_HSDMAC_BIT_INDEX, &hsdma_isr, IRQF_DISABLED, "STR8100 HSDMA", &hsdma_dev);
++ if (retval) {
++ printk("%s: unable to get IRQ %d (irqval=%d).\n", "STAR HSDMA", INTC_HSDMAC_BIT_INDEX, retval);
++ return retval;
++ }
++
++ return retval;
++}
++
++// Eileen , for linux kernel 2.6.24 , 20080425
++#ifdef STR8100_HSDMA_TEST
++ static int str8100_hsdma_test(void);
++#endif
++
++static int __init str8100_hsdma_init(void)
++{
++ int retval;
++
++ printk("STR8100 HSDMA driver init\n");
++ retval = hsdma_init();
++#ifdef STR8100_HSDMA_TEST
++ if (retval == 0) {
++ // Eileen ,for linux kernel 2.6.24 , 20080425
++ //move : static int str8100_hsdma_test(void);
++ (void)str8100_hsdma_test();
++ }
++#endif
++ return retval;
++}
++
++static void __exit str8100_hsdma_exit(void)
++{
++ return;
++}
++
++module_init(str8100_hsdma_init);
++module_exit(str8100_hsdma_exit);
++
++#ifdef STR8100_HSDMA_TEST
++#define MEMSIZE_K 128
++#define MEMSIZE (MEMSIZE_K*1024)
++
++#define NUM_HSDMA_VEC 16
++#define NUM_BYTES_PER_VEC 4096
++
++static hsdma_xfer_t hsdma_xfer_test;
++static u8 *src;
++static u8 *dst;
++
++static void hsdma_copy_end(hsdma_xfer_t *hsdma_xfer, int err)
++{
++ int i;
++
++ printk("STR8100 HSDMA Testing end\n");
++
++ if (err) {
++ printk("STR8100 HSDMA Testing failed!!\n");
++ } else {
++ for (i = 0; i < NUM_HSDMA_VEC; i++) {
++ if (memcmp((src + i * NUM_BYTES_PER_VEC), (dst + i * NUM_BYTES_PER_VEC), NUM_BYTES_PER_VEC) == 0) {
++ printk("STR8100 HSDMA Testing success started at offset: %04d:\n", i * NUM_BYTES_PER_VEC);
++ } else {
++ int j;
++ u8 *psrc;
++ u8 *pdst;
++
++ psrc = src + i * NUM_BYTES_PER_VEC;
++ pdst = dst + i * NUM_BYTES_PER_VEC;
++
++ printk("STR8100 HSDMA Testing error started at offset: %04d\n", i * NUM_BYTES_PER_VEC);
++
++ for (j = 0; j < NUM_BYTES_PER_VEC; j++) {
++ if ((j % 16) == 0) {
++ printk("\n 0x%08x: ", (u32)(psrc + j));
++ }
++ if (((j % 16) != 0) && ((j % 4) == 0)) {
++ printk(" ");
++ }
++ printk("%02x", psrc[j]);
++ }
++ printk("\n");
++
++ for (j = 0; j < NUM_BYTES_PER_VEC; j++) {
++ if ((j % 16) == 0) {
++ printk("\n 0x%08x: ", (u32)(pdst + j));
++ }
++ if (((j % 16) != 0) && ((j % 4) == 0)) {
++ printk(" ");
++ }
++ printk("%02x", pdst[j]);
++ }
++ printk("\n");
++ }
++ }
++ }
++
++ kfree(src);
++ kfree(dst);
++}
++
++static int str8100_hsdma_test(void)
++{
++ int i;
++
++ src = kmalloc(MEMSIZE, GFP_KERNEL);
++ if (!src) goto out;
++ dst = kmalloc(MEMSIZE, GFP_KERNEL);
++ if (!dst) {
++ kfree(src);
++ goto out;
++ }
++
++ memset(src, 0xAF, MEMSIZE);
++ memset(dst, 0x00, MEMSIZE);
++
++ hsdma_xfer_test.nr_vec = NUM_HSDMA_VEC;
++ hsdma_xfer_test.hsdma_end_io = hsdma_copy_end;
++ for (i = 0; i < NUM_HSDMA_VEC; i++) {
++ hsdma_xfer_test.vec[i].data_direction = HSDMAC_MASTER0_TO_MASTER1;
++ hsdma_xfer_test.vec[i].src_addr = (u32)(src + i * NUM_BYTES_PER_VEC);
++ hsdma_xfer_test.vec[i].dst_addr = (u32)(dst + i * NUM_BYTES_PER_VEC);
++ hsdma_xfer_test.vec[i].size = NUM_BYTES_PER_VEC;
++ }
++
++ printk("STR8100 HSDMA Testing ...\n");
++ hsdma_copy(&hsdma_xfer_test);
++
++out:
++ return 0;
++}
++
++#endif // STR8100_HSDMA_TEST
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_i2s.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_i2s.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_i2s.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_i2s.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,743 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++/*
++ * defines for each channel
++ */
++#define DMAC_CH_DISABLE 0
++#define DMAC_CH_ENABLE 1
++
++#define DMAC_CH_DST_SEL_M0 0
++#define DMAC_CH_DST_SEL_M1 1
++
++#define DMAC_CH_SRC_SEL_M0 0
++#define DMAC_CH_SRC_SEL_M1 1
++
++#define DMAC_CH_DSTAD_CTL_INC 0
++#define DMAC_CH_DSTAD_CTL_DEC 1
++#define DMAC_CH_DSTAD_CTL_FIX 2
++
++#define DMAC_CH_SRCAD_CTL_INC 0
++#define DMAC_CH_SRCAD_CTL_DEC 1
++#define DMAC_CH_SRCAD_CTL_FIX 2
++
++#define DMAC_CH_MODE_HW_HANDSHAKE 1
++
++#define DMAC_CH_SRC_WIDTH_8_BITS 0
++#define DMAC_CH_SRC_WIDTH_16_BITS 1
++#define DMAC_CH_SRC_WIDTH_32_BITS 2
++
++#define DMAC_CH_DST_WIDTH_8_BITS 0
++#define DMAC_CH_DST_WIDTH_16_BITS 1
++#define DMAC_CH_DST_WIDTH_32_BITS 2
++
++#define DMAC_CH_ABT_TRANSFER 1
++
++#define DMAC_CH_PROT1_PRIVILEGED_MODE 1
++#define DMAC_CH_PROT1_USER_MODE 0
++
++#define DMAC_CH_PROT2_BUFFERABLE 1
++#define DMAC_CH_PROT2_NON_BUFFERABLE 0
++
++#define DMAC_CH_PROT3_CACHEABLE 1
++#define DMAC_CH_PROT3_NON_CACHEABLE 0
++
++#define DMAC_CH_PRI_LEVEL_0 0
++#define DMAC_CH_PRI_LEVEL_1 1
++#define DMAC_CH_PRI_LEVEL_2 2
++#define DMAC_CH_PRI_LEVEL_3 3
++
++#define DMAC_CH_TC_MASK_DISABLE 0
++#define DMAC_CH_TC_MASK_ENABLE 1
++
++#define DMAC_MAX_CHANNEL_NUM (8)
++
++
++#define DMAC_CH0_ID (1 << 0)
++#define DMAC_CH1_ID (1 << 1)
++#define DMAC_CH2_ID (1 << 2)
++#define DMAC_CH3_ID (1 << 3)
++#define DMAC_CH4_ID (1 << 4)
++#define DMAC_CH5_ID (1 << 5)
++#define DMAC_CH6_ID (1 << 6)
++#define DMAC_CH7_ID (1 << 7)
++#define DMAC_CH_ID(idx) (1 << idx)
++
++#define DMAC_LITTLE_ENDIAN (0)
++#define DMAC_BIG_ENDIAN (1)
++
++
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++
++#include <linux/kernel.h> /* printk() */
++#include <linux/errno.h> /* error codes */
++#include <linux/types.h> /* size_t */
++#include <linux/proc_fs.h>
++#include <linux/interrupt.h>
++#include <linux/pci.h>
++
++#include <asm/system.h> /* cli(), *_flags */
++#include <asm/uaccess.h> /* copy_*_user */
++
++#include <mach/star_powermgt.h>
++#include <mach/star_misc.h>
++#include <mach/star_i2s.h>
++#include <mach/star_dmac.h>
++
++MODULE_AUTHOR("Mac Lin");
++MODULE_LICENSE("Dual BSD/GPL");
++
++
++#define CONFIG_I2S_USE_DMA
++//Debug = left only
++#define DEBUG
++
++static struct proc_dir_entry *star_i2s_proc_entry=NULL;
++static u32 sampling_rate=32000;
++static u32 sample_size=16;
++
++#define DMA_TRANSFER_MAX_BYTE (0xfff<<(sample_size>>4))
++#define BUFSIZE (0xfff<<4) //twice the 32-bit DMA transfer byte size
++
++static u8* lbuffer;
++static u8* lbuffer_p;
++static u32 llen=0;
++static u32 lpos=0;
++static u32 i2s_err_lur=0;
++
++static u32 debug=0;
++#define DEBUG_PRINT(arg...) if(debug) printk(arg);
++
++//=================================================================================
++//
++#ifdef CONFIG_I2S_USE_DMA
++typedef struct _DMAC_HARDWARE_HANDSHAKE_OBJ_ DMAC_HARDWARE_HANDSHAKE_OBJ_T;
++
++struct _DMAC_HARDWARE_HANDSHAKE_OBJ_
++{
++ unsigned int src_addr; //Src address
++ unsigned int dst_addr; //Dst address
++ unsigned int src_master; //0:AHB0, 1:AHB1
++ unsigned int dst_master; //0:AHB0, 1:AHB1
++ unsigned int dstad_ctl; //0:Incr, 1:Decr, 2:Fix
++ unsigned int srcad_ctl; //0:Incr, 1:Decr, 2:Fix
++ unsigned int src_width; //0:8bits, 1:16bits, 2:32bits
++ unsigned int dst_width; //0:8bits, 1:16bits, 2:32bits
++ unsigned int transfer_bytes; //Byte Count to be transferred
++ unsigned int channel_id; //0~7 for Channel0-7 selection
++ unsigned int channel_num; //0~7
++ unsigned int target_select; //target ID
++ unsigned int src_burst_size; //number of transfer
++};
++
++static DMAC_HARDWARE_HANDSHAKE_OBJ_T i2s_wm8759_dma_handshake_left_tx;
++static DMAC_HARDWARE_HANDSHAKE_OBJ_T i2s_wm8759_dma_handshake_right_tx;
++
++static u32 i2s_wm8759_dma_right_tx_channel = 1;
++
++
++
++
++void Hal_Dmac_Configure_DMA_Handshake(DMAC_HARDWARE_HANDSHAKE_OBJ_T *dmac_obj)
++{
++ u32 channel_control,interrupt_mask_config,ch;
++
++
++ /*
++ * Configure DMA controller for UART's hardware DMA handshake mode
++ */
++ HAL_DMAC_DISABLE();
++
++//#if (ENDIAN_MODE == BIG_ENDIAN)
++#if 0
++ /*Set Master0 and Master 1 endianness as Big Endian*/
++ HAL_DMAC_SET_MASTER0_BIG_ENDIAN();
++ HAL_DMAC_SET_MASTER1_BIG_ENDIAN();
++#else
++ /*Set Master0 and Master 1 endianness as Little Endian*/
++ HAL_DMAC_SET_MASTER0_LITTLE_ENDIAN();
++ HAL_DMAC_SET_MASTER1_LITTLE_ENDIAN();
++#endif
++
++ //Clear TC interrupt status
++ HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(0xFF); // 8 channels
++
++ //Clear Errot/Abort interrupt status
++ HAL_DMAC_CLEAR_ERROR_ABORT_INTERRUPT_STATUS(0x00FF00FF); // 8 channels
++
++ /*
++ * Configure DMA's channel control
++ */
++ channel_control = ((DMAC_CH_TC_MASK_DISABLE << 31) | \
++ ((dmac_obj->target_select&0xf) << 25) | \
++ (DMAC_CH_PRI_LEVEL_3 << 22) | \
++ (DMAC_CH_PROT3_NON_CACHEABLE << 21) | \
++ (DMAC_CH_PROT2_NON_BUFFERABLE << 20) | \
++ (DMAC_CH_PROT1_PRIVILEGED_MODE << 19) | \
++ ((dmac_obj->src_burst_size&0x7) << 16) | \
++ ((dmac_obj->src_width&0x7) << 11) | \
++ ((dmac_obj->dst_width&0x7) << 8) | \
++ (DMAC_CH_MODE_HW_HANDSHAKE << 7) | \
++ ((dmac_obj->srcad_ctl&0x3) << 5) | \
++ ((dmac_obj->dstad_ctl&0x3) << 3) | \
++ (dmac_obj->src_master << 2) | \
++ (dmac_obj->dst_master << 1) | \
++ (DMAC_CH_DISABLE));
++
++ for (ch = 0; ch < DMAC_MAX_CHANNEL_NUM; ch++)
++ {
++ if (dmac_obj->channel_id & DMAC_CH_ID(ch))
++ {
++ // 1. Set CSR
++ DMAC_CH_CSR_REG(ch) = channel_control & 0xFFFFFFFE; //Disable CH(n) DMA
++
++ // 2.1 Reset Abort/Error/Terminal Count INT
++ DMAC_CH_CFG_REG(ch) &= ~(0x07);
++
++ // 2.2 Disable Abort Count INT
++ interrupt_mask_config = (1 << 2);
++
++ DMAC_CH_CFG_REG(ch) |= (interrupt_mask_config & 0x07);
++ }
++ }
++
++ for (ch = 0; ch < DMAC_MAX_CHANNEL_NUM; ch++)
++ {
++ if (dmac_obj->channel_id & DMAC_CH_ID(ch))
++ {
++ //Set Src address register
++ DMAC_CH_SRC_ADDR_REG(ch)= dmac_obj->src_addr;
++
++ //Set Dst address register
++ DMAC_CH_DST_ADDR_REG(ch)= dmac_obj->dst_addr;
++
++ //Set Transfer Number
++ if (dmac_obj->src_width == DMAC_CH_SRC_WIDTH_8_BITS)
++ {
++ DMAC_CH_SIZE_REG(ch) = (dmac_obj->transfer_bytes & 0x0FFF);
++ DEBUG_PRINT("%s: 8-bits transfer_bytes=%d, DMAC_CH_SIZE_REG(%d)=%.8x\n",__FUNCTION__,dmac_obj->transfer_bytes,ch,DMAC_CH_SIZE_REG(ch));
++ }
++ else if (dmac_obj->src_width == DMAC_CH_SRC_WIDTH_16_BITS)
++ {
++ DMAC_CH_SIZE_REG(ch) = ((dmac_obj->transfer_bytes >> 1) + (dmac_obj->transfer_bytes % 2)) & 0x0FFF;
++ DEBUG_PRINT("%s: 16-bits transfer_bytes=%d, DMAC_CH_SIZE_REG(%d)=%.8x\n",__FUNCTION__,dmac_obj->transfer_bytes,ch,DMAC_CH_SIZE_REG(ch));
++ }
++ else if (dmac_obj->src_width == DMAC_CH_SRC_WIDTH_32_BITS)
++ {
++ DMAC_CH_SIZE_REG(ch) = ((dmac_obj->transfer_bytes >> 2) + ((dmac_obj->transfer_bytes % 4) ? 1 : 0)) & 0x0FFF;
++ DEBUG_PRINT("%s: 32-bits transfer_bytes=%d, DMAC_CH_SIZE_REG(%d)=%.8x\n",__FUNCTION__,dmac_obj->transfer_bytes,ch,DMAC_CH_SIZE_REG(ch));
++ }
++ else
++ {
++ DEBUG_PRINT("%s: dead\n",__FUNCTION__);
++ while (1);
++ }
++
++ //Enable Channel DMA transfer
++ HAL_DMAC_ENABLE_CHANNEL(ch);
++
++ //Set Channel's Sync logic
++ DMAC_SYNC_REG |= (1 << ch);
++
++ //For NON Chain Transfer, clear LLP registers
++ DMAC_CH_LLP_REG(ch) = 0;
++ }
++ }
++}
++
++void I2s_WM8759_Configure_DMA_Hardware_Handshake(void)
++{
++ /*
++ * Configure DMA's channel setting for I2S's Left Channel Tx
++ * Specially pay attention to the settings of src_width, dst_width, and src_burst_size
++ */
++ i2s_wm8759_dma_handshake_left_tx.channel_num = 0;
++ i2s_wm8759_dma_handshake_left_tx.channel_id = DMAC_CH_ID(i2s_wm8759_dma_handshake_left_tx.channel_num);
++ i2s_wm8759_dma_handshake_left_tx.target_select = DMAC_HW_HAND_SHAKE_I2S_TX_LEFT_ID;
++ i2s_wm8759_dma_handshake_left_tx.src_addr = (u32)lbuffer_p;
++ i2s_wm8759_dma_handshake_left_tx.src_master = DMAC_CH_SRC_SEL_M1;
++ i2s_wm8759_dma_handshake_left_tx.dst_master = DMAC_CH_DST_SEL_M0;
++ i2s_wm8759_dma_handshake_left_tx.srcad_ctl = DMAC_CH_SRCAD_CTL_INC;
++ i2s_wm8759_dma_handshake_left_tx.dstad_ctl = DMAC_CH_DSTAD_CTL_FIX;
++
++ switch(sample_size){
++ case 16:
++ i2s_wm8759_dma_handshake_left_tx.dst_addr = (SYSPA_I2S_BASE_ADDR + 0xCA);
++ i2s_wm8759_dma_handshake_left_tx.src_width = DMAC_CH_SRC_WIDTH_16_BITS;
++ i2s_wm8759_dma_handshake_left_tx.dst_width = DMAC_CH_DST_WIDTH_16_BITS;
++ break;
++ case 32:
++ i2s_wm8759_dma_handshake_left_tx.dst_addr = (SYSPA_I2S_BASE_ADDR + 0xC8);
++ i2s_wm8759_dma_handshake_left_tx.src_width = DMAC_CH_SRC_WIDTH_32_BITS;
++ i2s_wm8759_dma_handshake_left_tx.dst_width = DMAC_CH_DST_WIDTH_32_BITS;
++ break;
++ }
++
++// i2s_wm8759_dma_handshake_left_tx.dst_width = DMAC_CH_DST_WIDTH_16_BITS;
++
++ /*
++ * Note here the total number of bytes for each DMA transfer is specified!!
++ */
++// i2s_wm8759_dma_handshake_left_tx.transfer_bytes = DMA_TRANSFER_MAX_BYTE;
++ i2s_wm8759_dma_handshake_left_tx.transfer_bytes = (llen<DMA_TRANSFER_MAX_BYTE)?llen:DMA_TRANSFER_MAX_BYTE;
++
++ i2s_wm8759_dma_handshake_left_tx.src_burst_size = DMAC_CH_SRC_BURST_SIZE_1;
++
++ Hal_Dmac_Configure_DMA_Handshake(&i2s_wm8759_dma_handshake_left_tx);
++
++#ifndef DEBUG
++ /*
++ * Configure DMA's channel setting for I2S's Right Channel Tx
++ * Specially pay attention to the settings of src_width, dst_width, and src_burst_size
++ */
++ i2s_wm8759_dma_handshake_right_tx.channel_id = DMAC_CH_ID(i2s_wm8759_dma_right_tx_channel);
++
++ i2s_wm8759_dma_handshake_right_tx.target_select = DMAC_HW_HAND_SHAKE_I2S_TX_RIGHT_ID;
++
++ i2s_wm8759_dma_handshake_right_tx.src_addr = (u32)rbuffer_p;
++
++ i2s_wm8759_dma_handshake_right_tx.dst_addr = (SYSPA_I2S_BASE_ADDR + 0xC4);
++
++ i2s_wm8759_dma_handshake_right_tx.src_master = DMAC_CH_SRC_SEL_M1;
++
++ i2s_wm8759_dma_handshake_right_tx.dst_master = DMAC_CH_DST_SEL_M0;
++
++ i2s_wm8759_dma_handshake_right_tx.srcad_ctl = DMAC_CH_SRCAD_CTL_INC;
++
++ i2s_wm8759_dma_handshake_right_tx.dstad_ctl = DMAC_CH_DSTAD_CTL_FIX;
++
++ i2s_wm8759_dma_handshake_right_tx.src_width = DMAC_CH_SRC_WIDTH_32_BITS;
++
++ i2s_wm8759_dma_handshake_right_tx.dst_width = DMAC_CH_DST_WIDTH_32_BITS;
++
++ /*
++ * Note here the total number of bytes for each DMA transfer is specified!!
++ */
++ i2s_wm8759_dma_handshake_right_tx.transfer_bytes = DMA_TRANSFER_MAX_BYTE;
++
++ i2s_wm8759_dma_handshake_right_tx.src_burst_size = DMAC_CH_SRC_BURST_SIZE_1;
++
++ Hal_Dmac_Configure_DMA_Handshake(&i2s_wm8759_dma_handshake_right_tx);
++#endif
++ return;
++}
++#endif //CONFIG_I2S_USE_DMA
++
++
++//=================================================================================
++//
++
++extern void str8100_set_interrupt_trigger(unsigned int, unsigned int, unsigned int);
++
++#ifdef CONFIG_I2S_USE_DMA
++static irqreturn_t str8100_dma_tc_irq_handler(int this_irq, void *dev_id /*, struct pt_regs *regs*/)
++{
++ u32 dma_tc_status,tot_size;
++ u32 len;
++//printk("%s: this_irq=%d\n",__FUNCTION__,this_irq);
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(this_irq);
++ //todo:
++
++ HAL_DMAC_READ_TERMINAL_COUNT_INTERRUPT_STATUS(dma_tc_status);
++
++ /*
++ * For DMA's Tx for I2S Left Channel
++ */
++ if (dma_tc_status & DMAC_CH_ID(i2s_wm8759_dma_handshake_left_tx.channel_num))
++ {
++ HAL_DMAC_DISABLE_CHANNEL(i2s_wm8759_dma_handshake_left_tx.channel_num);
++ HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(DMAC_CH_ID(i2s_wm8759_dma_handshake_left_tx.channel_num));
++ lpos+=i2s_wm8759_dma_handshake_left_tx.transfer_bytes;
++ if(lpos<llen){
++ /*
++ * Re-initialize DMA's channel for Left_Tx
++ */
++ DMAC_CH_SRC_ADDR_REG(i2s_wm8759_dma_handshake_left_tx.channel_num) = (u32)lbuffer_p+lpos;
++ DMAC_CH_DST_ADDR_REG(i2s_wm8759_dma_handshake_left_tx.channel_num) = (SYSPA_I2S_BASE_ADDR + 0xC8);
++
++ /*
++ * Note this macro DMAC_CH_SIZE is to configure TOT_SIZE field which is the total transfer
++ * number of source transfer width!
++ */
++ len=(llen - lpos);
++ i2s_wm8759_dma_handshake_left_tx.transfer_bytes= (len<DMA_TRANSFER_MAX_BYTE)?len:DMA_TRANSFER_MAX_BYTE;
++
++ if (i2s_wm8759_dma_handshake_left_tx.src_width == DMAC_CH_SRC_WIDTH_16_BITS)
++ {
++ tot_size = (i2s_wm8759_dma_handshake_left_tx.transfer_bytes >> 1) + ((i2s_wm8759_dma_handshake_left_tx.transfer_bytes % 2) ? 1 : 0);
++ }
++ else if (i2s_wm8759_dma_handshake_left_tx.src_width == DMAC_CH_SRC_WIDTH_32_BITS)
++ {
++ tot_size = (i2s_wm8759_dma_handshake_left_tx.transfer_bytes >> 2) + ((i2s_wm8759_dma_handshake_left_tx.transfer_bytes % 4) ? 1 : 0);
++ }
++ else
++ {
++ tot_size = i2s_wm8759_dma_handshake_left_tx.transfer_bytes;
++ }
++
++ DMAC_CH_SIZE_REG(i2s_wm8759_dma_handshake_left_tx.channel_num) = tot_size & 0x0FFF;
++ HAL_DMAC_ENABLE_CHANNEL(i2s_wm8759_dma_handshake_left_tx.channel_num);
++//printk("%s: 32-bits transfer_bytes=%d, DMAC_CH_SIZE_REG(%d)=%.8x\n",__FUNCTION__,i2s_wm8759_dma_handshake_left_tx.transfer_bytes,i2s_wm8759_dma_handshake_left_tx.channel_num,DMAC_CH_SIZE_REG(i2s_wm8759_dma_handshake_left_tx.channel_num));
++
++ }else{
++ llen=lpos=0;
++ }
++ }
++
++
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq);
++
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t str8100_dma_err_irq_handler(int this_irq, void *dev_id /*, struct pt_regs *regs*/)
++{
++ u32 dma_error_status,dma_ch;
++printk("%s: this_irq=%d\n",__FUNCTION__,this_irq);
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(this_irq);
++ //todo:
++
++ HAL_DMAC_READ_ERROR_ABORT_INTERRUPT_STATUS(dma_error_status);
++ for (dma_ch = 0; dma_ch < DMAC_MAX_CHANNEL_NUM; dma_ch++)
++ {
++ if (dma_error_status & DMAC_CH_ID(dma_ch))
++ {
++ printk("%s: this_irq=%d, DMA channel error on ch %d\n",__FUNCTION__,this_irq,dma_ch);
++ HAL_DMAC_DISABLE_CHANNEL(dma_ch);
++ HAL_DMAC_CLEAR_ERROR_ABORT_INTERRUPT_STATUS(DMAC_CH_ID(dma_ch));
++ }
++ }
++
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq);
++
++ return IRQ_HANDLED;
++}
++#endif //CONFIG_I2S_USE_DMA
++
++static irqreturn_t str8100_i2s_irq_handler(int this_irq, void *dev_id /*, struct pt_regs *regs*/)
++{
++ u32 interrupt_status;
++ DEBUG_PRINT("%s: this_irq=%d, I2S_INTERRUPT_STATUS_REG=0x%.8x,llen=%d,lpos=%d\n",__FUNCTION__,this_irq,I2S_INTERRUPT_STATUS_REG,llen,lpos);
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(this_irq);
++ //todo:
++ interrupt_status = I2S_INTERRUPT_STATUS_REG;
++if((llen<lpos)||llen==0) HAL_I2S_DISABLE_I2S();
++
++#ifndef CONFIG_I2S_USE_DMA
++ I2S_RIGHT_TRANSMIT_DATA_REG=0;
++
++ if ((lpos<=llen) && (interrupt_status & I2S_TXBF_L_EMPTY_FLAG)){
++ switch(sample_size){
++ case 16:
++ I2S_LEFT_TRANSMIT_DATA_REG=(*((u16*)(&lbuffer[lpos])))<<16;lpos+=2;
++ break;
++ case 32:
++ I2S_LEFT_TRANSMIT_DATA_REG=*((u32*)(&lbuffer[lpos]));lpos+=4;
++ break;
++ }
++
++ if(lpos>llen){
++ // Disable Left Channel's Transmit Buffer Interrupt Sources
++ I2S_INTERRUPT_ENABLE_REG &= ~(I2S_TXBF_L_EMPTY_FLAG | I2S_TXBF_L_UR_FLAG);
++ lpos=llen=0;
++ }
++ }
++#endif //!CONFIG_I2S_USE_DMA
++
++
++ if (llen>=lpos && (interrupt_status & I2S_TXBF_L_UR_FLAG)){
++ // Clear I2S interrupt status
++ i2s_err_lur++;
++ if(i2s_err_lur>10)
++ I2S_INTERRUPT_ENABLE_REG &= ~(I2S_TXBF_L_UR_FLAG);
++// HAL_I2S_DISABLE_I2S();
++
++ printk("%s: Left Channel Tx Underrun!,llen=%d, lpos=%d, interrupt_status=%.8x,i2s_err_lur=%d\n",__FUNCTION__,llen,lpos,interrupt_status,i2s_err_lur);
++ }
++ I2S_INTERRUPT_STATUS_REG &= 0xf0;
++
++
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq);
++
++ return IRQ_HANDLED;
++}
++
++static int str8100_i2s_init(void){
++ DEBUG_PRINT("%s: \n",__FUNCTION__);
++ int ret;
++ u32 tmp;
++
++
++ /*
++ * Select I2S clock source; here we use 48K sampling rate for the target file.
++ */
++
++ switch(sampling_rate){
++ case 48000:
++ HAL_PWRMGT_I2S_CLOCK_SOURCE_12288000HZ();
++ break;
++ case 44100:
++ HAL_PWRMGT_I2S_CLOCK_SOURCE_11289600HZ();
++ break;
++ case 32000:
++ HAL_PWRMGT_I2S_CLOCK_SOURCE_8192000HZ();
++ break;
++ }
++ HAL_PWRMGT_CONFIGURE_CLOCK_OUT_PIN(11,0);
++
++ // Enable I2S pins
++ HAL_MISC_ENABLE_I2S_PINS();
++
++ // Enable I2S clock
++ HAL_PWRMGT_ENABLE_I2S_CLOCK();
++
++ //Hal_Pwrmgt_Software_Reset(PWRMGT_P2S_SOFTWARE_RESET_BIT_INDEX);
++
++ /*
++ * Configure I2S to be Master & Transmitter
++ * Note the I2S's WS Clock is derived from Clock & Power Management Functional
++ * Block!!
++ */
++ I2S_CONFIGURATION_REG = /*(I2S_DATA_16_BIT << 0) |*/
++ (I2S_DATA_32_BIT << 0) |
++ (0x0 << 4) |
++ (0x0 << 12) | /* Disable loopback */
++ (0x0 << 15) | /* Disable clock phase invert */
++ (0x0 << 24) | /* Disable I2S data swap */
++ (I2S_CLOCK_256S_MODE << 25) |
++ (I2S_I2S_MODE << 26) |
++ (0x0 << 29) | /* Enable I2S Transmitter */
++ (I2S_MASTER_MODE << 30) |
++ (0x0 << 31); /* Disable I2S */
++
++ //Enable none while initializing
++ I2S_INTERRUPT_ENABLE_REG = 0x0;
++// I2S_INTERRUPT_ENABLE_REG |= (I2S_TXBF_R_UR_FLAG | I2S_TXBF_L_UR_FLAG | I2S_TXBF_R_EMPTY_FLAG | I2S_TXBF_L_EMPTY_FLAG);
++
++ // Clear spurious interrupt sources
++ I2S_INTERRUPT_STATUS_REG = 0xF0;
++
++ tmp = I2S_LEFT_RECEIVE_DATA_REG;
++ tmp = I2S_RIGHT_RECEIVE_DATA_REG;
++
++ // Disable I2S
++ HAL_I2S_DISABLE_I2S();
++
++ return 0;
++}
++
++
++//=================================================================================
++static int proc_read_i2s(char *buf, char **start, off_t offset,
++ int count, int *eof, void *data)
++{
++ int len=0;
++ DEBUG_PRINT("%s:\n",__FUNCTION__);
++ len += sprintf(buf, "sampling_rate=%d\n"
++ "sample_size=%d\n"
++ ,sampling_rate,sample_size);
++ *eof = 1;
++ return len;
++}
++
++static proc_write_i2s(struct file *file, const char *buffer, unsigned long count, void *data){
++ int len=0;
++ DEBUG_PRINT("%s: sample size %d, sampling rate %d, count=%d\n",__FUNCTION__,sample_size,sampling_rate,count);
++
++ //is buffer free?
++ if(lpos!=llen){
++ printk("%s: buffer not free\n");
++ return -EBUSY;
++ }
++ if(sampling_rate!=32000&&sampling_rate!=44100&&sampling_rate!=48000){
++ printk("%s: invalid sampling rate(%d)\n",sampling_rate);
++ return -EFAULT;
++ }
++ if(sample_size!=16&&sample_size!=32){
++ printk("%s: invalid sample size(%d)\n",sample_size);
++ return -EFAULT;
++ }
++
++ //copy the raw data to local buffer
++ if(count>BUFSIZE) len=BUFSIZE;
++ else len=count;
++
++ if(copy_from_user(lbuffer,buffer,len)){
++ return -EFAULT;
++ }
++ llen=len;
++ lpos=0;
++ i2s_err_lur=0;
++
++ str8100_i2s_init();
++
++#ifdef CONFIG_I2S_USE_DMA
++ /*
++ * Configure DMA for hardware handshake for I2S
++ * Note the DMA is NOT enabled after invoking the following function, but the specified
++ * DMA channels are enabled!!
++ */
++ i2s_wm8759_dma_right_tx_channel = 1;
++
++ I2s_WM8759_Configure_DMA_Hardware_Handshake();
++
++#endif //CONFIG_I2S_USE_DMA
++ //fill the tx left/right registers
++
++ switch(sample_size){
++ case 16:
++ I2S_LEFT_TRANSMIT_DATA_REG=(*((u16*)(&lbuffer[lpos])))<<16;lpos+=2;
++ break;
++ case 32:
++ I2S_LEFT_TRANSMIT_DATA_REG=*((u32*)(&lbuffer[lpos]));lpos+=4;
++ break;
++ }
++
++ I2S_RIGHT_TRANSMIT_DATA_REG=0;
++
++#ifdef CONFIG_I2S_USE_DMA
++ /*
++ * Enable I2S's interrupt sources
++ * Note for DMA hardware handshake, we only need to enable Left/Right Channel's
++ * Transmit Buffer Underrun.
++ */
++#ifdef DEBUG
++ I2S_INTERRUPT_ENABLE_REG |= (I2S_TXBF_L_UR_FLAG);
++#else
++ I2S_INTERRUPT_ENABLE_REG |= (I2S_TXBF_R_UR_FLAG | I2S_TXBF_L_UR_FLAG);
++#endif
++#else //CONFIG_I2S_USE_DMA
++#ifdef DEBUG
++ I2S_INTERRUPT_ENABLE_REG |= (I2S_TXBF_L_UR_FLAG | I2S_TXBF_L_EMPTY_FLAG);
++#else
++ I2S_INTERRUPT_ENABLE_REG |= (I2S_TXBF_R_UR_FLAG | I2S_TXBF_L_UR_FLAG | I2S_TXBF_R_EMPTY_FLAG | I2S_TXBF_L_EMPTY_FLAG);
++#endif
++#endif //CONFIG_I2S_USE_DMA
++
++ // Enable CPU interrupt
++ local_irq_enable();
++
++#ifdef CONFIG_I2S_USE_DMA
++ /*
++ * Note DMA must be enabled first before I2S is enabled
++ */
++ HAL_DMAC_ENABLE();
++#endif //CONFIG_I2S_USE_DMA
++ HAL_I2S_ENABLE_I2S();
++
++
++ while (1){
++ local_irq_disable();
++ if (lpos>llen||llen==0){
++ // Disable I2S
++ HAL_I2S_DISABLE_I2S();
++ break;
++ }
++ local_irq_enable();
++ }
++ DEBUG_PRINT("%s: exit. i2s_err_lur=%d\n",__FUNCTION__,i2s_err_lur);
++
++ local_irq_enable();
++
++ return len;
++
++debug:
++ HAL_I2S_DISABLE_I2S();
++ return count;
++}
++
++static void __devexit i2s_exit_module(void)
++{
++ printk("%s:\n",__FUNCTION__);
++ remove_proc_entry("str8100/i2s", NULL);
++ free_irq(INTC_I2S_BIT_INDEX, NULL);
++#ifdef CONFIG_I2S_USE_DMA
++ free_irq(INTC_GDMAC_TC_BIT_INDEX, NULL);
++ free_irq(INTC_GDMAC_ERROR_BIT_INDEX, NULL);
++#endif //CONFIG_I2S_USE_DMA
++ if(lbuffer) {
++ pci_free_consistent(NULL, BUFSIZE, lbuffer, lbuffer_p);
++ lbuffer=lbuffer_p=NULL;
++ }
++}
++
++static int __devinit i2s_init_module(void)
++{
++ u32 ret;
++
++ printk("%s:\n",__FUNCTION__);
++#ifdef CONFIG_I2S_USE_DMA
++ printk("%s: DMA Enabled...\n",__FUNCTION__);
++#endif //CONFIG_I2S_USE_DMA
++
++ star_i2s_proc_entry = create_proc_entry("str8100/i2s", S_IFREG | S_IRUGO, NULL);
++ if(!star_i2s_proc_entry){
++ return -EBUSY;
++ }
++ star_i2s_proc_entry->read_proc=proc_read_i2s;
++ star_i2s_proc_entry->write_proc=proc_write_i2s;
++
++ lbuffer = pci_alloc_consistent(NULL, BUFSIZE, &lbuffer_p);
++ if(!lbuffer){
++ printk("%s: alloc lbuffer failed.\n",__FUNCTION__);
++ goto exit1;
++ }
++
++ str8100_set_interrupt_trigger (INTC_I2S_BIT_INDEX,INTC_LEVEL_TRIGGER,INTC_ACTIVE_LOW);
++ if ((ret=request_irq(INTC_I2S_BIT_INDEX, str8100_i2s_irq_handler, 0, "i2s", NULL))){
++ printk("%s: request_irq %d failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,INTC_I2S_BIT_INDEX,ret,-EBUSY);
++ goto exit1;
++ }
++
++#ifdef CONFIG_I2S_USE_DMA
++ str8100_set_interrupt_trigger (INTC_GDMAC_TC_BIT_INDEX,INTC_LEVEL_TRIGGER,INTC_ACTIVE_HIGH);
++ if ((ret=request_irq(INTC_GDMAC_TC_BIT_INDEX, str8100_dma_tc_irq_handler, 0, "dma tc", NULL))){
++ printk("%s: request_irq %d failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,INTC_GDMAC_TC_BIT_INDEX,ret,-EBUSY);
++ goto exit1;
++ }
++ str8100_set_interrupt_trigger (INTC_GDMAC_ERROR_BIT_INDEX,INTC_LEVEL_TRIGGER,INTC_ACTIVE_HIGH);
++ if ((ret=request_irq(INTC_GDMAC_ERROR_BIT_INDEX, str8100_dma_err_irq_handler, 0, "dma error", NULL))){
++ printk("%s: request_irq %d failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,INTC_GDMAC_ERROR_BIT_INDEX,ret,-EBUSY);
++ goto exit1;
++ }
++#endif //CONFIG_I2S_USE_DMA
++
++ return 0;
++exit1:
++ i2s_exit_module();
++ return -EBUSY;
++}
++
++module_init(i2s_init_module);
++module_exit(i2s_exit_module);
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_intc.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_intc.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_intc.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_intc.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,222 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/module.h>
++
++#include <mach/hardware.h>
++#include <asm/mach/irq.h>
++#include <asm/irq.h>
++
++#define INTC_TRIGGER_UNKNOWN -1
++
++typedef struct
++{
++ int mode;
++ int level;
++} intc_trigger_t;
++
++static intc_trigger_t intc_trigger_table[] =
++{
++ { INTC_EDGE_TRIGGER, INTC_RISING_EDGE }, // 0
++ { INTC_EDGE_TRIGGER, INTC_RISING_EDGE }, // 1
++ { INTC_EDGE_TRIGGER, INTC_FALLING_EDGE }, // 2
++ { INTC_EDGE_TRIGGER, INTC_RISING_EDGE }, // 3
++ { INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN }, // 4
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW }, // 5
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW }, // 6
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH }, // 7
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH }, // 8
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH }, // 9
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH }, // 10
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH }, // 11
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH }, // 12
++ { INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN }, // 13
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH }, // 14
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW }, // 15
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW }, // 16
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH }, // 17
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH }, // 18
++ { INTC_EDGE_TRIGGER, INTC_RISING_EDGE }, // 19
++ { INTC_EDGE_TRIGGER, INTC_RISING_EDGE }, // 20
++ { INTC_EDGE_TRIGGER, INTC_RISING_EDGE }, // 21
++ { INTC_EDGE_TRIGGER, INTC_RISING_EDGE }, // 22
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW }, // 23
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW }, // 24
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW }, // 25
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW }, // 26
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW }, // 27
++ { INTC_EDGE_TRIGGER, INTC_RISING_EDGE }, // 28
++ { INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN }, // 29
++ { INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN }, // 30
++ { INTC_EDGE_TRIGGER, INTC_RISING_EDGE }, // 31
++};
++
++static u32 intc_edge_trigger_bitmap;
++
++/*
++ * Configure interrupt trigger mode to be level trigger or edge trigger
++ */
++static inline void str8100_set_irq_mode(unsigned int irq, unsigned int mode)
++{
++ volatile unsigned int val;
++
++ if (irq < 0 || irq > NR_IRQS) {
++ return;
++ }
++
++ if ((mode != INTC_LEVEL_TRIGGER) &&
++ (mode != INTC_EDGE_TRIGGER)) {
++ return;
++ }
++
++ val = INTC_INTERRUPT_TRIGGER_MODE_REG;
++
++ if (mode == INTC_LEVEL_TRIGGER) {
++ if (val & (1UL << irq)) {
++ val &= ~(1UL << irq);
++ INTC_INTERRUPT_TRIGGER_MODE_REG = val;
++ }
++ } else {
++ intc_edge_trigger_bitmap |= (1UL << irq);
++ if (!(val & (1UL << irq))) {
++ val |= (1UL << irq);
++ INTC_INTERRUPT_TRIGGER_MODE_REG = val;
++ }
++ }
++}
++
++/*
++ * Configure interrupt trigger level to be Active High/Low or Rising/Falling Edge
++ */
++static inline void str8100_set_irq_level(unsigned int irq, unsigned int level)
++{
++ volatile unsigned int val;
++
++ if (irq < 0 || irq > NR_IRQS) {
++ return;
++ }
++
++ if ((level != INTC_ACTIVE_HIGH) &&
++ (level != INTC_ACTIVE_LOW) &&
++ (level != INTC_RISING_EDGE) &&
++ (level != INTC_FALLING_EDGE)) {
++ return;
++ }
++
++ val = INTC_INTERRUPT_TRIGGER_LEVEL_REG;
++
++ if ((level == INTC_ACTIVE_HIGH) ||
++ (level == INTC_RISING_EDGE)) {
++ if (val & (1UL << irq)) {
++ val &= ~(1UL << irq);
++ INTC_INTERRUPT_TRIGGER_LEVEL_REG = val;
++ }
++ } else {
++ if (!(val & (1UL << irq))) {
++ val |= (1UL << irq);
++ INTC_INTERRUPT_TRIGGER_LEVEL_REG = val;
++ }
++ }
++}
++
++/*
++ * Configure interrupt trigger mode and trigger level
++ */
++void str8100_set_interrupt_trigger(unsigned int irq, unsigned int mode, unsigned int level)
++{
++ str8100_set_irq_mode(irq, mode);
++ str8100_set_irq_level(irq, level);
++}
++EXPORT_SYMBOL(str8100_set_interrupt_trigger);
++
++/*
++ * Mask/Disable this interrupt source
++ */
++void str8100_mask_irq(unsigned int irq)
++{
++
++// if (irq != INTC_NIC_RXRC_BIT_INDEX && irq != INTC_NIC_RXQF_BIT_INDEX) {
++ // Mask/Disable this interrupt source
++ INTC_INTERRUPT_MASK_REG = (1UL << irq);
++// }
++}
++
++/*
++ * Un-Mask/Enable this interrupt source
++ */
++void str8100_unmask_irq(unsigned int irq)
++{
++
++#ifndef CONFIG_VIC_INTERRUPT
++ // Clear interrupt status of the interrupt source which is edge-triggered
++ INTC_EDGE_INTERRUPT_SOURCE_CLEAR_REG = (1UL << irq);
++#endif
++ // Enable this interrupt source
++ INTC_INTERRUPT_MASK_CLEAR_REG = (1UL << irq);
++}
++
++static struct irq_chip str8100_irqchip = {
++ .ack = str8100_mask_irq,
++ .mask = str8100_mask_irq,
++ .unmask = str8100_unmask_irq,
++};
++
++void __init str8100_init_irq(void)
++{
++ int i;
++
++ //printk("str8100_init_irq()\n");
++
++ disable_hlt();
++
++ INTC_INTERRUPT_MASK_REG = 0xFFFFFFFF;
++ INTC_EDGE_INTERRUPT_SOURCE_CLEAR_REG = 0xFFFFFFFF;
++ INTC_SOFTWARE_INTERRUPT_CLEAR_REG = 0xFFFFFFFF;
++ INTC_SOFTWARE_PRIORITY_MASK_REG = 0x0;
++ INTC_FIQ_SELECT_REG = 0x0;
++#ifdef CONFIG_VIC_INTERRUPT
++ for (i = 0; i < NR_IRQS; i++) {
++ (*((u32 volatile *)(SYSVA_VIC_BASE_ADDR + 0x40 + (i << 2)))) = i;
++ }
++ INTC_VECTOR_INTERRUPT_ENABLE_REG = 1;
++#else
++ INTC_VECTOR_INTERRUPT_ENABLE_REG = 0;
++#endif
++
++ for (i = 0; i < NR_IRQS; i++) {
++ if (intc_trigger_table[i].mode != INTC_TRIGGER_UNKNOWN) {
++ str8100_set_irq_mode(i, intc_trigger_table[i].mode);
++ str8100_set_irq_level(i, intc_trigger_table[i].level);
++ }
++ }
++
++ for (i = 0; i < NR_IRQS; i++) {
++ set_irq_chip(i, &str8100_irqchip);
++ /* scott.patch */
++ set_irq_handler(i, handle_level_irq);
++ set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
++ }
++}
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_misc.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_misc.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_misc.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_misc.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,210 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++//#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/proc_fs.h>
++#include <asm/mach/map.h>
++#include <mach/hardware.h>
++
++static struct map_desc str8100_map_desc[64];
++static int str8100_map_desc_count;
++
++#define REG_DEBUG_CMD_BUFFER_SIZE 128
++#define REG_DEBUG_RESULT_BUFFER_SIZE 256
++
++struct proc_dir_entry *str8100_proc_dir;
++EXPORT_SYMBOL(str8100_proc_dir);
++static struct proc_dir_entry *star_reg_debug_proc_entry;
++static char str8100_reg_debug_cmd_buf[REG_DEBUG_CMD_BUFFER_SIZE];
++static char str8100_reg_debug_result_buf[REG_DEBUG_RESULT_BUFFER_SIZE];
++
++void str8100_register_map_desc(struct map_desc *map, int count)
++{
++ if (count) {
++ if (str8100_map_desc) {
++ int i;
++ for (i = 0; i < count; i++) {
++ str8100_map_desc[i].virtual = map->virtual;
++ str8100_map_desc[i].pfn = map->pfn;
++ str8100_map_desc[i].length = map->length;
++ str8100_map_desc[i].type = map->type;
++ map++;
++ }
++ str8100_map_desc_count = count;
++ }
++ }
++}
++
++u32 str8100_query_map_desc_by_phy(u32 addr)
++{
++ struct map_desc *map;
++ int i;
++ u32 ret_addr = 0;
++ for (i = 0; i < str8100_map_desc_count; i++) {
++ map = &str8100_map_desc[i];
++ if (addr >= (map->pfn << PAGE_SHIFT) && addr < ((map->pfn << PAGE_SHIFT) + map->length)) {
++ ret_addr = map->virtual + (addr - (map->pfn << PAGE_SHIFT));
++ break;
++ }
++ }
++
++ return ret_addr;
++}
++
++u32 str8100_query_map_desc_by_vir(u32 addr)
++{
++ struct map_desc *map;
++ int i;
++ u32 ret_addr = 0;
++ for (i = 0; i < str8100_map_desc_count; i++) {
++ map = &str8100_map_desc[i];
++ if (addr >= map->virtual && addr < (map->virtual + map->length)) {
++ ret_addr = (map->pfn << PAGE_SHIFT) + (addr - map->virtual);
++ break;
++ }
++ }
++
++ return ret_addr;
++}
++
++static int star_reg_debug_read_proc(char *buffer, char **start, off_t offset,
++ int length, int *eof, void *data)
++{
++ int count;
++ int num = 0;
++
++ if (str8100_reg_debug_cmd_buf[0]) {
++ count = strlen(str8100_reg_debug_cmd_buf);
++ sprintf(buffer, str8100_reg_debug_cmd_buf, count);
++ num += count;
++ }
++ if (str8100_reg_debug_result_buf[0]) {
++ count = strlen(str8100_reg_debug_result_buf);
++ sprintf(buffer + num, str8100_reg_debug_result_buf, count);
++ num += count;
++ }
++
++ return num;
++}
++
++static int
++star_reg_debug_write_proc(struct file *file, const char __user *buffer,
++ unsigned long count, void *data)
++{
++ char *str;
++ char *cmd;
++
++ if (count > 0) {
++ str = (char *)buffer,
++ cmd = strsep(&str, "\t \n");
++ if (!cmd) goto err_out;
++ if (strcmp(cmd, "dump") == 0) {
++ u32 addr;
++ u32 vir_addr;
++ char *arg = strsep(&str, "\t \n");
++ if (!arg) goto err_out;
++ addr = simple_strtoul(arg, &arg, 16);
++ if (addr & 0x3) goto err_out;
++ vir_addr = str8100_query_map_desc_by_phy(addr);
++ sprintf(str8100_reg_debug_cmd_buf,
++ "dump 0x%08x\n",
++ addr);
++ if (!vir_addr) goto err_out;
++ sprintf(str8100_reg_debug_result_buf,
++ "physical addr: 0x%08x content: 0x%08x\n",
++ addr,
++ *(volatile unsigned int __force *)(vir_addr));
++ } else if (strcmp(cmd, "write") == 0) {
++ u32 addr;
++ u32 vir_addr;
++ u32 data;
++ char *arg = strsep(&str, "\t \n");
++ if (!arg) goto err_out;
++ addr = simple_strtoul(arg, &arg, 16);
++ arg = strsep(&str, "\t \n");
++ if (!arg) goto err_out;
++ data = simple_strtoul(arg, &arg, 16);
++ if (addr & 0x3) goto err_out;
++ vir_addr = str8100_query_map_desc_by_phy(addr);
++ if (!vir_addr) goto err_out;
++ *(volatile unsigned int __force *)(vir_addr) = data;
++ sprintf(str8100_reg_debug_cmd_buf,
++ "write 0x%08x 0x%08x\n",
++ addr, data);
++ sprintf(str8100_reg_debug_result_buf,
++ "physical addr: 0x%08x content: 0x%08x\n",
++ addr,
++ *(volatile unsigned int __force *)(vir_addr));
++ } else {
++ goto err_out;
++ }
++ }
++
++ return count;
++
++err_out:
++ return -EFAULT;
++}
++
++static int __init star_reg_debug_proc_init(void)
++{
++ star_reg_debug_proc_entry = create_proc_entry("str8100/reg_debug", S_IFREG | S_IRUGO, NULL);
++ if (star_reg_debug_proc_entry) {
++ star_reg_debug_proc_entry->read_proc = star_reg_debug_read_proc;
++ star_reg_debug_proc_entry->write_proc = star_reg_debug_write_proc;
++ }
++
++ return 0;
++}
++
++static int __init str8100_proc_dir_create(void)
++{
++ str8100_proc_dir = proc_mkdir("str8100", NULL);
++ if (!str8100_proc_dir) {
++ printk("Error: cannot create str8100 proc dir entry at /proc/str8100\n");
++ return -EINVAL;
++ }
++
++ if (str8100_map_desc_count) {
++ (void)star_reg_debug_proc_init();
++ }
++
++ return 0;
++}
++
++extern int __init str8100_counter_setup(void);
++static int __init str8100_misc_init(void)
++{
++ str8100_proc_dir_create();
++ str8100_counter_setup();
++ return 0;
++}
++
++module_init(str8100_misc_init);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Star Semi Corporation");
++MODULE_DESCRIPTION("STR8100 MISC");
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_pci.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_pci.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_pci.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_pci.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,337 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++//#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/ptrace.h>
++#include <linux/slab.h>
++#include <linux/ioport.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/init.h>
++
++#include <mach/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++#include <asm/mach/pci.h>
++
++#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | ((bus) << 16) | ((device_fn) << 8) | ((where) & ~3))
++
++static struct pci_dev *pci_bridge = NULL;
++static u32 pci_config_addr; // PCI configuration register address port
++static u32 pci_config_data; // PCI configuration register data port
++u32 str8100_pci_irqs[4] = {0, INTC_PCI_INTA_BIT_INDEX, INTC_PCI_INTB_BIT_INDEX, 0};
++
++static int str8100_pci_read_config(struct pci_bus *bus,
++ unsigned int devfn, int where, int size, u32 *val)
++{
++ u32 v = 0;
++ u32 shift;
++ unsigned long flags;
++
++ switch (size) {
++ case 1:
++ shift = (where & 0x3) << 3;
++ local_irq_save(flags);
++ __raw_writel(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ v = __raw_readl(pci_config_data);
++ local_irq_restore(flags);
++ v = (v >> shift) & 0xff;
++ break;
++
++ case 2:
++ shift = (where & 0x3) << 3;
++ local_irq_save(flags);
++ __raw_writel(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ v = __raw_readl(pci_config_data);
++ local_irq_restore(flags);
++ v = (v >> shift) & 0xffff;
++
++ break;
++
++ case 4:
++ local_irq_save(flags);
++ __raw_writel(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ v = __raw_readl(pci_config_data);
++ local_irq_restore(flags);
++ break;
++ }
++
++ *val = v;
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int str8100_pci_write_config(struct pci_bus *bus,
++ unsigned int devfn, int where, int size, u32 val)
++{
++ u32 v;
++ u32 shift;
++ unsigned long flags;
++
++ switch (size) {
++ case 1:
++ shift = (where & 0x3) << 3;
++ local_irq_save(flags);
++ __raw_writel(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ v = __raw_readl(pci_config_data);
++ v = (v & ~(0xff << shift)) | (val << shift);
++ __raw_writel(v, pci_config_data);
++ local_irq_restore(flags);
++ break;
++
++ case 2:
++ shift = (where & 0x3) << 3;
++ local_irq_save(flags);
++ __raw_writel(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ v = __raw_readl(pci_config_data);
++ v = (v & ~(0xffff << shift)) | (val << shift);
++ __raw_writel(v, pci_config_data);
++ local_irq_restore(flags);
++ break;
++
++ case 4:
++ local_irq_save(flags);
++ __raw_writel(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ __raw_writel(val, pci_config_data);
++ local_irq_restore(flags);
++ break;
++ }
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops str8100_pci_ops = {
++ .read = str8100_pci_read_config,
++ .write = str8100_pci_write_config,
++};
++
++static struct resource str8100_pci_io = {
++ .name = "PCI I/O space",
++ .start = PCI_IO_SPACE_START,
++ .end = PCI_IO_SPACE_END, //albert : 20040714
++ .flags = IORESOURCE_IO,
++};
++
++static struct resource str8100_pci_nprefetch_mem = {
++ .name = "PCI non-prefetchable",
++ .start = PCI_NPREFETCH_MEMORY_SPACE_START,
++ .end = PCI_NPREFETCH_MEMORY_SPACE_END,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct resource str8100_pci_prefetch_mem = {
++ .name = "PCI prefetchable",
++ .start = PCI_PREFETCH_MEMORY_SPACE_START,
++ .end = PCI_PREFETCH_MEMORY_SPACE_END,
++ .flags = IORESOURCE_MEM | IORESOURCE_PREFETCH,
++};
++
++static int __init str8100_pci_setup_resources(struct resource **resource)
++{
++ int ret = -1;
++
++ ret = request_resource(&iomem_resource, &str8100_pci_io);
++ if (ret) {
++ printk(KERN_ERR "PCI: unable to allocate I/O "
++ "memory region (%d)\n", ret);
++ goto out;
++ }
++ ret = request_resource(&iomem_resource, &str8100_pci_nprefetch_mem);
++ if (ret) {
++ printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
++ "memory region (%d)\n", ret);
++ goto release_io;
++ }
++ ret = request_resource(&iomem_resource, &str8100_pci_prefetch_mem);
++ if (ret) {
++ printk(KERN_ERR "PCI: unable to allocate prefetchable "
++ "memory region (%d)\n", ret);
++ goto release_nprefetch_mem;
++ }
++
++ /*
++ * bus->resource[0] is the IO resource for this bus
++ * bus->resource[1] is the mem resource for this bus
++ * bus->resource[2] is the prefetch mem resource for this bus
++ */
++ resource[0] = &str8100_pci_io;
++ resource[1] = &str8100_pci_nprefetch_mem;
++ resource[2] = &str8100_pci_prefetch_mem;
++
++ ret = 0;
++
++ goto out;
++
++release_nprefetch_mem:
++ release_resource(&str8100_pci_nprefetch_mem);
++release_io:
++ release_resource(&str8100_pci_io);
++out:
++ return ret;
++}
++
++static irqreturn_t PCI_AHB2PCIB_ISR(int irq, void *dev_id /*, struct pt_regs * regs*/)
++{
++ u32 status;
++
++ //disable_irq(INTC_PCI_AHB2BRIDGE_BIT_INDEX);
++ pci_read_config_dword(pci_bridge, PCI_COMMAND, &status);
++ printk("AHB to bridge interrupt status: 0x%x\n", status);
++ pci_write_config_dword(pci_bridge, PCI_COMMAND, status);
++ //enable_irq(INTC_PCI_AHB2BRIDGE_BIT_INDEX);
++
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t PCI_BROKEN_ISR(int irq, void *dev_id /*, struct pt_regs *regs*/)
++{
++ u32 status;
++
++ status = MISC_PCI_BROKEN_STATUS_REG & 0x1f;
++ printk("PCI BROKEN interrupt status: 0x%x\n", status);
++ MISC_PCI_BROKEN_STATUS_REG = status;
++
++ return IRQ_HANDLED;
++}
++
++int __init str8100_pci_setup(int nr, struct pci_sys_data *sys)
++{
++ if (nr != 0) {
++ return 0;
++ }
++
++ if (str8100_pci_setup_resources(sys->resource)) {
++ BUG();
++ }
++
++ return 1;
++}
++
++struct pci_bus * __devinit str8100_pci_scan_bus(int nr, struct pci_sys_data *sys)
++{
++ return pci_scan_bus(sys->busnr, &str8100_pci_ops, sys);
++}
++
++void __init str8100_pci_preinit(void)
++{
++ pci_config_addr = SYSVA_PCI_BRIDGE_CONFIG_ADDR_BASE_ADDR + PCI_BRIDGE_CONFIG_ADDR_REG_OFFSET;
++ pci_config_data = SYSVA_PCI_BRIDGE_CONFIG_DATA_BASE_ADDR + PCI_BRIDGE_CONFIG_DATA_REG_OFFSET;
++
++ HAL_MISC_ENABLE_PCI_PINS();
++
++#ifdef CONFIG_STR8100_PCI66M
++ printk("PCI clock at 66M\n");
++ HAL_PWRMGT_ENABLE_PCI_BRIDGE_66M_CLOCK();
++#else
++ printk("PCI clock at 33M\n");
++ HAL_PWRMGT_ENABLE_PCI_BRIDGE_33M_CLOCK();
++#endif
++}
++
++void __init str8100_pci_postinit(void)
++{
++// pci_bridge = pci_find_device(PCIB_VENDOR_ID, PCIB_DEVICE_ID, NULL);
++ pci_bridge = pci_get_device(PCIB_VENDOR_ID, PCIB_DEVICE_ID, NULL);
++ if (pci_bridge == NULL) {
++ printk("PCI Bridge not found\n");
++ return;
++ } else {
++ printk("PCI Bridge found\n");
++ }
++
++ /* scott.patch
++ request_irq(INTC_PCI_AHB2BRIDGE_BIT_INDEX, PCI_AHB2PCIB_ISR, SA_INTERRUPT, "pci bridge", pci_bridge);
++ */
++ request_irq(INTC_PCI_AHB2BRIDGE_BIT_INDEX, PCI_AHB2PCIB_ISR, IRQF_DISABLED, "pci bridge", (void*)pci_bridge);
++
++ MISC_PCI_CONTROL_BROKEN_MASK_REG &= ~0x1f;
++
++ /* scott.patch */
++ request_irq(INTC_PCI_BROKEN_BIT_INDEX, PCI_BROKEN_ISR, IRQF_DISABLED, "pci broken", pci_bridge);
++
++ //albert :20040803
++ pci_write_config_dword(pci_bridge, PCI_BASE_ADDRESS_0, 0x0); // = 0x0, can NOT use 0x20000000
++ pci_write_config_dword(pci_bridge, PCI_BASE_ADDRESS_1, 0x0); // = 0x0, can NOT use 0x20000000
++
++ // if we enable pci on u-boot
++ // the pci_enable_device will complain with resource collisions
++ // use this to fixup
++ {
++ int i;
++ struct resource *r;
++
++ for (i = 0; i < 6; i++) {
++ r = pci_bridge->resource + i;
++ r->start = 0;
++ r->end = 0;
++ }
++ }
++
++ pci_enable_device(pci_bridge);
++ pci_set_master(pci_bridge);
++
++ pci_write_config_byte(pci_bridge, PCI_CACHE_LINE_SIZE, 0x8); //configure cache line size
++ pci_write_config_byte(pci_bridge, PCI_LATENCY_TIMER, 0x30); //configure latency timer
++}
++
++/*
++ * map the specified device/slot/pin to an IRQ. Different backplanes may need to modify this.
++ */
++static int __init str8100_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ int irq;
++
++ /* slot, pin, irq
++ * 0 1 0
++ * 1 1 5
++ * 2 1 6
++ * 3 1 0
++ */
++ irq = str8100_pci_irqs[((slot + pin - 1) & 3)];
++
++ printk("PCI map irq: %02x:%02x.%02x slot %d, pin %d, irq: %d\n",
++ dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
++ slot, pin, irq);
++
++ return irq;
++}
++
++static struct hw_pci str8100_pci __initdata = {
++ .swizzle = pci_std_swizzle,
++ .map_irq = str8100_pci_map_irq,
++ .nr_controllers = 1,
++ .setup = str8100_pci_setup,
++ .scan = str8100_pci_scan_bus,
++ .preinit = str8100_pci_preinit,
++ .postinit = str8100_pci_postinit,
++};
++
++static int __init str8100_pci_init(void)
++{
++ pci_common_init(&str8100_pci);
++ return 0;
++}
++
++subsys_initcall(str8100_pci_init);
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_pm.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_pm.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_pm.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_pm.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,162 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/pm.h>
++#include <linux/sched.h>
++#include <linux/proc_fs.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/mach/time.h>
++#include <asm/mach/irq.h>
++
++#include <asm/mach-types.h>
++#include <linux/suspend.h>
++
++#ifdef CONFIG_PM
++/******************************************************************************
++ *
++ * FUNCTION: Hal_Cpu_Enter_Sleep_Mode
++ * PURPOSE:
++ *
++ ******************************************************************************/
++#ifdef CONFIG_PM_DEBUG
++#define PM_DEBUG printk
++#else
++#define PM_DEBUG(_parm,...)
++#endif
++void inline Hal_Cpu_Enter_Sleep_Mode(void)
++{
++ __asm__ volatile (
++ "nop\n"
++ "mcr p15, 0, r0, c7, c0, 5\n");
++}
++
++static int str8100_pm_prepare(suspend_state_t state)
++{
++ int error = 0;
++ PM_DEBUG("%s: state=%d\n",__FUNCTION__,state);
++ switch (state)
++ {
++ case PM_SUSPEND_STANDBY:
++ case PM_SUSPEND_MEM:
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ return error;
++}
++
++extern int str8100_nic_suspend(suspend_state_t);
++extern int str8100_nic_resume(void);
++static int str8100_pm_enter(suspend_state_t state)
++{
++ PM_DEBUG("%s: state=%d\n",__FUNCTION__,state);
++ switch (state)
++ {
++ case PM_SUSPEND_STANDBY:
++ case PM_SUSPEND_MEM:
++
++#ifdef DEBUG
++ /*
++ * Configure system Xtal clock to be output to CLKOUT pin
++ */
++ HAL_PWRMGT_CONFIGURE_CLOCK_OUT_PIN(0, 0);
++#endif
++
++ /*
++ * 1. Disable DRAM Controller's clock
++ * 2. Power-down sytem 25MHz XTAL pad
++ * 3. Force CPU into sleep mode, and wait until wake-up interrupt happens!!
++ * When in sleep mode, CPU internal clock and system PLLs and/or 25MHZ XTAL
++ * pad will be power-down!!
++ */
++
++//int 16, 18, 28-30
++//#define WAKEUP_INT 0x70050000
++//int 16, 18, 29-30
++//#define WAKEUP_INT 0x60050000
++//int 18, 29-30
++#define WAKEUP_INT 0x60040000
++//int 29-30
++//#define WAKEUP_INT 0x60000000
++//#define WAKEUP_INT 0xffffffff
++ PM_DEBUG("%s: int that can wake cpu up, WAKEUP_INT=%.8x\n",__FUNCTION__,WAKEUP_INT);
++// HAL_INTC_SELECT_INTERRUPT_SOURCE_FOR_SLEEP_WAKEUP(30);
++ INTC_POWER_MANAGEMENT_INTERRUPT_REG=WAKEUP_INT;
++ HAL_PWRMGT_DISABLE_DRAMC_CLOCK();
++#ifndef CONFIG_STAR_NIC_PHY_INTERNAL_PHY
++ HAL_PWRMGT_POWER_DOWN_SYSTEM_XTAL_PAD();
++#endif
++
++ PM_DEBUG("%s: bye...\n",__FUNCTION__);
++ str8100_nic_suspend(state);
++ local_irq_enable();
++ Hal_Cpu_Enter_Sleep_Mode();
++ local_irq_disable();
++ str8100_nic_resume();
++ PM_DEBUG("%s: awake from sleep\n",__FUNCTION__);
++
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++/*
++static int str8100_pm_finish(suspend_state_t state)
++{
++printk("%s: \n",__FUNCTION__);
++ return 0;
++}
++*/
++
++static struct platform_suspend_ops str8100_pm_ops ={
++ .prepare = str8100_pm_prepare,
++ .enter = str8100_pm_enter,
++// .finish = str8100_pm_finish,
++};
++
++static int __init str8100_pm_init(void)
++{
++ int ret;
++printk("%s: \n",__FUNCTION__);
++
++ /*
++ * Configure system Xtal clock to be output to CLKOUT pin
++ */
++ HAL_PWRMGT_CONFIGURE_CLOCK_OUT_PIN(0, 0);
++
++ suspend_set_ops(&str8100_pm_ops);
++ return 0;
++}
++__initcall(str8100_pm_init);
++
++
++#endif//CONFIG_PM
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_rtc.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_rtc.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_rtc.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_rtc.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,497 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/miscdevice.h>
++#include <linux/ioport.h>
++#include <linux/fcntl.h>
++#include <linux/init.h>
++#include <linux/poll.h>
++#include <linux/proc_fs.h>
++#include <linux/spinlock.h>
++#include <linux/sysctl.h>
++#include <linux/rtc.h>
++#include <linux/interrupt.h>
++
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/system.h>
++
++#include <mach/star_rtc.h>
++#include <mach/star_intc.h>
++
++#define STR8100_RTC_DATE "20060628"
++#define STR8100_RTC_VERSION "1.0.0"
++#define DEVICE_NAME "rtc"
++#define SECS_PER_HOUR (60 * 60)
++#define SECS_PER_DAY (SECS_PER_HOUR * 24)
++#define TM_YEAR_BASE 1900
++#define EPOCH_YEAR 1970
++#define RTC_INTR_ALARM 0x20
++
++extern spinlock_t rtc_lock;
++
++static int rtc_busy = 0;
++static unsigned long epoch = 1900;
++static unsigned int rtc_interrupt_flag = 0;
++static time_t local_rtc_offset, set_rtc_offset, current_rtc_time;
++static DECLARE_WAIT_QUEUE_HEAD(str8100_rtc_wait);
++
++
++# define __isleap(year) ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
++
++static const unsigned char days_in_mo[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
++
++static const unsigned short int __mon_yday[2][13] =
++{
++ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
++ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
++};
++
++static int offtime (const time_t *t, long int offset, struct rtc_time *tp)
++{
++ long int days, rem, y;
++ const unsigned short int *ip;
++
++ days = *t / SECS_PER_DAY;
++ rem = *t % SECS_PER_DAY;
++ rem += offset;
++ while (rem < 0)
++ {
++ rem += SECS_PER_DAY;
++ --days;
++ }
++ while (rem >= SECS_PER_DAY)
++ {
++ rem -= SECS_PER_DAY;
++ ++days;
++ }
++ tp->tm_hour = rem / SECS_PER_HOUR;
++ rem %= SECS_PER_HOUR;
++ tp->tm_min = rem / 60;
++ tp->tm_sec = rem % 60;
++ tp->tm_wday = (4 + days) % 7;
++ if (tp->tm_wday < 0)
++ tp->tm_wday += 7;
++ y = 1970;
++#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
++#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
++ while (days < 0 || days >= (__isleap (y) ? 366 : 365))
++ {
++ long int yg = y + days / 365 - (days % 365 < 0);
++ days -= ((yg - y) * 365 + LEAPS_THRU_END_OF (yg - 1)- LEAPS_THRU_END_OF (y - 1));
++ y = yg;
++ }
++ tp->tm_year = y - 1900;
++ if (tp->tm_year != y - 1900)
++ return 0;
++ tp->tm_yday = days;
++ ip = __mon_yday[__isleap(y)];
++ for (y = 11; days < (long int) ip[y]; --y)
++ continue;
++ days -= ip[y];
++ tp->tm_mon = y;
++ tp->tm_mday = days + 1;
++ return 1;
++}
++
++static time_t ydhms_tm_diff (int year, int yday, int hour, int min, int sec, const struct rtc_time *tp)
++{
++ if (!tp) return 1;
++ else {
++ int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
++ int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
++ int a100 = a4 / 25 - (a4 % 25 < 0);
++ int b100 = b4 / 25 - (b4 % 25 < 0);
++ int a400 = a100 >> 2;
++ int b400 = b100 >> 2;
++ int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
++ time_t years = year - (time_t) tp->tm_year;
++ time_t days = (365 * years + intervening_leap_days + (yday - tp->tm_yday));
++ return (60 * (60 * (24 * days+(hour - tp->tm_hour))+(min - tp->tm_min))+(sec - tp->tm_sec));
++ }
++}
++
++static time_t _mktime(struct rtc_time *tp, time_t *offset)
++{
++ time_t t;
++ struct rtc_time tm;
++ int sec = tp->tm_sec;
++ int min = tp->tm_min;
++ int hour = tp->tm_hour;
++ int mday = tp->tm_mday;
++ int mon = tp->tm_mon;
++ int year_requested = tp->tm_year;
++
++ int mon_remainder = mon % 12;
++ int negative_mon_remainder = mon_remainder < 0;
++ int mon_years = mon / 12 - negative_mon_remainder;
++ int year = year_requested + mon_years;
++ int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
++ [mon_remainder + 12 * negative_mon_remainder])
++ + mday - 1);
++ if (year < 69) return -1;
++ tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
++ tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
++ t = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
++ if (year == 69)
++ {
++ if (t < 0 || t > 2 * 24 * 60 * 60) return -1;
++ }
++ *tp = tm;
++ return t;
++}
++
++void get_rtc_time (struct rtc_time *rtc_tm)
++{
++ time_t update_time;
++
++ spin_lock (&rtc_lock);
++ update_time = RTC_SECOND_REG + RTC_MINUTE_REG * 60 + RTC_HOUR_REG * 60 * 60 + RTC_DAY_REG * 60 * 60 * 24 - local_rtc_offset + set_rtc_offset;
++ offtime(&update_time, 0, rtc_tm);
++ if ((rtc_tm->tm_year += (epoch - 1900)) <= 69)
++ rtc_tm->tm_year += 100;
++ spin_unlock (&rtc_lock);
++}
++
++int set_rtc_time (struct rtc_time *rtc_tm)
++{
++ unsigned char mon, day, hrs, min, sec, leap_yr;
++ unsigned int yrs;
++
++ spin_lock (&rtc_lock);
++ yrs = rtc_tm->tm_year + 1900;
++ mon = rtc_tm->tm_mon + 1;
++ day = rtc_tm->tm_mday;
++ hrs = rtc_tm->tm_hour;
++ min = rtc_tm->tm_min;
++ sec = rtc_tm->tm_sec;
++ if (yrs < 1970) return -EINVAL;
++ leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
++ if ((mon > 12) || (day == 0)) return -EINVAL;
++ if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) return -EINVAL;
++ if ((hrs >= 24) || (min >= 60) || (sec >= 60)) return -EINVAL;
++ if ((yrs -= epoch) > 255) return -EINVAL;
++ local_rtc_offset = RTC_SECOND_REG + RTC_MINUTE_REG * 60 + RTC_HOUR_REG * 60 * 60 + RTC_DAY_REG * 60 * 60 * 24;
++ set_rtc_offset = _mktime(rtc_tm, 0);
++ spin_unlock (&rtc_lock);
++ return 0;
++}
++
++int set_rtc_alm_time (struct rtc_time *alm_tm)
++{
++ unsigned char hrs, min, sec;
++ unsigned long alm_sec;
++ unsigned int volatile rtc_int_status;
++
++ spin_lock_irq(&rtc_lock);
++ alm_sec = alm_tm->tm_hour * 3600 + alm_tm->tm_min * 60 + alm_tm->tm_sec;
++ hrs = alm_sec / 3600;
++ min = (alm_sec % 3600) / 60;
++ sec = (alm_sec % 3600) % 60;
++ RTC_HOUR_ALARM_REG = hrs;
++ RTC_MINUTE_ALARM_REG = min;
++ RTC_SECOND_ALARM_REG = sec;
++ RTC_CONTROL_REG = RTC_MATCH_ALARM_ENABLE_BIT;
++ rtc_int_status = RTC_INTERRUPT_STATUS_REG;
++ RTC_INTERRUPT_STATUS_REG = rtc_int_status;
++ spin_unlock_irq(&rtc_lock);
++ return 0;
++}
++
++static loff_t rtc_lseek(struct file *file, loff_t offset, int origin)
++{
++ return -ESPIPE;
++}
++
++static void mask_rtc_irq_bit(unsigned char bit)
++{
++ unsigned char val;
++ unsigned int volatile rtc_int_status;
++
++ spin_lock_irq(&rtc_lock);
++ val = RTC_CONTROL_REG;
++ val &= ~bit;
++ RTC_CONTROL_REG = val;
++ rtc_int_status = RTC_INTERRUPT_STATUS_REG;
++ spin_unlock_irq(&rtc_lock);
++}
++
++static void set_rtc_irq_bit(unsigned char bit)
++{
++ unsigned char val;
++ unsigned int volatile rtc_int_status;
++
++ spin_lock_irq(&rtc_lock);
++ val = RTC_CONTROL_REG;
++ val |= bit;
++ RTC_CONTROL_REG = val;
++ rtc_int_status = RTC_INTERRUPT_STATUS_REG;
++ spin_unlock_irq(&rtc_lock);
++}
++
++static void get_rtc_alm_time(struct rtc_time *alm_tm)
++{
++ spin_lock_irq(&rtc_lock);
++ alm_tm->tm_sec = RTC_SECOND_ALARM_REG;
++ alm_tm->tm_min = RTC_MINUTE_ALARM_REG;
++ alm_tm->tm_hour = RTC_HOUR_ALARM_REG;
++ spin_unlock_irq(&rtc_lock);
++}
++
++static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg)
++{
++ struct rtc_time wtime;
++
++ switch (cmd)
++ {
++ case RTC_RD_TIME:
++ memset(&wtime, 0, sizeof(struct rtc_time));
++ get_rtc_time(&wtime);
++ break;
++ case RTC_SET_TIME:
++ {
++ struct rtc_time rtc_tm;
++ if (!capable(CAP_SYS_TIME))
++ return -EPERM;
++ if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
++ return -EFAULT;
++ set_rtc_time(&rtc_tm);
++ return 0;
++ }
++ case RTC_ALM_SET:
++ {
++ struct rtc_time alm_tm;
++ if (copy_from_user(&alm_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
++ return -EFAULT;
++ memset(&wtime, 0, sizeof(struct rtc_time));
++ set_rtc_alm_time(&alm_tm);
++ return 0;
++ }
++ case RTC_ALM_READ:
++ memset(&wtime, 0, sizeof(struct rtc_time));
++ get_rtc_alm_time(&wtime);
++ break;
++ case RTC_AIE_OFF:
++ mask_rtc_irq_bit(RTC_INTR_ALARM);
++ return 0;
++ case RTC_AIE_ON:
++ set_rtc_irq_bit(RTC_INTR_ALARM);
++ return 0;
++ default:
++ return -EINVAL;
++ }
++ return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
++}
++
++// Eileen , for linux kernel 2.6.24 , 20080417
++// old : static irqreturn_t rtc_fire(int irq, void *dev_id, struct pt_regs *regs)
++static irqreturn_t rtc_fire(int irq, void *dev_id)
++{
++ unsigned int volatile rtc_int_status;
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_RTC_BIT_INDEX);
++ HAL_RTC_READ_INTERRUPT_STATUS(rtc_int_status);
++ HAL_RTC_WRITE_INTERRUPT_STATUS(rtc_int_status);
++// HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_RTC_BIT_INDEX);
++// return IRQ_HANDLED;
++ if (rtc_int_status & RTC_AUTO_SECOND_ALARM_INTR_BIT) rtc_interrupt_flag |= RTC_AUTO_SECOND_ALARM_INTR_BIT;
++ if (rtc_int_status & RTC_AUTO_MINUTE_ALARM_INTR_BIT) rtc_interrupt_flag |= RTC_AUTO_MINUTE_ALARM_INTR_BIT;
++ if (rtc_int_status & RTC_AUTO_HOUR_ALARM_INTR_BIT) rtc_interrupt_flag |= RTC_AUTO_HOUR_ALARM_INTR_BIT;
++ if (rtc_int_status & RTC_AUTO_DAY_ALARM_INTR_BIT) rtc_interrupt_flag |= RTC_AUTO_DAY_ALARM_INTR_BIT;
++ if (rtc_int_status & RTC_MATCH_ALARM_INTR_BIT) {rtc_interrupt_flag |= RTC_MATCH_ALARM_INTR_BIT;
++ wake_up_interruptible(&str8100_rtc_wait);
++ }
++ if (rtc_int_status & RTC_BATTERY_LOW_VOLTAGE_INTR_BIT)
++ {
++ rtc_interrupt_flag |= RTC_BATTERY_LOW_VOLTAGE_INTR_BIT;
++ printk(" str8100 rtc: Low Battery Voltage!!\n");
++ }
++ if (!(rtc_interrupt_flag & RTC_MATCH_ALARM_INTR_BIT)) HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_RTC_BIT_INDEX);
++
++ return IRQ_HANDLED;
++}
++
++static void rtc_str8100_hwinit(int ctrl, int hour, int min, int sec)
++{
++ RTC_CONTROL_REG &= ~(RTC_ENABLE_BIT);
++ if (ctrl & RTC_MATCH_ALARM_ENABLE_BIT)
++ {
++ RTC_SECOND_ALARM_REG = sec;
++ RTC_MINUTE_ALARM_REG = min;
++ RTC_HOUR_ALARM_REG = hour;
++ }else{
++ RTC_SECOND_ALARM_REG = 0;
++ RTC_MINUTE_ALARM_REG = 0;
++ RTC_HOUR_ALARM_REG = 0;
++ }
++ RTC_CONTROL_REG = ctrl;
++}
++
++static int rtc_open(struct inode *inode, struct file *file)
++{
++ if (rtc_busy) return -EBUSY;
++
++ rtc_busy = 1;
++ return 0;
++}
++
++static ssize_t rtc_read(struct file * file, char *buf, size_t count, loff_t * ppos)
++{
++ DECLARE_WAITQUEUE(wait, current);
++ unsigned long data;
++ ssize_t retval;
++
++ if (count < sizeof(unsigned long))
++ return -EINVAL;
++
++ add_wait_queue(&str8100_rtc_wait, &wait);
++ set_current_state(TASK_INTERRUPTIBLE);
++ for (;;) {
++ spin_lock(&rtc_lock);
++ data = rtc_interrupt_flag;
++ if (data != 0) {
++ rtc_interrupt_flag = 0;
++ break;
++ }
++ spin_unlock(&rtc_lock);
++ if (file->f_flags & O_NONBLOCK) {
++ retval = -EAGAIN;
++ goto out;
++ }
++ if (signal_pending(current)) {
++ retval = -ERESTARTSYS;
++ goto out;
++ }
++ schedule();
++ }
++ spin_unlock(&rtc_lock);
++ retval = put_user(data, (unsigned long *) buf);
++ if (!retval) retval = sizeof(unsigned long);
++out:
++ mask_rtc_irq_bit(RTC_INTR_ALARM);
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&str8100_rtc_wait, &wait);
++ return retval;
++}
++
++static int rtc_release(struct inode *inode, struct file *file)
++{
++ rtc_busy = 0;
++ return 0;
++}
++
++static struct file_operations rtc_fops = {
++ owner: THIS_MODULE,
++ llseek: rtc_lseek,
++ ioctl: rtc_ioctl,
++ open: rtc_open,
++ read: rtc_read,
++ release: rtc_release
++};
++
++static struct miscdevice rtc_dev = { RTC_MINOR, "rtc", &rtc_fops };
++
++static int rtc_proc_output (char *buf)
++{
++ char *p;
++ struct rtc_time tm;
++
++ p = buf;
++ get_rtc_time(&tm);
++ p += sprintf(p,"rtc_time\t: %02d:%02d:%02d\n"
++ "rtc_date\t: %04d-%02d-%02d\n"
++ "rtc_epoch\t: %04lu\n",
++ tm.tm_hour, tm.tm_min, tm.tm_sec,
++ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch);
++ get_rtc_alm_time(&tm);
++ p += sprintf(p, "alarm\t\t: ");
++ if (tm.tm_hour <= 24)
++ p += sprintf(p, "%02d:", tm.tm_hour);
++ else
++ p += sprintf(p, "**:");
++ if (tm.tm_min <= 59)
++ p += sprintf(p, "%02d:", tm.tm_min);
++ else
++ p += sprintf(p, "**:");
++ if (tm.tm_sec <= 59)
++ p += sprintf(p, "%02d\n", tm.tm_sec);
++ else
++ p += sprintf(p, "**\n");
++ return p - buf;
++}
++
++static int rtc_read_proc(char *page, char **start, off_t off,int count, int *eof, void *data)
++{
++ int len = rtc_proc_output (page);
++
++ if (len <= off+count) *eof = 1;
++ *start = page + off;
++ len -= off;
++ if (len>count) len = count;
++ if (len<0) len = 0;
++ return len;
++}
++
++static int __init str8100_rtc_init(void)
++{
++ int error;
++
++ error = misc_register(&rtc_dev);
++ if (error) {
++ printk(KERN_ERR "rtc: unable to get misc minor\n");
++ return error;
++ }
++ printk(KERN_INFO "str8100_rtc.o: rtc module version %s\n", STR8100_RTC_VERSION);
++ rtc_str8100_hwinit(0,0,0,0);
++ HAL_RTC_ENABLE();
++ request_irq(INTC_RTC_BIT_INDEX, rtc_fire, 0, DEVICE_NAME, NULL);
++ create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL);
++ local_rtc_offset = 0;
++ set_rtc_offset = current_rtc_time = 0;
++ return 0;
++}
++
++static void __exit str8100_rtc_exit (void)
++{
++ char buf[64];
++
++ HAL_RTC_DISABLE();
++ // Eileen , for linux kernel 2.6.24 , 20080417
++ // cleanup_sysctl();
++ sprintf (buf,"driver/%s",DEVICE_NAME);
++ remove_proc_entry (buf, NULL);
++ misc_deregister(&rtc_dev);
++ free_irq (INTC_RTC_BIT_INDEX, NULL);
++}
++
++module_init(str8100_rtc_init);
++module_exit(str8100_rtc_exit);
++// Eileen , for linux kernel 2.6.24 , 20080417
++//EXPORT_NO_SYMBOLS;
++
++MODULE_AUTHOR("Rober Hsu");
++MODULE_LICENSE("GPL");
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_setup.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_setup.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_setup.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_setup.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,569 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/mm.h>
++#include <linux/init.h>
++//#include <linux/config.h>
++#include <linux/major.h>
++#include <linux/fs.h>
++#include <linux/platform_device.h>
++#include <linux/serial.h>
++#include <linux/tty.h>
++#include <linux/serial_8250.h>
++#ifdef CONFIG_SPI_STR8100
++#include <mach/star_spi.h>
++#include <linux/spi/spi.h>
++#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
++#include <linux/spi/flash.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#endif
++#endif // CONFIG_SPI_STR8100
++
++#include <asm/io.h>
++#include <asm/pgtable.h>
++#include <asm/page.h>
++#include <asm/mach/map.h>
++#include <asm/setup.h>
++#include <asm/system.h>
++#include <asm/memory.h>
++#include <mach/hardware.h>
++#include <asm/mach-types.h>
++#include <asm/mach/arch.h>
++
++
++
++#if 1 // on ASIC
++#define STR8100_UART_XTAL 24000000
++#else // on FPGA
++#define STR8100_UART_XTAL 13000000
++#endif
++
++#define EARLY_REGISTER_CONSOLE
++#define DEVICE_REGISTER_MULTIPLE
++
++/*
++ * Standard IO mapping
++ */
++static struct map_desc str8100_std_desc[] __initdata = {
++ {
++ .virtual = SYSVA_FLASH_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_FLASH_SRAM_BANK0_BASE_ADDR),
++ .length = SZ_8M,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_IDE_DEVICE_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_IDE_DEVICE_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_GDMAC_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_GDMAC_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_NIC_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_NIC_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_SPI_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_SPI_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_PCM_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_PCM_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_I2C_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_I2C_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_I2S_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_I2S_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_DDRC_SDRC_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_DDRC_SDRC_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_SMC_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_SMC_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_IDE_CONTROLLER_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_IDE_CONTROLLER_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_MISC_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_MISC_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_POWER_MANAGEMENT_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_POWER_MANAGEMENT_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_UART0_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_UART0_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_UART1_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_UART1_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_TIMER_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_TIMER_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_WATCHDOG_TIMER_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_WATCHDOG_TIMER_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_RTC_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_RTC_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_GPIOA_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_GPIOA_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_GPIOB_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_GPIOB_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_PCI_BRIDGE_CONFIG_DATA_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_PCI_BRIDGE_CONFIG_DATA_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_PCI_BRIDGE_CONFIG_ADDR_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_PCI_BRIDGE_CONFIG_ADDR_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_USB11_CONFIG_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_USB11_CONFIG_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_USB11_OPERATION_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_USB11_OPERATION_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_USB20_CONFIG_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_USB20_CONFIG_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_USB20_OPERATION_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_USB20_OPERATION_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_USB20_DEVICE_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_USB20_DEVICE_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_VIC_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_VIC_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }
++};
++
++#ifdef EARLY_REGISTER_CONSOLE
++static struct uart_port str8100_serial_ports[] = {
++ {
++ .membase = (char*)(SYSVA_UART0_BASE_ADDR),
++ .mapbase = (SYSPA_UART0_BASE_ADDR),
++ .irq = INTC_UART0_BIT_INDEX,
++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ .iotype = UPIO_MEM,
++ .regshift = 2,
++ .uartclk = STR8100_UART_XTAL,
++ .line = 0,
++ .type = PORT_16550A,
++ .fifosize = 16
++ } , {
++ .membase = (char*)(SYSVA_UART1_BASE_ADDR),
++ .mapbase = (SYSPA_UART1_BASE_ADDR),
++ .irq = INTC_UART1_BIT_INDEX,
++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ .iotype = UPIO_MEM,
++ .regshift = 2,
++ .uartclk = STR8100_UART_XTAL,
++ .line = 1,
++ .type = PORT_16550A,
++ .fifosize = 16
++ }
++};
++#else
++static struct resource str8100_uart0_resources[] = {
++ [0] = {
++ .start = SYSPA_UART0_BASE_ADDR,
++ .end = SYSPA_UART0_BASE_ADDR + 0xff,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = INTC_UART0_BIT_INDEX,
++ .end = INTC_UART0_BIT_INDEX,
++ .flags = IORESOURCE_IRQ
++ }
++};
++
++static struct resource str8100_uart1_resources[] = {
++ [0] = {
++ .start = SYSPA_UART1_BASE_ADDR,
++ .end = SYSPA_UART1_BASE_ADDR + 0xff,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = INTC_UART1_BIT_INDEX,
++ .end = INTC_UART1_BIT_INDEX,
++ .flags = IORESOURCE_IRQ
++ }
++};
++
++static struct plat_serial8250_port str8100_uart0_data[] = {
++ {
++ .membase = (char*)(SYSVA_UART0_BASE_ADDR),
++ .mapbase = (SYSPA_UART0_BASE_ADDR),
++ .irq = INTC_UART0_BIT_INDEX,
++ .uartclk = STR8100_UART_XTAL,
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ },
++ { },
++};
++
++static struct plat_serial8250_port str8100_uart1_data[] = {
++ {
++ .membase = (char*)(SYSVA_UART1_BASE_ADDR),
++ .mapbase = (SYSPA_UART1_BASE_ADDR),
++ .irq = INTC_UART1_BIT_INDEX,
++ .uartclk = STR8100_UART_XTAL,
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ },
++ { },
++};
++
++static struct platform_device str8100_uart0_device = {
++ .name = "serial8250",
++ .id = 0,
++ .dev.platform_data = str8100_uart0_data,
++ .num_resources = 2,
++ .resource = str8100_uart0_resources,
++};
++
++static struct platform_device str8100_uart1_device = {
++ .name = "serial8250",
++ .id = 1,
++ .dev.platform_data = str8100_uart1_data,
++ .num_resources = 2,
++ .resource = str8100_uart1_resources,
++};
++#endif
++
++
++static u64 usb_dmamask = 0xffffffffULL;
++static struct resource str8100_usb11_resources[] = {
++ [0] = {
++ .start = SYSPA_USB11_CONFIG_BASE_ADDR,
++ .end = SYSPA_USB11_CONFIG_BASE_ADDR + SZ_1M - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = INTC_USB11_BIT_INDEX,
++ .end = INTC_USB11_BIT_INDEX,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device str8100_usb11_device = {
++ .name = "str8100-ohci",
++ .id = -1,
++ .dev = {
++ .dma_mask = &usb_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = str8100_usb11_resources,
++ .num_resources = ARRAY_SIZE(str8100_usb11_resources),
++};
++
++static struct resource str8100_usb20_resources[] = {
++ [0] = {
++ .start = SYSPA_USB20_CONFIG_BASE_ADDR,
++ .end = SYSPA_USB20_CONFIG_BASE_ADDR + SZ_1M - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = INTC_USB20_BIT_INDEX,
++ .end = INTC_USB20_BIT_INDEX,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device str8100_usb20_device = {
++ .name = "str8100-ehci",
++ .id = -1,
++ .dev = {
++ .dma_mask = &usb_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = str8100_usb20_resources,
++ .num_resources = ARRAY_SIZE(str8100_usb20_resources),
++};
++
++#ifdef CONFIG_SPI_STR8100
++#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
++static struct mtd_partition str8100_spi_flash_partitions[] = {
++ {
++ .name = "all",
++ .offset = CONFIG_ARMBOOT_OFFSET,
++ .size = 0x800000-CONFIG_ARMBOOT_OFFSET,
++ },{
++ .name = "ARMBOOT",
++ .offset = CONFIG_ARMBOOT_OFFSET,
++ .size = CONFIG_KERNEL_OFFSET-CONFIG_ARMBOOT_OFFSET,
++ },{
++ .name = "Linux Kernel",
++ .offset = CONFIG_KERNEL_OFFSET,
++ .size = CONFIG_ROOTFS_OFFSET-CONFIG_KERNEL_OFFSET,
++ },{
++ .name = "MTD Disk1",
++ .offset = CONFIG_ROOTFS_OFFSET,
++ .size = CONFIG_CFG_OFFSET-CONFIG_ROOTFS_OFFSET,
++ },{
++ .name = "MTD Disk2",
++ .offset = CONFIG_CFG_OFFSET,
++ .size = 0x800000-CONFIG_CFG_OFFSET,
++ }
++};
++
++static struct flash_platform_data str8100_spi_flash_data = {
++ .name = "m25p80",
++ .parts = str8100_spi_flash_partitions,
++ .nr_parts = ARRAY_SIZE(str8100_spi_flash_partitions),
++ .type = "m25p64",
++};
++
++#if defined(CONFIG_LE88221_CONTROL)
++static struct str8100_spi_dev_attr str8100_spi_le88221_attr = {
++ .spi_serial_mode = STR8100_SPI_SERIAL_MODE_MICROPROCESSOR,
++};
++#endif
++
++static struct spi_board_info str8100_spi_board_info[] = {
++ {
++ .modalias = "m25p80",
++ .chip_select = 0,
++ .max_speed_hz = 25 * 1000 * 1000,
++ .bus_num = 1,
++ .platform_data = &str8100_spi_flash_data,
++ },
++
++#if defined(CONFIG_LE88221_CONTROL)
++ {
++ .modalias = "le88221",
++ .chip_select = 1,
++ .max_speed_hz = 25 * 1000 * 1000,
++ .bus_num = 1,
++ .platform_data = NULL,
++ .controller_data = &str8100_spi_le88221_attr,
++ },
++#endif
++};
++#endif
++
++static u64 spi_dmamask = 0xffffffffUL;
++static struct resource str8100_spi_resources[] = {
++ [0] = {
++ .start = SYSPA_SPI_BASE_ADDR,
++ .end = SYSPA_SPI_BASE_ADDR + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = INTC_SPI_BIT_INDEX,
++ .end = INTC_SPI_BIT_INDEX,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device str8100_spi_master_device = {
++ .name = "str8100_spi",
++ .id = -1,
++ .dev = {
++ .dma_mask = &spi_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = str8100_spi_resources,
++ .num_resources = ARRAY_SIZE(str8100_spi_resources),
++};
++#endif // CONFIG_SPI_STR8100
++
++#ifdef DEVICE_REGISTER_MULTIPLE
++static struct platform_device *str8100_devices[] __initdata = {
++#ifndef EARLY_REGISTER_CONSOLE
++ &str8100_uart0_device,
++ &str8100_uart1_device,
++#endif
++#ifdef CONFIG_SPI_STR8100
++ &str8100_spi_master_device,
++#endif
++ &str8100_usb11_device,
++ &str8100_usb20_device
++};
++#endif
++
++static void __init str8100_fixup(struct machine_desc *desc,
++ struct tag *tags, char **cmdline, struct meminfo *mi)
++{
++ mi->nr_banks = 1;
++ mi->bank[0].start = CONFIG_SYSTEM_DRAM_BASE;
++ mi->bank[0].size = CONFIG_SYSTEM_DRAM_SIZE << 20;
++ //mi->bank[0].node = 0;
++}
++
++/* ######################################################################### */
++#ifdef CONFIG_CPU_ISPAD_ENABLE
++extern unsigned long __ispad_begin;
++#endif
++u32 PLL_clock;
++u32 CPU_clock;
++u32 AHB_clock;
++u32 APB_clock;
++EXPORT_SYMBOL(PLL_clock);
++EXPORT_SYMBOL(CPU_clock);
++EXPORT_SYMBOL(AHB_clock);
++EXPORT_SYMBOL(APB_clock);
++// This function is called just after the
++// page table and cpu have been initialized
++
++#include "asm/procinfo.h"
++#include "asm/cacheflush.h"
++#include "asm/system.h"
++void __init str8100_early_init(void)
++{
++ //printk("str8100_early_init()\n");
++
++ switch (PWRMGT_SYSTEM_CLOCK_CONTROL_REG & 0x3) {
++ case 0x0:
++ PLL_clock = 175000000;
++ break;
++ case 0x1:
++ PLL_clock = 200000000;
++ break;
++ case 0x2:
++ PLL_clock = 225000000;
++ break;
++ case 0x3:
++ PLL_clock = 250000000;
++ break;
++ }
++
++ CPU_clock = PLL_clock / (((PWRMGT_SYSTEM_CLOCK_CONTROL_REG >> 2) & 0x3) + 1);
++ AHB_clock = CPU_clock / (((PWRMGT_SYSTEM_CLOCK_CONTROL_REG >> 4) & 0x3) + 1);
++ APB_clock = AHB_clock / (((PWRMGT_SYSTEM_CLOCK_CONTROL_REG >> 8) & 0x3) + 1);
++
++ printk("PLL clock at %dMHz\n", PLL_clock / 1000000);
++ printk("CPU clock at %dMHz\n", CPU_clock / 1000000);
++ printk("AHB clock at %dMHz\n", AHB_clock / 1000000);
++ printk("APB clock at %dMHz\n", APB_clock / 1000000);
++}
++/* ######################################################################### */
++
++void __init str8100_init(void)
++{
++// printk("str8100_init()\n");
++
++#ifdef DEVICE_REGISTER_MULTIPLE
++ platform_add_devices(str8100_devices, ARRAY_SIZE(str8100_devices));
++#ifdef CONFIG_SPI_STR8100
++#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
++ spi_register_board_info(str8100_spi_board_info, ARRAY_SIZE(str8100_spi_board_info));
++#endif
++#endif // CONFIG_SPI_STR8100
++#else // DEVICE_REGISTER_MULTIPLE
++#ifndef EARLY_REGISTER_CONSOLE
++ platform_device_register(&str8100_uart0_device);
++ platform_device_register(&str8100_uart1_device);
++#endif
++#ifdef CONFIG_SPI_STR8100
++ platform_device_register(&str8100_spi_master_device);
++#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
++ spi_register_board_info(str8100_spi_board_info, ARRAY_SIZE(str8100_spi_board_info));
++#endif
++#endif
++ platform_device_register(&str8100_usb11_device);
++ platform_device_register(&str8100_usb20_device);
++#endif
++}
++
++extern void str8100_register_map_desc(struct map_desc *map, int count);
++void __init str8100_map_io(void)
++{
++// printk("str8100_map_io()\n");
++
++ iotable_init(str8100_std_desc, ARRAY_SIZE(str8100_std_desc));
++ str8100_register_map_desc(str8100_std_desc, ARRAY_SIZE(str8100_std_desc));
++#ifdef EARLY_REGISTER_CONSOLE
++ early_serial_setup(&str8100_serial_ports[0]);
++ early_serial_setup(&str8100_serial_ports[1]);
++#endif
++}
++
++extern void str8100_init_irq(void);
++extern struct sys_timer str8100_timer;
++
++MACHINE_START(STR8100, "STAR STR8100")
++ .phys_io = SYSPA_UART0_BASE_ADDR,
++ .io_pg_offst = ((SYSVA_UART0_BASE_ADDR) >> 18) & 0xfffc, // virtual, physical
++ .fixup = str8100_fixup,
++ .map_io = str8100_map_io,
++ .init_irq = str8100_init_irq,
++ .timer = &str8100_timer,
++ .boot_params = 0x0100,
++ .init_machine = str8100_init,
++MACHINE_END
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str8100/str8100_timer.c linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_timer.c
+--- linux-2.6.35.11/arch/arm/mach-str8100/str8100_timer.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str8100/str8100_timer.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,224 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/interrupt.h>
++#include <linux/time.h>
++#include <linux/init.h>
++#include <linux/timex.h>
++
++#include <mach/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/uaccess.h>
++#include <asm/mach/irq.h>
++#include <asm/mach/time.h>
++
++#if 1
++// for timer clock < 100MHz
++#define uSECS_PER_TICK (1000000 / APB_clock)
++#define TICKS2USECS(x) ((x) * uSECS_PER_TICK)
++#else
++// for timer clock >= 100MHz
++#define TICKS_PER_uSEC (APB_clock / 1000000)
++#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
++#endif
++
++extern u32 APB_clock;
++static u32 timer_counter_value;
++
++static inline unsigned int str8100_read_timer_counter(void)
++{
++ return TIMER1_COUNTER_REG;
++}
++
++static inline unsigned int str8100_read_timer_interrupt_status(void)
++{
++ return TIMER1_TIMER2_INTERRUPT_STATUS_REG;
++}
++
++static inline void str8100_clear_timer_interrupt_status(unsigned int irq)
++{
++ TIMER1_TIMER2_INTERRUPT_STATUS_REG &= ~(1 << TIMER1_OVERFLOW_INTERRUPT_BIT_INDEX);
++}
++
++static void str8100_setup_timer(unsigned int counter_value)
++{
++ unsigned long control_value;
++ unsigned long mask_value;
++
++ control_value = TIMER1_TIMER2_CONTROL_REG;
++ mask_value = TIMER1_TIMER2_INTERRUPT_MASK_REG;
++
++ TIMER1_COUNTER_REG = counter_value;
++ TIMER1_AUTO_RELOAD_VALUE_REG = counter_value;
++ TIMER1_MATCH_VALUE1_REG = 0;
++ TIMER1_MATCH_VALUE2_REG = 0;
++
++ // Clock Source: PCLK
++ control_value &= ~(1 << TIMER1_CLOCK_SOURCE_BIT_INDEX);
++
++ // Down Count Mode
++ control_value |= (1 << TIMER1_UP_DOWN_COUNT_BIT_INDEX);
++
++ // un-mask overflow, match2 and match1 interrupt sources
++ mask_value &= ~(0x7);
++
++ // mask match2 and match1 interrupt sources
++ mask_value |= 0x03;
++
++ TIMER1_TIMER2_CONTROL_REG = control_value;
++ TIMER1_TIMER2_INTERRUPT_MASK_REG = mask_value;
++}
++
++static void str8100_timer_enable(void)
++{
++ unsigned long control_value;
++
++ control_value = TIMER1_TIMER2_CONTROL_REG;
++
++ // enable overflow mode
++ control_value |= (1 << TIMER1_OVERFLOW_ENABLE_BIT_INDEX);
++
++ // enable the timer
++ control_value |= (1 << TIMER1_ENABLE_BIT_INDEX);
++
++ TIMER1_TIMER2_CONTROL_REG = control_value;
++}
++
++static void str8100_timer_disable(void)
++{
++ unsigned long control_value;
++
++ control_value = TIMER1_TIMER2_CONTROL_REG;
++
++ // disable overflow mode
++ control_value &= ~(1 << TIMER1_OVERFLOW_ENABLE_BIT_INDEX);
++
++ // disable the timer
++ control_value &= ~(1 << TIMER1_ENABLE_BIT_INDEX);
++
++ TIMER1_TIMER2_CONTROL_REG = control_value;
++}
++
++/*
++ * Returns number of us since last clock interrupt. Note that interrupts
++ * will have been disabled by do_gettimeoffset()
++ */
++static unsigned long str8100_gettimeoffset(void)
++{
++ unsigned long ticks1, ticks2;
++ unsigned long interrupt_status;
++
++ /*
++ * Get the current number of ticks. Note that there is a race
++ * condition between us reading the timer and checking for
++ * an interrupt. We get around this by ensuring that the
++ * counter has not reloaded between our two reads.
++ */
++ ticks2 = str8100_read_timer_counter();
++ do {
++ ticks1 = ticks2;
++ interrupt_status = str8100_read_timer_interrupt_status();
++ ticks2 = str8100_read_timer_counter();
++ } while (ticks2 > ticks1);
++
++ /*
++ * Number of ticks since last interrupt
++ */
++ ticks1 = timer_counter_value - ticks2;
++
++ /*
++ * Interrupt pending? If so, we've reloaded once already.
++ */
++ if (interrupt_status) {
++ ticks1 += timer_counter_value;
++ }
++
++ /*
++ * Convert the ticks to usecs
++ */
++ return TICKS2USECS(ticks1);
++}
++
++/*
++ * IRQ handler for the timer
++ */
++static irqreturn_t
++str8100_timer_interrupt(int irq, void *dev_id /*, struct pt_regs *regs*/)
++{
++
++#ifndef CONFIG_VIC_INTERRUPT
++ str8100_clear_timer_interrupt_status((unsigned int)irq);
++#endif
++ /* scot.patch
++ timer_tick(regs);
++ */
++ timer_tick();
++
++ return IRQ_HANDLED;
++}
++
++static struct irqaction str8100_timer_irq = {
++ .name = "STR8100 Timer Tick",
++/* scott.patch
++ .flags = SA_INTERRUPT | SA_TIMER,
++*/
++ .flags = IRQF_DISABLED | IRQF_TIMER,
++ .handler = str8100_timer_interrupt,
++};
++
++/*
++ * Set up timer interrupt, and return the current time in seconds.
++ */
++
++
++static void __init str8100_timer_init(void)
++{
++ /*
++ * prepare timer-related values
++ */
++ timer_counter_value = APB_clock / HZ;
++
++ /*
++ * setup timer-related values
++ */
++ str8100_setup_timer(timer_counter_value);
++
++
++ /*
++ * Make irqs happen for the system timer
++ */
++ setup_irq(INTC_TIMER1_BIT_INDEX, &str8100_timer_irq);
++
++ str8100_timer_enable();
++
++
++}
++
++struct sys_timer str8100_timer = {
++ .init = str8100_timer_init,
++#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
++ .offset = str8100_gettimeoffset,
++#endif
++};
+diff -rupN linux-2.6.35.11/arch/arm/mach-str9100/Kconfig linux-2.6.35.11-ts7500/arch/arm/mach-str9100/Kconfig
+--- linux-2.6.35.11/arch/arm/mach-str9100/Kconfig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str9100/Kconfig 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,99 @@
++if ARCH_STR9100
++
++menu "STR9100 Options"
++
++config CONSOLE_BAUD_RATE
++ int "Console Baud Rate"
++ default 115200
++ help
++ set the console baudrate
++
++config CPU_ISPAD_ENABLE
++ bool "Enable I-Scratch Pad Support"
++ default y
++ help
++ enable I-Scratch Pad support
++
++choice
++ prompt "DRAM SIZE"
++ default STR9100_DRAM_16M
++
++config STR9100_DRAM_16M
++ bool "16MBytes"
++
++config STR9100_DRAM_32M
++ bool "32MBytes"
++
++config STR9100_DRAM_64M
++ bool "64MBytes"
++
++endchoice
++
++if PCI
++choice
++ prompt "PCI Frequency"
++ default STAR9100_PCI33M
++
++config STR9100_PCI33M
++ bool "PCI_33Mhz"
++
++config STR9100_PCI66M
++ bool "PCI_66Mhz"
++
++endchoice
++endif
++
++config STR9100_RTC
++ bool "STR9100 Real Time Clock Support"
++
++config STR9100_GPIO
++ bool "STR9100 GPIO Support"
++
++config STR9100_GPIO_INTERRUPT
++ bool "Interrupt Library Support"
++ depends on STR9100_GPIO
++
++config STR9100_INFO
++ bool "STR9100 Infomation at /proc/str9100/info"
++
++comment "Flash MAP"
++config STR9100_FLASH_PART
++ bool "STR9100 flash partition setting"
++
++if STR9100_FLASH_PART
++ config ARMBOOT_OFFSET
++ hex "ARMBOOT OFFSET"
++ default 0x0
++ help
++ The armboot start offset in flash layout
++
++ config KERNEL_OFFSET
++ hex "KERNEL OFFSET"
++ default 0x40000
++ help
++ The kernel start offset in flash layout
++
++ config ROOTFS_OFFSET
++ hex "ROOTFS OFFSET"
++ default 0x140000
++ help
++ The rootfs start offset in flash layout
++
++ config CFG_OFFSET
++ hex "CFG OFFSET"
++ default 0x7f0000
++ help
++ The cfg start offset in flash layout
++endif
++
++comment "Third Party Support"
++
++config STR9100_EWC_SUPPORT
++ bool "EWC(802.11N) Support"
++
++config SWITCH_IOCTL
++ bool "SUPPORT SWITCH IOCTL"
++
++endmenu
++
++endif
+diff -rupN linux-2.6.35.11/arch/arm/mach-str9100/Makefile linux-2.6.35.11-ts7500/arch/arm/mach-str9100/Makefile
+--- linux-2.6.35.11/arch/arm/mach-str9100/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str9100/Makefile 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,14 @@
++#
++# Makefile for the linux kernel.
++#
++
++# Object file lists.
++
++obj-y := str9100_debug.o str9100_setup.o str9100_timer.o str9100_intc.o str9100_counter.o str9100_misc.o
++obj-m :=
++obj-n :=
++obj- :=
++
++obj-$(CONFIG_PCI) += str9100_pci.o
++obj-$(CONFIG_STR9100_GPIO) += str9100_gpio.o
++obj-$(CONFIG_STR9100_RTC) += str9100_rtc.o
+\ No newline at end of file
+diff -rupN linux-2.6.35.11/arch/arm/mach-str9100/Makefile.boot linux-2.6.35.11-ts7500/arch/arm/mach-str9100/Makefile.boot
+--- linux-2.6.35.11/arch/arm/mach-str9100/Makefile.boot 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str9100/Makefile.boot 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,10 @@
++# Note: the following conditions must always be true:
++# ZRELADDR == virt_to_phys(TEXTADDR)
++# PARAMS_PHYS must be within 4MB of ZRELADDR
++# INITRD_PHYS must be in RAM
++
++ zreladdr-y := 0x00008000
++params_phys-y := 0x00000100
++initrd_phys-y := 0x00C00000
++kernel_phys-y := 0x00400000
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str9100/str9100_counter.c linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_counter.c
+--- linux-2.6.35.11/arch/arm/mach-str9100/str9100_counter.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_counter.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,214 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/interrupt.h>
++#include <linux/time.h>
++#include <linux/init.h>
++#include <linux/timex.h>
++#include <linux/proc_fs.h>
++#include <linux/module.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/uaccess.h>
++#include <asm/mach/irq.h>
++#include <asm/mach/time.h>
++
++u64 volatile str9100_counter_tick;
++EXPORT_SYMBOL(str9100_counter_tick);
++
++static struct proc_dir_entry *str9100_counter_proc_entry;
++
++#if 0
++// this is defined in include/asm/arch-str9100/system.h
++u64 str9100_read_counter(void)
++{
++ return (str9100_counter_tick + TIMER2_COUNTER_REG);
++}
++EXPORT_SYMBOL(str9100_read_counter);
++#endif
++
++static int match1=0;
++static int match2=0;
++static void str9100_setup_counter(void)
++{
++ unsigned long control_value;
++ unsigned long mask_value;
++ unsigned long val;
++
++ control_value = TIMER_CONTROL_REG;
++ mask_value = TIMER_INTERRUPT_MASK_REG;
++
++ TIMER2_COUNTER_REG = 0;
++ TIMER2_AUTO_RELOAD_VALUE_REG = 0;
++ TIMER2_MATCH_VALUE1_REG = match1;
++ TIMER2_MATCH_VALUE2_REG = match2;
++
++ // Clock Source: PCLK
++ control_value &= ~(1 << TIMER2_CLOCK_SOURCE_BIT_INDEX);
++
++ // UP Count Mode
++ control_value &= ~(1 << TIMER2_UP_DOWN_COUNT_BIT_INDEX);
++
++ // un-mask match1, match2, and overflow interrupt sources
++ mask_value &= ~(0x7 << 3);
++
++ // mask match1, match2 interrupt sources
++ //mask_value |= (0x3 << 3);
++ val=0;
++ if(!match1) val|=0x1;
++ if(!match2) val|=0x2;
++ mask_value |= (val<< 3);
++
++ TIMER_CONTROL_REG = control_value;
++ TIMER_INTERRUPT_MASK_REG = mask_value;
++}
++
++static void str9100_counter_enable(void)
++{
++ unsigned long control_value;
++
++ control_value = TIMER_CONTROL_REG;
++
++ // enable overflow mode
++ control_value |= (1 << TIMER2_OVERFLOW_ENABLE_BIT_INDEX);
++
++ // enable the timer
++ control_value |= (1 << TIMER2_ENABLE_BIT_INDEX);
++
++ TIMER_CONTROL_REG = control_value;
++}
++
++static void str9100_counter_disable(void)
++{
++ unsigned long control_value;
++
++ control_value = TIMER_CONTROL_REG;
++
++ // enable overflow mode
++ control_value &= ~(1 << TIMER2_OVERFLOW_ENABLE_BIT_INDEX);
++
++ // enable the timer
++ control_value &= ~(1 << TIMER2_ENABLE_BIT_INDEX);
++
++ TIMER_CONTROL_REG = control_value;
++}
++
++/*
++ * IRQ handler for the timer
++ */
++static irqreturn_t
++str9100_counter_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++ // clear counter interrrupt status
++ TIMER_INTERRUPT_STATUS_REG &= ~(1 << TIMER2_OVERFLOW_INTERRUPT_BIT_INDEX);
++ str9100_counter_tick += (1ULL << 32);
++ if(match1){
++ TIMER2_MATCH_VALUE1_REG=TIMER2_COUNTER_REG+match1;
++ TIMER_INTERRUPT_MASK_REG |= (0x1<<3);
++ }
++ if(match2){
++ TIMER2_MATCH_VALUE2_REG=TIMER2_COUNTER_REG+match2;
++ TIMER_INTERRUPT_MASK_REG |= (0x2<<3);
++ }
++ return IRQ_HANDLED;
++}
++
++static struct irqaction str9100_counter_irq = {
++ .name = "STR9100 Counter Tick",
++ /* scott.patch */
++ .flags = IRQF_DISABLED | IRQF_TIMER,
++ .handler = str9100_counter_interrupt,
++};
++
++static int str9100_counter_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
++{
++ return sprintf(page, "str9100_counter_tick: %llu\n", str9100_counter_tick + TIMER2_COUNTER_REG);
++}
++static int
++str9100_counter_write_proc(struct file *file, const char __user *buffer,
++ unsigned long count, void *data)
++{
++ char *str;
++ char *cmd;
++
++ if (count > 0) {
++ str = (char *)buffer,
++ cmd = strsep(&str, "\t \n");
++ if (!cmd) goto err_out;
++ if (strcmp(cmd, "match1") == 0) {
++ u32 addr;
++ u32 vir_addr;
++ char *arg = strsep(&str, "\t \n");
++ if (!arg) goto err_out;
++ addr = simple_strtoul(arg, &arg, 10);
++ match1=addr;
++
++ } else if (strcmp(cmd, "match2") == 0) {
++ u32 addr;
++ u32 vir_addr;
++ char *arg = strsep(&str, "\t \n");
++ if (!arg) goto err_out;
++ addr = simple_strtoul(arg, &arg, 10);
++ match2=addr;
++
++
++ } else {
++ goto err_out;
++ }
++ }
++ if(match1){
++ TIMER2_MATCH_VALUE1_REG=TIMER2_COUNTER_REG+match1;
++ TIMER_INTERRUPT_MASK_REG |= (0x1<<3);
++ }
++ if(match2){
++ TIMER2_MATCH_VALUE2_REG=TIMER2_COUNTER_REG+match2;
++ TIMER_INTERRUPT_MASK_REG |= (0x2<<3);
++ }
++
++ return count;
++
++err_out:
++ return -EFAULT;
++}
++
++/*
++ * Set up timer interrupt, and return the current time in seconds.
++ */
++int __init str9100_counter_setup(void)
++{
++ str9100_setup_counter();
++ setup_irq(INTC_TIMER2_BIT_INDEX, &str9100_counter_irq);
++ str9100_counter_enable();
++ str9100_counter_proc_entry = create_proc_entry("str9100/counter", S_IFREG | S_IRUGO, NULL);
++ if (str9100_counter_proc_entry) {
++ str9100_counter_proc_entry->read_proc = str9100_counter_read_proc;
++ str9100_counter_proc_entry->write_proc = str9100_counter_write_proc;
++
++ }
++
++ return 0;
++}
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str9100/str9100_debug.c linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_debug.c
+--- linux-2.6.35.11/arch/arm/mach-str9100/str9100_debug.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_debug.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,48 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/types.h>
++#include <asm/hardware.h>
++
++void debug_puts(const char *s)
++{
++ while (*s) {
++ volatile unsigned int status = 0;
++ do {
++ status = _UART_LSR;
++ } while (!((status & THR_EMPTY) == THR_EMPTY));
++
++ _UART_THR = *s;
++
++ if (*s == '\n') {
++ do {
++ status = _UART_LSR;
++ } while (!((status & THR_EMPTY) == THR_EMPTY));
++
++ _UART_THR = '\r';
++
++ }
++ s++;
++ }
++}
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str9100/str9100_gpio.c linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_gpio.c
+--- linux-2.6.35.11/arch/arm/mach-str9100/str9100_gpio.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_gpio.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,532 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/miscdevice.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/sched.h>
++#include <linux/proc_fs.h>
++#include <linux/interrupt.h>
++
++#include <asm/irq.h>
++#include <asm/uaccess.h>
++#include <asm/arch/star_gpio.h>
++
++#include <linux/str9100/str9100_gpio.h>
++
++#ifdef CONFIG_STR9100_GPIO_INTERRUPT
++#define MAX_GPIO_LINE 21
++void (*gpio_isr[MAX_GPIO_LINE])(int i);
++#endif
++
++/*
++ * Read GPIO input data from register
++ */
++int str9100_gpio_in(volatile __u32 *data)
++{
++ *data = GPIO_DATA_IN_REG;
++ return 0;
++}
++
++/*
++ * Write data to GPIO output register
++ */
++int str9100_gpio_out(__u32 data)
++{
++ GPIO_DATA_OUT_REG = data;
++ return 0;
++}
++
++/*
++ * Read GPIO direction Register
++ */
++int str9100_gpio_read_direction(volatile __u32 *data)
++{
++ *data = GPIO_PIN_DIR_REG;
++ return 0;
++}
++
++/*
++ * Write GPIO direction Register
++ */
++int str9100_gpio_write_direction(__u32 data)
++{
++ GPIO_PIN_DIR_REG = data;
++ return 0;
++}
++
++/*
++ * Write GPIO set Register
++ */
++int str9100_gpio_dataset(__u32 data)
++{
++ GPIO_DATA_SET_REG = data;
++ return 0;
++}
++
++/*
++ * Write GPIO clear Register
++ */
++int str9100_gpio_dataclear(__u32 data)
++{
++ GPIO_DATA_CLEAR_REG = data;
++ return 0;
++}
++
++/* Read GPIO Data, but only one bit */
++int str9100_gpio_in_bit(volatile __u32 *data, int bit)
++{
++ u32 temp;
++ if (bit >= 0 && bit <= 20) {
++ str9100_gpio_in(&temp);
++ *data = ((temp >> bit)&0x1);
++ }
++ return 0;
++}
++
++/* Write GPIO Data, but only one bit */
++int str9100_gpio_out_bit(__u32 data, int bit)
++{
++ u32 temp;
++ if (bit >= 0 && bit <= 20) {
++ str9100_gpio_in(&temp);
++ temp &= ~(1 <<bit);
++ temp |= (data &0x1)<< bit;
++ str9100_gpio_out(temp);
++ }
++ return 0;
++
++}
++
++int str9100_gpio_read_direction_bit(volatile __u32 *data, int bit)
++{
++ u32 temp;
++ if (bit >= 0 && bit <= 20) {
++ str9100_gpio_read_direction(&temp);
++ *data = ((temp >> bit)&0x1);
++ }
++ return 0;
++}
++
++int str9100_gpio_write_direction_bit(__u32 data, int bit)
++{
++ u32 temp;
++ if (bit >= 0 && bit <= 20) {
++ str9100_gpio_read_direction(&temp);
++ temp &= ~(1 <<bit);
++ temp |= (data &0x1)<< bit;
++ str9100_gpio_write_direction(temp);
++ }
++ return 0;
++}
++
++int str9100_gpio_dataset_bit(__u32 data, int bit)
++{
++ u32 temp=0;
++ if (bit >= 0 && bit <= 20) {
++ temp |= (data &0x1)<< bit;
++ str9100_gpio_dataset(temp);
++ }
++ return 0;
++}
++
++int str9100_gpio_dataclear_bit(__u32 data, int bit)
++{
++ u32 temp=0;
++ if (bit >= 0 && bit <= 20) {
++ temp |= (data &0x1)<< bit;
++ str9100_gpio_dataclear(temp);
++ }
++ return 0;
++}
++
++#define GEN_GPIO_WRITE_SCRIPT(regname)\
++int str9100_gpio_write_##regname##_bit(volatile __u32 data,int bit) \
++{ \
++ u32 temp=0; \
++ if (bit >= 0 && bit <= 20) { \
++ temp |= ((data &0x1)<< bit); \
++ str9100_gpio_write_##regname(temp); \
++ } \
++ return 0; \
++}
++//EXPORT_SYMBOL(str9100_gpio_write_##regname_bit);
++
++#define GEN_GPIO_READ_SCRIPT(regname) \
++int str9100_gpio_read_##regname##_bit(volatile __u32 *data,int bit) \
++{ \
++ u32 temp; \
++ if (bit >= 0 && bit <= 20) { \
++ str9100_gpio_read_##regname(&temp); \
++ *data = ((temp >> bit)&0x1); \
++ } \
++ return 0; \
++}
++//EXPORT_SYMBOL(str9100_gpio_read_##regname_bit);
++
++#ifdef CONFIG_STR9100_GPIO_INTERRUPT
++int str9100_gpio_read_intrenable(volatile __u32 *data)
++{
++ *data = GPIO_INTERRUPT_ENABLE_REG;
++ return 0;
++}
++GEN_GPIO_READ_SCRIPT(intrenable);
++
++int str9100_gpio_write_intrenable(__u32 data)
++{
++ GPIO_INTERRUPT_ENABLE_REG = data;
++ return 0;
++}
++GEN_GPIO_WRITE_SCRIPT(intrenable);
++
++int str9100_gpio_read_intrrawstate(volatile __u32 *data)
++{
++ *data = GPIO_INTERRUPT_RAW_STATE_REG;
++ return 0;
++}
++GEN_GPIO_READ_SCRIPT(intrrawstate);
++
++int str9100_gpio_read_intrmaskedstatus(volatile __u32 *data)
++{
++ *data = GPIO_INTERRUPT_MASKED_STATE_REG;
++ return 0;
++}
++GEN_GPIO_READ_SCRIPT(intrmaskedstatus);
++
++int str9100_gpio_read_intrmask(volatile __u32 *data)
++{
++ *data = GPIO_INTERRUPT_MASK_REG;
++ return 0;
++}
++GEN_GPIO_READ_SCRIPT(intrmask);
++
++int str9100_gpio_write_intrmask(__u32 data)
++{
++ GPIO_INTERRUPT_MASK_REG = data;
++ return 0;
++}
++GEN_GPIO_WRITE_SCRIPT(intrmask);
++
++int str9100_gpio_read_intrclear(volatile __u32 *data)
++{
++ *data = GPIO_INTERRUPT_CLEAR_REG;
++ return 0;
++}
++GEN_GPIO_READ_SCRIPT(intrclear);
++
++int str9100_gpio_write_intrclear(__u32 data)
++{
++ GPIO_INTERRUPT_CLEAR_REG = data;
++ return 0;
++}
++GEN_GPIO_WRITE_SCRIPT(intrclear);
++
++int str9100_gpio_read_intrtrigger(volatile __u32 *data)
++{
++ *data = GPIO_INTERRUPT_TRIGGER_REG;
++ return 0;
++}
++GEN_GPIO_READ_SCRIPT(intrtrigger);
++
++int str9100_gpio_write_intrtrigger(__u32 data)
++{
++ GPIO_INTERRUPT_TRIGGER_REG = data;
++ return 0;
++}
++GEN_GPIO_WRITE_SCRIPT(intrtrigger);
++
++int str9100_gpio_read_intrboth(volatile __u32 *data)
++{
++ *data = GPIO_INTERRUPT_BOTH_REG;
++ return 0;
++}
++GEN_GPIO_READ_SCRIPT(intrboth);
++
++int str9100_gpio_write_intrboth(__u32 data)
++{
++ GPIO_INTERRUPT_BOTH_REG = data;
++ return 0;
++}
++GEN_GPIO_WRITE_SCRIPT(intrboth);
++
++int str9100_gpio_read_intrriseneg(volatile __u32 *data)
++{
++ *data = GPIO_INTERRUPT_RISE_NEG_REG;
++ return 0;
++}
++GEN_GPIO_READ_SCRIPT(intrriseneg);
++
++int str9100_gpio_write_intrriseneg(__u32 data)
++{
++ GPIO_INTERRUPT_RISE_NEG_REG = data;
++ return 0;
++}
++GEN_GPIO_WRITE_SCRIPT(intrriseneg);
++
++#endif
++
++#if 0
++EXPORT_SYMBOL(str9100_gpio_in);
++EXPORT_SYMBOL(str9100_gpio_out);
++EXPORT_SYMBOL(str9100_gpio_in_bit);
++EXPORT_SYMBOL(str9100_gpio_out_bit);
++EXPORT_SYMBOL(str9100_gpio_read_direction);
++EXPORT_SYMBOL(str9100_gpio_write_direction);
++EXPORT_SYMBOL(str9100_gpio_read_direction_bit);
++EXPORT_SYMBOL(str9100_gpio_write_direction_bit);
++EXPORT_SYMBOL(str9100_gpio_dataset);
++EXPORT_SYMBOL(str9100_gpio_dataclear);
++EXPORT_SYMBOL(str9100_gpio_dataset_bit);
++EXPORT_SYMBOL(str9100_gpio_dataclear_bit);
++
++#ifdef CONFIG_STR9100_GPIO_INTERRUPT
++EXPORT_SYMBOL(str9100_gpio_read_intrenable);
++EXPORT_SYMBOL(str9100_gpio_write_intrenable);
++EXPORT_SYMBOL(str9100_gpio_read_intrrawstate);
++EXPORT_SYMBOL(str9100_gpio_read_intrmaskedstatus);
++EXPORT_SYMBOL(str9100_gpio_read_intrmask);
++EXPORT_SYMBOL(str9100_gpio_write_intrmask);
++EXPORT_SYMBOL(str9100_gpio_read_intrclear);
++EXPORT_SYMBOL(str9100_gpio_write_intrclear);
++EXPORT_SYMBOL(str9100_gpio_read_intrtrigger);
++EXPORT_SYMBOL(str9100_gpio_write_intrtrigger);
++EXPORT_SYMBOL(str9100_gpio_read_intrboth);
++EXPORT_SYMBOL(str9100_gpio_write_intrboth);
++EXPORT_SYMBOL(str9100_gpio_read_intrriseneg);
++EXPORT_SYMBOL(str9100_gpio_write_intrriseneg);
++#endif
++#endif
++
++static int str9100_gpio_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
++{
++ u32 temp;
++ int num=0;
++
++ str9100_gpio_in(&temp);
++ num += sprintf(page+num, "GPIO IN : %08x \n", temp);
++
++ str9100_gpio_read_direction(&temp);
++ num += sprintf(page+num, "GPIO Direction : %08x \n", temp);
++
++#ifdef CONFIG_STR9100_GPIO_INTERRUPT
++ str9100_gpio_read_intrenable(&temp);
++ num += sprintf(page+num, "GPIO Interrupt Enable : %08x \n", temp);
++
++ str9100_gpio_read_intrrawstate(&temp);
++ num += sprintf(page+num, "GPIO Interrupt Raw : %08x \n", temp);
++
++ str9100_gpio_read_intrtrigger(&temp);
++ num += sprintf(page+num, "GPIO Interrupt Trigger : %08x \n", temp);
++
++ str9100_gpio_read_intrboth(&temp);
++ num += sprintf(page+num, "GPIO Interrupt Both : %08x \n", temp);
++
++ str9100_gpio_read_intrriseneg(&temp);
++ num += sprintf(page+num, "GPIO Interrupt RiseNeg : %08x \n", temp);
++
++ str9100_gpio_read_intrmask(&temp);
++ num += sprintf(page+num, "GPIO Interrupt MASKED : %08x \n", temp);
++
++ str9100_gpio_read_intrmaskedstatus(&temp);
++ num += sprintf(page+num, "GPIO Interrupt MASKEDST: %08x \n", temp);
++#endif
++
++ return num;
++}
++
++#ifdef CONFIG_STR9100_GPIO_INTERRUPT
++static void str9100_gpio_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs)
++{
++ int i;
++ u32 gpio_intr;
++
++ // Clean System irq status
++ INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++ INTC_INTERRUPT_MASK_REG |= (0x1 << INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++
++ str9100_gpio_read_intrrawstate(&gpio_intr);
++ //printk("GPIO INTERRUPT : %08x \n",gpio_intr);
++
++ for (i = 0; i < MAX_GPIO_LINE; i++) {
++ if ((gpio_intr &0x1) == 0x1) {
++ if (gpio_isr[i] != NULL) {
++ gpio_isr[i](i);
++ }
++ }
++ gpio_intr = gpio_intr >> 1;
++ }
++ /* Clear All Interrupt Status */
++ str9100_gpio_write_intrclear(0x1FFFFF);
++ /* Unmask Intc Interrupt Status */
++ INTC_INTERRUPT_MASK_REG &= ~(0x1 << INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++}
++
++/*
++ * Setup GPIO for Edge Triggle Interrupt mode
++ */
++void str9100_gpio_set_edgeintr(void (*funcptr)(int),int trig_both,int trig_rising, int gpio_pin)
++{
++ u32 intrtmp;
++
++ if (gpio_pin >= 0 && gpio_pin < MAX_GPIO_LINE) {
++ str9100_gpio_write_direction_bit(PIN_INPUT,gpio_pin);
++
++ /* Set Triggle Level */
++ str9100_gpio_read_intrtrigger(&intrtmp);
++ intrtmp &= ~(0x1 << gpio_pin);
++ intrtmp |= (PIN_TRIG_EDGE << gpio_pin);
++ str9100_gpio_write_intrtrigger(intrtmp);
++
++ /* Set Triggle Both */
++ str9100_gpio_read_intrboth(&intrtmp);
++ intrtmp &= ~(0x1 << gpio_pin);
++ intrtmp |= (trig_both << gpio_pin);
++ str9100_gpio_write_intrboth(intrtmp);
++
++ /* Set Triggle Rising/Falling */
++ str9100_gpio_read_intrriseneg(&intrtmp);
++ intrtmp &= ~(0x1 << gpio_pin);
++ intrtmp |= (trig_rising << gpio_pin);
++ str9100_gpio_write_intrriseneg(intrtmp);
++
++ gpio_isr[gpio_pin] = funcptr;
++
++ // Enable Interrupt
++ str9100_gpio_read_intrenable(&intrtmp);
++ intrtmp |= (0x1 << gpio_pin);
++ str9100_gpio_write_intrenable(intrtmp);
++ }
++}
++/*
++ * Clear GPIO Triggle Interrupt
++ */
++void str9100_gpio_clear_intr(int gpio_pin)
++{
++ u32 intrtmp;
++ if (gpio_pin >= 0 && gpio_pin < MAX_GPIO_LINE) {
++ gpio_isr[gpio_pin] = NULL;
++ // Disable Interrupt
++ str9100_gpio_read_intrenable(&intrtmp);
++ intrtmp &= ~( 0x1 << gpio_pin);
++ str9100_gpio_write_intrenable(intrtmp);
++ }
++}
++
++/*
++ * Setup GPIO for LEVEL Triggle Interrupt mode
++ */
++void str9100_gpio_set_levelintr(void (*funcptr)(int),int trig_level, int gpio_pin)
++{
++ u32 intrtmp;
++ if (gpio_pin >= 0 && gpio_pin < MAX_GPIO_LINE) {
++ str9100_gpio_write_direction_bit(PIN_INPUT,gpio_pin);
++ /* Set Triggle Level */
++ str9100_gpio_read_intrtrigger(&intrtmp);
++ intrtmp &= ~(0x1 << gpio_pin);
++ intrtmp |= (PIN_TRIG_LEVEL << gpio_pin);
++ str9100_gpio_write_intrtrigger(intrtmp);
++
++ /* Set Triggle High/Low */
++ str9100_gpio_read_intrriseneg(&intrtmp);
++ intrtmp &= ~(0x1 << gpio_pin);
++ intrtmp |= (trig_level << gpio_pin);
++ str9100_gpio_write_intrriseneg(intrtmp);
++
++ gpio_isr[gpio_pin] = funcptr;
++
++ // Enable Interrupt
++ str9100_gpio_read_intrenable(&intrtmp);
++ intrtmp |= (0x1 << gpio_pin);
++ str9100_gpio_write_intrenable(intrtmp);
++ }
++}
++EXPORT_SYMBOL(str9100_gpio_set_edgeintr);
++EXPORT_SYMBOL(str9100_gpio_clear_intr);
++EXPORT_SYMBOL(str9100_gpio_set_levelintr);
++
++/*
++ * Display GPIO information at /proc/str9100/gpio
++ */
++
++#ifdef STR9100_GPIO_INTERRUPT_TEST
++void str9100_gpio_intr_test(int i)
++{
++ printk("GPIO Interrupt Service Single Active : %d \n",i);
++}
++#endif
++
++#endif
++static struct proc_dir_entry *proc_str9100_gpio;
++int __init str9100_gpio_init(void)
++{
++#ifdef CONFIG_STR9100_GPIO_INTERRUPT
++ u32 i, ret;
++#endif
++#ifdef STR9100_GPIO_INTERRUPT_TEST
++ /* test script */
++ u32 temp;
++ str9100_gpio_read_direction(&temp);
++ printk("direction: %08X\n",temp);
++ str9100_gpio_write_direction_bit(PIN_OUTPUT,15);
++ str9100_gpio_read_direction(&temp);
++ printk("direction: %08X\n",temp);
++ str9100_gpio_in(&temp);
++ printk("data: %08X\n",temp);
++#endif
++
++ proc_str9100_gpio = create_proc_read_entry("str9100/gpio", 0, NULL, str9100_gpio_proc, NULL) ;
++
++#ifdef CONFIG_STR9100_GPIO_INTERRUPT
++ for (i = 0; i < MAX_GPIO_LINE; i++) {
++ gpio_isr[i] = NULL;
++ }
++ /* Clear All Interrupt Status */
++ str9100_gpio_write_intrclear(0x1FFFFF);
++ str9100_set_interrupt_trigger(INTC_GPIO_EXTERNAL_INT_BIT_INDEX, INTC_EDGE_TRIGGER, INTC_RISING_EDGE);
++ ret = request_irq(INTC_GPIO_EXTERNAL_INT_BIT_INDEX, str9100_gpio_irq_handler, 0, "str9100_gpio", 0);
++ if (ret < 0) {
++ printk("request_irq fail : %d \n", ret);
++ return 0;
++ } else {
++ printk("GPIO interrupt handler install ok. \n");
++ }
++#endif
++#ifdef STR9100_GPIO_INTERRUPT_TEST
++ str9100_gpio_set_edgeintr(&str9100_gpio_intr_test,PIN_TRIG_SINGLE,PIN_TRIG_RISING,12);
++#endif
++
++ return 0;
++}
++
++void __exit str9100_gpio_exit(void)
++{
++ free_irq(INTC_GPIO_EXTERNAL_INT_BIT_INDEX,0);
++}
++
++module_init(str9100_gpio_init);
++module_exit(str9100_gpio_exit);
++
++MODULE_LICENSE("GPL");
+diff -rupN linux-2.6.35.11/arch/arm/mach-str9100/str9100_intc.c linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_intc.c
+--- linux-2.6.35.11/arch/arm/mach-str9100/str9100_intc.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_intc.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,193 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/module.h>
++
++#include <asm/hardware.h>
++#include <asm/mach/irq.h>
++#include <asm/irq.h>
++
++#define INTC_TRIGGER_UNKNOWN -1
++
++typedef struct
++{
++ int mode;
++ int level;
++} intc_trigger_t;
++
++static intc_trigger_t intc_trigger_table[] =
++{
++ { INTC_EDGE_TRIGGER, INTC_RISING_EDGE }, // 0
++ { INTC_EDGE_TRIGGER, INTC_RISING_EDGE }, // 1
++ { INTC_EDGE_TRIGGER, INTC_FALLING_EDGE }, // 2
++ { INTC_EDGE_TRIGGER, INTC_RISING_EDGE }, // 3
++ { INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN }, // 4
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW }, // 5
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW }, // 6
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH }, // 7
++ { INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN }, // 8
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH }, // 9
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH }, // 10
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH }, // 11
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH }, // 12
++ { INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN }, // 13
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH }, // 14
++ { INTC_EDGE_TRIGGER, INTC_FALLING_EDGE }, // 15
++ { INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN }, // 16
++ { INTC_TRIGGER_UNKNOWN, INTC_TRIGGER_UNKNOWN }, // 17
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH }, // 18
++ { INTC_EDGE_TRIGGER, INTC_RISING_EDGE }, // 19
++ { INTC_EDGE_TRIGGER, INTC_RISING_EDGE }, // 20
++ { INTC_EDGE_TRIGGER, INTC_RISING_EDGE }, // 21
++ { INTC_EDGE_TRIGGER, INTC_RISING_EDGE }, // 22
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW }, // 23
++ { INTC_LEVEL_TRIGGER, INTC_ACTIVE_LOW }, // 24
++};
++
++/*
++ * Configure interrupt trigger mode to be level trigger or edge trigger
++ */
++static inline void str9100_set_irq_mode(unsigned int irq, unsigned int mode)
++{
++ unsigned int val;
++
++ if (irq < 0 || irq > NR_IRQS) {
++ return;
++ }
++
++ if ((mode != INTC_LEVEL_TRIGGER) &&
++ (mode != INTC_EDGE_TRIGGER)) {
++ return;
++ }
++
++ val = INTC_INTERRUPT_TRIGGER_MODE_REG;
++
++ if (mode == INTC_LEVEL_TRIGGER) {
++ if (val & (1UL << irq)) {
++ val &= ~(1UL << irq);
++ INTC_INTERRUPT_TRIGGER_MODE_REG = val;
++ }
++ } else {
++ if (!(val & (1UL << irq))) {
++ val |= (1UL << irq);
++ INTC_INTERRUPT_TRIGGER_MODE_REG = val;
++ }
++ }
++}
++
++/*
++ * Configure interrupt trigger level to be Active High/Low or Rising/Falling Edge
++ */
++static inline void str9100_set_irq_level(unsigned int irq, unsigned int level)
++{
++ unsigned int val;
++
++ if (irq < 0 || irq > NR_IRQS) {
++ return;
++ }
++
++ if ((level != INTC_ACTIVE_HIGH) &&
++ (level != INTC_ACTIVE_LOW) &&
++ (level != INTC_RISING_EDGE) &&
++ (level != INTC_FALLING_EDGE)) {
++ return;
++ }
++
++ val = INTC_INTERRUPT_TRIGGER_LEVEL_REG;
++
++ if ((level == INTC_ACTIVE_HIGH) ||
++ (level == INTC_RISING_EDGE)) {
++ if (val & (1UL << irq)) {
++ val &= ~(1UL << irq);
++ INTC_INTERRUPT_TRIGGER_LEVEL_REG = val;
++ }
++ } else {
++ if (!(val & (1UL << irq))) {
++ val |= (1UL << irq);
++ INTC_INTERRUPT_TRIGGER_LEVEL_REG = val;
++ }
++ }
++}
++
++/*
++ * Configure interrupt trigger mode and trigger level
++ */
++void str9100_set_interrupt_trigger(unsigned int irq, unsigned int mode, unsigned int level)
++{
++ str9100_set_irq_mode(irq, mode);
++ str9100_set_irq_level(irq, level);
++}
++EXPORT_SYMBOL(str9100_set_interrupt_trigger);
++
++/*
++ * Mask/Disable this interrupt source
++ */
++static void str9100_mask_irq(unsigned int irq)
++{
++ // Mask/Disable this interrupt source
++ INTC_INTERRUPT_MASK_REG |= (1UL << irq);
++}
++
++/*
++ * Un-Mask/Enable this interrupt source
++ */
++static void str9100_unmask_irq(unsigned int irq)
++{
++ // Clear interrupt status of the interrupt source which is edge-triggered
++ INTC_INTERRUPT_CLEAR_EDGE_TRIGGER_REG |= (1UL << irq);
++
++ // Mask/Disable this interrupt source
++ INTC_INTERRUPT_MASK_REG &= ~(1UL << irq);
++}
++
++static struct irq_chip str9100_irqchip = {
++ .ack = str9100_mask_irq,
++ .mask = str9100_mask_irq,
++ .unmask = str9100_unmask_irq,
++};
++
++void __init str9100_init_irq(void)
++{
++ int i;
++
++ INTC_INTERRUPT_MASK_REG = 0xFFFFFFFF;
++ INTC_INTERRUPT_CLEAR_EDGE_TRIGGER_REG = 0xFFFFFFFF;
++ INTC_FIQ_MODE_SELECT_REG = 0x0;
++
++ for (i = 0; i < NR_IRQS; i++) {
++ if (intc_trigger_table[i].mode != INTC_TRIGGER_UNKNOWN) {
++ str9100_set_irq_mode(i, intc_trigger_table[i].mode);
++ str9100_set_irq_level(i, intc_trigger_table[i].level);
++ }
++ }
++
++ for (i = 0; i < NR_IRQS; i++) {
++ set_irq_chip(i, &str9100_irqchip);
++ /* scott.patch */
++ set_irq_handler(i, handle_level_irq);
++ set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
++ }
++}
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str9100/str9100_misc.c linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_misc.c
+--- linux-2.6.35.11/arch/arm/mach-str9100/str9100_misc.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_misc.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,249 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/proc_fs.h>
++#include <asm/mach/map.h>
++#include <asm/hardware.h>
++
++// enable I-Scratchpad
++int str9100_enable_ispad(u32 base_addr)
++{
++ u32 ispad_config = 0;
++ u32 flush_ispad = 0;
++ u32 ispad_size = 4; // 8K on STR9100
++ u32 cp15 = 1, cp15_off = 0;
++
++ // Configure Base
++ ispad_config |= (base_addr & 0xfffffc00);
++
++ // Configure Size
++ ispad_config &= ~(0xf << 2);
++ ispad_config |= ((ispad_size & 0xf) << 2) | (0x1 << 2);
++
++ // Enable
++ ispad_config |= 0x1;
++
++ // 1. set cp15, cr1-1(ECR) register value to 0x1
++ // 2. set up the base and size configuration
++ // 3. Invalidate IScratchpad All(flushed ISpad)
++ // 4. clear cp15, cr1-1(ECR) register value to 0x0
++ __asm__ __volatile__ (
++ "mcr p15,0,%0,c1,c1,0\n\t"
++ "mcr p15,0,%1,c9,c1,1\n\t"
++ "mcr p15,0,%2,c7,c5,5\n\t"
++ "mcr p15,0,%3,c1,c1,0\n\t"
++ "nop\n\t"
++ "nop\n\t"
++ "nop\n\t"
++ "nop\n\t"
++ "nop\n\t"
++ :
++ : "r"(cp15), "r"(ispad_config), "r"(flush_ispad), "r"(cp15_off));
++
++ return 0;
++}
++
++static struct map_desc str9100_map_desc[64];
++static int str9100_map_desc_count;
++#define REG_DEBUG_CMD_BUFFER_SIZE 128
++#define REG_DEBUG_RESULT_BUFFER_SIZE 256
++static struct proc_dir_entry *star_reg_debug_proc_entry;
++static char str9100_reg_debug_cmd_buf[REG_DEBUG_CMD_BUFFER_SIZE];
++static char str9100_reg_debug_result_buf[REG_DEBUG_RESULT_BUFFER_SIZE];
++
++struct proc_dir_entry *str9100_proc_dir;
++EXPORT_SYMBOL(str9100_proc_dir);
++
++void str9100_register_map_desc(struct map_desc *map, int count)
++{
++ if (count) {
++ if (str9100_map_desc) {
++ int i;
++ for (i = 0; i < count; i++) {
++ str9100_map_desc[i].virtual = map->virtual;
++ str9100_map_desc[i].pfn = map->pfn;
++ str9100_map_desc[i].length = map->length;
++ str9100_map_desc[i].type = map->type;
++ map++;
++ }
++ str9100_map_desc_count = count;
++ }
++ }
++}
++
++u32 str9100_query_map_desc_by_phy(u32 addr)
++{
++ struct map_desc *map;
++ int i;
++ u32 ret_addr = 0;
++ for (i = 0; i < str9100_map_desc_count; i++) {
++ map = &str9100_map_desc[i];
++ if (addr >= (map->pfn << PAGE_SHIFT) && addr < ((map->pfn << PAGE_SHIFT) + map->length)) {
++ ret_addr = map->virtual + (addr - (map->pfn << PAGE_SHIFT));
++ break;
++ }
++ }
++
++ return ret_addr;
++}
++
++u32 str9100_query_map_desc_by_vir(u32 addr)
++{
++ struct map_desc *map;
++ int i;
++ u32 ret_addr = 0;
++ for (i = 0; i < str9100_map_desc_count; i++) {
++ map = &str9100_map_desc[i];
++ if (addr >= map->virtual && addr < (map->virtual + map->length)) {
++ ret_addr = (map->pfn << PAGE_SHIFT) + (addr - map->virtual);
++ break;
++ }
++ }
++
++ return ret_addr;
++}
++
++static int star_reg_debug_read_proc(char *buffer, char **start, off_t offset,
++ int length, int *eof, void *data)
++{
++ int count;
++ int num = 0;
++
++ if (str9100_reg_debug_cmd_buf[0]) {
++ count = strlen(str9100_reg_debug_cmd_buf);
++ sprintf(buffer, str9100_reg_debug_cmd_buf, count);
++ num += count;
++ }
++ if (str9100_reg_debug_result_buf[0]) {
++ count = strlen(str9100_reg_debug_result_buf);
++ sprintf(buffer + num, str9100_reg_debug_result_buf, count);
++ num += count;
++ }
++
++ return num;
++}
++
++static int
++star_reg_debug_write_proc(struct file *file, const char __user *buffer,
++ unsigned long count, void *data)
++{
++ char *str;
++ char *cmd;
++
++ if (count > 0) {
++ str = (char *)buffer,
++ cmd = strsep(&str, "\t \n");
++ if (!cmd) goto err_out;
++ if (strcmp(cmd, "dump") == 0) {
++ u32 addr;
++ u32 vir_addr;
++ char *arg = strsep(&str, "\t \n");
++ if (!arg) goto err_out;
++ addr = simple_strtoul(arg, &arg, 16);
++ if (addr & 0x3) goto err_out;
++ vir_addr = str9100_query_map_desc_by_phy(addr);
++ sprintf(str9100_reg_debug_cmd_buf,
++ "dump 0x%08x\n",
++ addr);
++ if (!vir_addr) goto err_out;
++ sprintf(str9100_reg_debug_result_buf,
++ "physical addr: 0x%08x content: 0x%08x\n",
++ addr,
++ *(volatile unsigned int __force *)(vir_addr));
++ } else if (strcmp(cmd, "write") == 0) {
++ u32 addr;
++ u32 vir_addr;
++ u32 data;
++ char *arg = strsep(&str, "\t \n");
++ if (!arg) goto err_out;
++ addr = simple_strtoul(arg, &arg, 16);
++ arg = strsep(&str, "\t \n");
++ if (!arg) goto err_out;
++ data = simple_strtoul(arg, &arg, 16);
++ if (addr & 0x3) goto err_out;
++ vir_addr = str9100_query_map_desc_by_phy(addr);
++ if (!vir_addr) goto err_out;
++ *(volatile unsigned int __force *)(vir_addr) = data;
++ sprintf(str9100_reg_debug_cmd_buf,
++ "write 0x%08x 0x%08x\n",
++ addr, data);
++ sprintf(str9100_reg_debug_result_buf,
++ "physical addr: 0x%08x content: 0x%08x\n",
++ addr,
++ *(volatile unsigned int __force *)(vir_addr));
++ } else {
++ goto err_out;
++ }
++ }
++
++ return count;
++
++err_out:
++ return -EFAULT;
++}
++
++static int __init star_reg_debug_proc_init(void)
++{
++ star_reg_debug_proc_entry = create_proc_entry("str9100/reg_debug", S_IFREG | S_IRUGO, NULL);
++ if (star_reg_debug_proc_entry) {
++ star_reg_debug_proc_entry->read_proc = star_reg_debug_read_proc;
++ star_reg_debug_proc_entry->write_proc = star_reg_debug_write_proc;
++ }
++
++ return 0;
++}
++
++static int __init str9100_proc_dir_create(void)
++{
++ str9100_proc_dir = proc_mkdir("str9100", NULL);
++ if (str9100_proc_dir) {
++ str9100_proc_dir->owner = THIS_MODULE;
++ } else {
++ printk("Error: cannot crete str9100 proc dir entry at /proc/str9100\n");
++ return -EINVAL;
++ }
++
++ if (str9100_map_desc_count) {
++ (void)star_reg_debug_proc_init();
++ }
++
++ return 0;
++}
++
++extern int __init str9100_counter_setup(void);
++static int __init str9100_misc_init(void)
++{
++ str9100_proc_dir_create();
++ str9100_counter_setup();
++ return 0;
++}
++
++module_init(str9100_misc_init);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Star Semi Corporation");
++MODULE_DESCRIPTION("STR9100 MISC");
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str9100/str9100_pci.c linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_pci.c
+--- linux-2.6.35.11/arch/arm/mach-str9100/str9100_pci.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_pci.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,331 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/ptrace.h>
++#include <linux/slab.h>
++#include <linux/ioport.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/init.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++#include <asm/mach/pci.h>
++
++#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | ((bus) << 16) | ((device_fn) << 8) | ((where) & ~3))
++
++static struct pci_dev *pci_bridge = NULL;
++static u32 pci_config_addr; // PCI configuration register address port
++static u32 pci_config_data; // PCI configuration register data port
++u32 str9100_pci_irqs[4] = {0, INTC_PCI_INTA_BIT_INDEX, INTC_PCI_INTB_BIT_INDEX, 0};
++
++static int str9100_pci_read_config(struct pci_bus *bus,
++ unsigned int devfn, int where, int size, u32 *val)
++{
++ u32 v = 0;
++ u32 shift;
++ unsigned long flags;
++
++ switch (size) {
++ case 1:
++ shift = (where & 0x3) << 3;
++ local_irq_save(flags);
++ __raw_writel(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ v = __raw_readl(pci_config_data);
++ local_irq_restore(flags);
++ v = (v >> shift) & 0xff;
++ break;
++
++ case 2:
++ shift = (where & 0x3) << 3;
++ local_irq_save(flags);
++ __raw_writel(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ v = __raw_readl(pci_config_data);
++ local_irq_restore(flags);
++ v = (v >> shift) & 0xffff;
++
++ break;
++
++ case 4:
++ local_irq_save(flags);
++ __raw_writel(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ v = __raw_readl(pci_config_data);
++ local_irq_restore(flags);
++ break;
++ }
++
++ *val = v;
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int str9100_pci_write_config(struct pci_bus *bus,
++ unsigned int devfn, int where, int size, u32 val)
++{
++ u32 v;
++ u32 shift;
++ unsigned long flags;
++
++ switch (size) {
++ case 1:
++ shift = (where & 0x3) << 3;
++ local_irq_save(flags);
++ __raw_writel(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ v = __raw_readl(pci_config_data);
++ v = (v & ~(0xff << shift)) | (val << shift);
++ __raw_writel(v, pci_config_data);
++ local_irq_restore(flags);
++ break;
++
++ case 2:
++ shift = (where & 0x3) << 3;
++ local_irq_save(flags);
++ __raw_writel(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ v = __raw_readl(pci_config_data);
++ v = (v & ~(0xffff << shift)) | (val << shift);
++ __raw_writel(v, pci_config_data);
++ local_irq_restore(flags);
++ break;
++
++ case 4:
++ local_irq_save(flags);
++ __raw_writel(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ __raw_writel(val, pci_config_data);
++ local_irq_restore(flags);
++ break;
++ }
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops str9100_pci_ops = {
++ .read = str9100_pci_read_config,
++ .write = str9100_pci_write_config,
++};
++
++static struct resource str9100_pci_io = {
++ .name = "PCI I/O space",
++ .start = PCI_IO_SPACE_START,
++ .end = PCI_IO_SPACE_END, //albert : 20040714
++ .flags = IORESOURCE_IO,
++};
++
++static struct resource str9100_pci_nprefetch_mem = {
++ .name = "PCI non-prefetchable",
++ .start = PCI_NPREFETCH_MEMORY_SPACE_START,
++ .end = PCI_NPREFETCH_MEMORY_SPACE_END,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct resource str9100_pci_prefetch_mem = {
++ .name = "PCI prefetchable",
++ .start = PCI_PREFETCH_MEMORY_SPACE_START,
++ .end = PCI_PREFETCH_MEMORY_SPACE_END,
++ .flags = IORESOURCE_MEM | IORESOURCE_PREFETCH,
++};
++
++static int __init str9100_pci_setup_resources(struct resource **resource)
++{
++ int ret = -1;
++
++ ret = request_resource(&iomem_resource, &str9100_pci_io);
++ if (ret) {
++ printk(KERN_ERR "PCI: unable to allocate I/O "
++ "memory region (%d)\n", ret);
++ goto out;
++ }
++ ret = request_resource(&iomem_resource, &str9100_pci_nprefetch_mem);
++ if (ret) {
++ printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
++ "memory region (%d)\n", ret);
++ goto release_io;
++ }
++ ret = request_resource(&iomem_resource, &str9100_pci_prefetch_mem);
++ if (ret) {
++ printk(KERN_ERR "PCI: unable to allocate prefetchable "
++ "memory region (%d)\n", ret);
++ goto release_nprefetch_mem;
++ }
++
++ /*
++ * bus->resource[0] is the IO resource for this bus
++ * bus->resource[1] is the mem resource for this bus
++ * bus->resource[2] is the prefetch mem resource for this bus
++ */
++ resource[0] = &str9100_pci_io;
++ resource[1] = &str9100_pci_nprefetch_mem;
++ resource[2] = &str9100_pci_prefetch_mem;
++
++ ret = 0;
++
++ goto out;
++
++release_nprefetch_mem:
++ release_resource(&str9100_pci_nprefetch_mem);
++release_io:
++ release_resource(&str9100_pci_io);
++out:
++ return ret;
++}
++
++static irqreturn_t PCI_AHB2PCIB_ISR(int irq, void *dev_id, struct pt_regs * regs)
++{
++ u32 status;
++
++ //disable_irq(INTC_PCI_AHB2BRIDGE_BIT_INDEX);
++ pci_read_config_dword(pci_bridge, PCI_COMMAND, &status);
++ printk("AHB to bridge interrupt status: 0x%x\n", status);
++ pci_write_config_dword(pci_bridge, PCI_COMMAND, status);
++ //enable_irq(INTC_PCI_AHB2BRIDGE_BIT_INDEX);
++
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t PCI_BROKEN_ISR(int irq, void *dev_id, struct pt_regs *regs)
++{
++ u32 status;
++
++ status = MISC_PCI_BROKEN_STATUS_REG & 0x1f;
++ printk("PCI BROKEN interrupt status: 0x%x\n", status);
++ MISC_PCI_BROKEN_STATUS_REG = status;
++
++ return IRQ_HANDLED;
++}
++
++int __init str9100_pci_setup(int nr, struct pci_sys_data *sys)
++{
++ if (nr != 0) {
++ return 0;
++ }
++
++ if (str9100_pci_setup_resources(sys->resource)) {
++ BUG();
++ }
++
++ return 1;
++}
++
++struct pci_bus *str9100_pci_scan_bus(int nr, struct pci_sys_data *sys)
++{
++ return pci_scan_bus(sys->busnr, &str9100_pci_ops, sys);
++}
++
++void __init str9100_pci_preinit(void)
++{
++ pci_config_addr = SYSVA_PCI_BRIDGE_CONFIG_ADDR_BASE_ADDR + PCI_BRIDGE_CONFIG_ADDR_REG_OFFSET;
++ pci_config_data = SYSVA_PCI_BRIDGE_CONFIG_DATA_BASE_ADDR + PCI_BRIDGE_CONFIG_DATA_REG_OFFSET;
++
++#if defined(CONFIG_STAR9100_PCI66M)
++ printk("PCI clock at 66M\n");
++ HAL_PWRMGT_ENABLE_PCI_BRIDGE_66MM();
++#elif defined(CONFIG_STAR9100_PCI33M)
++ printk("PCI clock at 33M\n");
++ HAL_PWRMGT_ENABLE_PCI_BRIDGE_33M();
++#else
++ printk("PCI clock at 33M\n");
++ HAL_PWRMGT_ENABLE_PCI_BRIDGE_33M();
++#endif
++}
++
++void __init str9100_pci_postinit(void)
++{
++ pci_bridge = pci_get_device(PCIB_VENDOR_ID, PCIB_DEVICE_ID, NULL);
++ if (pci_bridge == NULL) {
++ printk("PCI Bridge not found\n");
++ return;
++ } else {
++ printk("PCI Bridge found\n");
++ }
++
++ /* scott.patch */
++ request_irq(INTC_PCI_AHB2BRIDGE_BIT_INDEX, PCI_AHB2PCIB_ISR, IRQF_DISABLED, "pci bridge", pci_bridge);
++
++ MISC_PCI_ARBITER_INTERRUPT_MASK_REG &= ~0x1f;
++
++ /* scott.patch */
++ request_irq(INTC_PCI_ARBITOR_BIT_INDEX, PCI_BROKEN_ISR, IRQF_DISABLED, "pci broken", pci_bridge);
++
++ pci_write_config_dword(pci_bridge, PCI_BASE_ADDRESS_0, 0x0); // = 0x0, can NOT use 0x20000000
++ pci_write_config_dword(pci_bridge, PCI_BASE_ADDRESS_1, 0x0); // = 0x0, can NOT use 0x20000000
++
++ // if we enable pci on u-boot
++ // the pci_enable_device will complain with resource collisions
++ // use this to fixup
++ {
++ int i;
++ struct resource *r;
++
++ for (i = 0; i < 6; i++) {
++ r = pci_bridge->resource + i;
++ r->start = 0;
++ r->end = 0;
++ }
++ }
++
++ pci_enable_device(pci_bridge);
++ pci_set_master(pci_bridge);
++}
++
++/*
++ * map the specified device/slot/pin to an IRQ. Different backplanes may need to modify this.
++ */
++static int __init str9100_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ int irq;
++
++ /* slot, pin, irq
++ * 0 1 0
++ * 1 1 5
++ * 2 1 6
++ * 3 1 0
++ */
++ irq = str9100_pci_irqs[((slot + pin - 1) & 3)];
++
++ printk("PCI map irq: %02x:%02x.%02x slot %d, pin %d, irq: %d\n",
++ dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
++ slot, pin, irq);
++
++ return irq;
++}
++
++static struct hw_pci str9100_pci __initdata = {
++ .swizzle = pci_std_swizzle,
++ .map_irq = str9100_pci_map_irq,
++ .nr_controllers = 1,
++ .setup = str9100_pci_setup,
++ .scan = str9100_pci_scan_bus,
++ .preinit = str9100_pci_preinit,
++ .postinit = str9100_pci_postinit,
++};
++
++static int __init str9100_pci_init(void)
++{
++ pci_common_init(&str9100_pci);
++ return 0;
++}
++
++subsys_initcall(str9100_pci_init);
+diff -rupN linux-2.6.35.11/arch/arm/mach-str9100/str9100_rtc.c linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_rtc.c
+--- linux-2.6.35.11/arch/arm/mach-str9100/str9100_rtc.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_rtc.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,493 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/miscdevice.h>
++#include <linux/ioport.h>
++#include <linux/fcntl.h>
++#include <linux/init.h>
++#include <linux/poll.h>
++#include <linux/proc_fs.h>
++#include <linux/spinlock.h>
++#include <linux/sysctl.h>
++#include <linux/rtc.h>
++#include <linux/interrupt.h>
++
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/system.h>
++
++#include <asm/arch/star_rtc.h>
++#include <asm/arch/star_intc.h>
++
++#define STR9100_RTC_DATE "20060628"
++#define STR9100_RTC_VERSION "2.0.0"
++#define DEVICE_NAME "rtc"
++#define SECS_PER_HOUR (60 * 60)
++#define SECS_PER_DAY (SECS_PER_HOUR * 24)
++#define TM_YEAR_BASE 1900
++#define EPOCH_YEAR 1970
++#define RTC_INTR_ALARM 0x20
++
++extern spinlock_t rtc_lock;
++
++static int rtc_busy = 0;
++static unsigned long epoch = 1900;
++static unsigned int rtc_interrupt_flag = 0;
++static time_t local_rtc_offset, set_rtc_offset, current_rtc_time;
++static DECLARE_WAIT_QUEUE_HEAD(str9100_rtc_wait);
++
++# define __isleap(year) ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
++
++static const unsigned char days_in_mo[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
++
++static const unsigned short int __mon_yday[2][13] =
++{
++ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
++ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
++};
++
++static int offtime (const time_t *t, long int offset, struct rtc_time *tp)
++{
++ long int days, rem, y;
++ const unsigned short int *ip;
++
++ days = *t / SECS_PER_DAY;
++ rem = *t % SECS_PER_DAY;
++ rem += offset;
++ while (rem < 0)
++ {
++ rem += SECS_PER_DAY;
++ --days;
++ }
++ while (rem >= SECS_PER_DAY)
++ {
++ rem -= SECS_PER_DAY;
++ ++days;
++ }
++ tp->tm_hour = rem / SECS_PER_HOUR;
++ rem %= SECS_PER_HOUR;
++ tp->tm_min = rem / 60;
++ tp->tm_sec = rem % 60;
++ tp->tm_wday = (4 + days) % 7;
++ if (tp->tm_wday < 0)
++ tp->tm_wday += 7;
++ y = 1970;
++#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
++#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
++ while (days < 0 || days >= (__isleap (y) ? 366 : 365))
++ {
++ long int yg = y + days / 365 - (days % 365 < 0);
++ days -= ((yg - y) * 365 + LEAPS_THRU_END_OF (yg - 1)- LEAPS_THRU_END_OF (y - 1));
++ y = yg;
++ }
++ tp->tm_year = y - 1900;
++ if (tp->tm_year != y - 1900)
++ return 0;
++ tp->tm_yday = days;
++ ip = __mon_yday[__isleap(y)];
++ for (y = 11; days < (long int) ip[y]; --y)
++ continue;
++ days -= ip[y];
++ tp->tm_mon = y;
++ tp->tm_mday = days + 1;
++ return 1;
++}
++
++static time_t ydhms_tm_diff (int year, int yday, int hour, int min, int sec, const struct rtc_time *tp)
++{
++ if (!tp) return 1;
++ else {
++ int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
++ int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
++ int a100 = a4 / 25 - (a4 % 25 < 0);
++ int b100 = b4 / 25 - (b4 % 25 < 0);
++ int a400 = a100 >> 2;
++ int b400 = b100 >> 2;
++ int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
++ time_t years = year - (time_t) tp->tm_year;
++ time_t days = (365 * years + intervening_leap_days + (yday - tp->tm_yday));
++ return (60 * (60 * (24 * days+(hour - tp->tm_hour))+(min - tp->tm_min))+(sec - tp->tm_sec));
++ }
++}
++
++static time_t _mktime(struct rtc_time *tp, time_t *offset)
++{
++ time_t t;
++ struct rtc_time tm;
++ int sec = tp->tm_sec;
++ int min = tp->tm_min;
++ int hour = tp->tm_hour;
++ int mday = tp->tm_mday;
++ int mon = tp->tm_mon;
++ int year_requested = tp->tm_year;
++
++ int mon_remainder = mon % 12;
++ int negative_mon_remainder = mon_remainder < 0;
++ int mon_years = mon / 12 - negative_mon_remainder;
++ int year = year_requested + mon_years;
++ int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
++ [mon_remainder + 12 * negative_mon_remainder])
++ + mday - 1);
++ if (year < 69) return -1;
++ tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
++ tm.tm_yday = tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
++ t = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
++ if (year == 69)
++ {
++ if (t < 0 || t > 2 * 24 * 60 * 60) return -1;
++ }
++ *tp = tm;
++ return t;
++}
++
++void get_rtc_time (struct rtc_time *rtc_tm)
++{
++ time_t update_time;
++ static time_t old_time = 0;
++
++ spin_lock (&rtc_lock);
++ update_time = RTC_SECOND_REG + RTC_MINUTE_REG * 60 + RTC_HOUR_REG * 60 * 60 + RTC_DAY_REG * 60 * 60 * 24 - local_rtc_offset + set_rtc_offset;
++ if (old_time > 0)
++ {
++ printk ("\n\n Old time is %d, last time is %d, diff is %d\n",old_time,update_time,update_time-old_time);
++ printk (" Throughput is %d B/s, %d KB/s\n\n",106096775/(update_time-old_time),(106096775/1024)/(update_time-old_time));
++ }
++ old_time = update_time;
++ offtime(&update_time, 0, rtc_tm);
++ if ((rtc_tm->tm_year += (epoch - 1900)) <= 69)
++ rtc_tm->tm_year += 100;
++ spin_unlock (&rtc_lock);
++}
++
++int set_rtc_time (struct rtc_time *rtc_tm)
++{
++ unsigned char mon, day, hrs, min, sec, leap_yr;
++ unsigned int yrs;
++
++ spin_lock (&rtc_lock);
++ yrs = rtc_tm->tm_year + 1900;
++ mon = rtc_tm->tm_mon + 1;
++ day = rtc_tm->tm_mday;
++ hrs = rtc_tm->tm_hour;
++ min = rtc_tm->tm_min;
++ sec = rtc_tm->tm_sec;
++ if (yrs < 1970) return -EINVAL;
++ leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
++ if ((mon > 12) || (day == 0)) return -EINVAL;
++ if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) return -EINVAL;
++ if ((hrs >= 24) || (min >= 60) || (sec >= 60)) return -EINVAL;
++ if ((yrs -= epoch) > 255) return -EINVAL;
++ local_rtc_offset = RTC_SECOND_REG + RTC_MINUTE_REG * 60 + RTC_HOUR_REG * 60 * 60 + RTC_DAY_REG * 60 * 60 * 24;
++ set_rtc_offset = _mktime(rtc_tm, 0);
++ spin_unlock (&rtc_lock);
++ return 0;
++}
++
++int set_rtc_alm_time (struct rtc_time *alm_tm)
++{
++ unsigned char hrs, min, sec;
++ unsigned long alm_sec;
++ unsigned int volatile rtc_int_status;
++
++ spin_lock_irq(&rtc_lock);
++ alm_sec = alm_tm->tm_hour * 3600 + alm_tm->tm_min * 60 + alm_tm->tm_sec;
++ hrs = alm_sec / 3600;
++ min = (alm_sec % 3600) / 60;
++ sec = (alm_sec % 3600) % 60;
++ RTC_ALARM_HOUR_REG = hrs;
++ RTC_ALARM_MINUTE_REG = min;
++ RTC_ALARM_SECOND_REG = sec;
++ RTC_CONTROL_REG = RTC_MATCH_ALARM_ENABLE_BIT;
++ rtc_int_status = RTC_INTERRUPT_STATE_REG;
++ RTC_INTERRUPT_STATE_REG = rtc_int_status;
++ spin_unlock_irq(&rtc_lock);
++ return 0;
++}
++
++static loff_t rtc_lseek(struct file *file, loff_t offset, int origin)
++{
++ return -ESPIPE;
++}
++
++static void mask_rtc_irq_bit(unsigned char bit)
++{
++ unsigned char val;
++ unsigned int volatile rtc_int_status;
++
++ spin_lock_irq(&rtc_lock);
++ val = RTC_CONTROL_REG;
++ val &= ~bit;
++ RTC_CONTROL_REG = val;
++ rtc_int_status = RTC_INTERRUPT_STATE_REG;
++ spin_unlock_irq(&rtc_lock);
++}
++
++static void set_rtc_irq_bit(unsigned char bit)
++{
++ unsigned char val;
++ unsigned int volatile rtc_int_status;
++
++ spin_lock_irq(&rtc_lock);
++ val = RTC_CONTROL_REG;
++ val |= bit;
++ RTC_CONTROL_REG = val;
++ rtc_int_status = RTC_INTERRUPT_STATE_REG;
++ spin_unlock_irq(&rtc_lock);
++}
++
++static void get_rtc_alm_time(struct rtc_time *alm_tm)
++{
++ spin_lock_irq(&rtc_lock);
++ alm_tm->tm_sec = RTC_ALARM_SECOND_REG;
++ alm_tm->tm_min = RTC_ALARM_MINUTE_REG;
++ alm_tm->tm_hour = RTC_ALARM_HOUR_REG;
++ spin_unlock_irq(&rtc_lock);
++}
++
++static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg)
++{
++ struct rtc_time wtime;
++
++ switch (cmd)
++ {
++ case RTC_RD_TIME:
++ memset(&wtime, 0, sizeof(struct rtc_time));
++ get_rtc_time(&wtime);
++ break;
++ case RTC_SET_TIME:
++ {
++ struct rtc_time rtc_tm;
++ if (!capable(CAP_SYS_TIME))
++ return -EPERM;
++ if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
++ return -EFAULT;
++ set_rtc_time(&rtc_tm);
++ return 0;
++ }
++ case RTC_ALM_SET:
++ {
++ struct rtc_time alm_tm;
++ if (copy_from_user(&alm_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
++ return -EFAULT;
++ memset(&wtime, 0, sizeof(struct rtc_time));
++ set_rtc_alm_time(&alm_tm);
++ return 0;
++ }
++ case RTC_ALM_READ:
++ memset(&wtime, 0, sizeof(struct rtc_time));
++ get_rtc_alm_time(&wtime);
++ break;
++ case RTC_AIE_OFF:
++ mask_rtc_irq_bit(RTC_INTR_ALARM);
++ return 0;
++ case RTC_AIE_ON:
++ set_rtc_irq_bit(RTC_INTR_ALARM);
++ return 0;
++ default:
++ return -EINVAL;
++ }
++ return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
++}
++
++static void rtc_fire(int irq, void *dev_id, struct pt_regs *regs)
++{
++ unsigned int volatile rtc_int_status;
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_RTC_BIT_INDEX);
++ HAL_RTC_READ_INTERRUPT_STATUS(rtc_int_status);
++ HAL_RTC_WRITE_INTERRUPT_STATUS(rtc_int_status);
++ if (rtc_int_status & RTC_AUTO_SECOND_ALARM_INTERRUPT_BIT) rtc_interrupt_flag |= RTC_AUTO_SECOND_ALARM_INTERRUPT_BIT;
++ if (rtc_int_status & RTC_AUTO_MINUTE_ALARM_INTERRUPT_BIT) rtc_interrupt_flag |= RTC_AUTO_MINUTE_ALARM_INTERRUPT_BIT;
++ if (rtc_int_status & RTC_AUTO_HOUR_ALARM_INTERRUPT_BIT) rtc_interrupt_flag |= RTC_AUTO_HOUR_ALARM_INTERRUPT_BIT;
++ if (rtc_int_status & RTC_AUTO_DAY_ALARM_INTERRUPT_BIT) rtc_interrupt_flag |= RTC_AUTO_DAY_ALARM_INTERRUPT_BIT;
++ if (rtc_int_status & RTC_MATCH_ALARM_INTERRUPT_BIT) {rtc_interrupt_flag |= RTC_MATCH_ALARM_INTERRUPT_BIT;
++ wake_up_interruptible(&str9100_rtc_wait);
++ }
++ if (rtc_int_status & RTC_BATTERY_LOW_VOLTAGE_INTR_BIT)
++ {
++ rtc_interrupt_flag |= RTC_BATTERY_LOW_VOLTAGE_INTR_BIT;
++ printk("str9100 rtc: Low Battery Voltage!!\n");
++ }
++ if (!(rtc_interrupt_flag & RTC_MATCH_ALARM_INTERRUPT_BIT)) HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_RTC_BIT_INDEX);
++}
++
++static void rtc_str9100_hwinit(int ctrl, int hour, int min, int sec)
++{
++ RTC_CONTROL_REG &= ~(RTC_ENABLE_BIT);
++ if (ctrl & RTC_MATCH_ALARM_ENABLE_BIT)
++ {
++ RTC_ALARM_SECOND_REG = sec;
++ RTC_ALARM_MINUTE_REG = min;
++ RTC_ALARM_HOUR_REG = hour;
++ }else{
++ RTC_ALARM_SECOND_REG = 0;
++ RTC_ALARM_MINUTE_REG = 0;
++ RTC_ALARM_HOUR_REG = 0;
++ }
++ RTC_CONTROL_REG = ctrl;
++}
++
++static int rtc_open(struct inode *inode, struct file *file)
++{
++ if (rtc_busy) return -EBUSY;
++
++ rtc_busy = 1;
++ return 0;
++}
++
++static ssize_t rtc_read(struct file * file, char *buf, size_t count, loff_t * ppos)
++{
++ DECLARE_WAITQUEUE(wait, current);
++ unsigned long data;
++ ssize_t retval;
++
++ if (count < sizeof(unsigned long))
++ return -EINVAL;
++
++ add_wait_queue(&str9100_rtc_wait, &wait);
++ set_current_state(TASK_INTERRUPTIBLE);
++ for (;;) {
++ spin_lock(&rtc_lock);
++ data = rtc_interrupt_flag;
++ if (data != 0) {
++ rtc_interrupt_flag = 0;
++ break;
++ }
++ spin_unlock(&rtc_lock);
++ if (file->f_flags & O_NONBLOCK) {
++ retval = -EAGAIN;
++ goto out;
++ }
++ if (signal_pending(current)) {
++ retval = -ERESTARTSYS;
++ goto out;
++ }
++ schedule();
++ }
++ spin_unlock(&rtc_lock);
++ retval = put_user(data, (unsigned long *) buf);
++ if (!retval) retval = sizeof(unsigned long);
++out:
++ mask_rtc_irq_bit(RTC_INTR_ALARM);
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&str9100_rtc_wait, &wait);
++ return retval;
++}
++
++static int rtc_release(struct inode *inode, struct file *file)
++{
++ rtc_busy = 0;
++ return 0;
++}
++
++static struct file_operations rtc_fops = {
++ owner: THIS_MODULE,
++ llseek: rtc_lseek,
++ ioctl: rtc_ioctl,
++ open: rtc_open,
++ read: rtc_read,
++ release: rtc_release
++};
++
++static struct miscdevice rtc_dev = { RTC_MINOR, "rtc", &rtc_fops };
++
++static int rtc_proc_output (char *buf)
++{
++ char *p;
++ struct rtc_time tm;
++
++ p = buf;
++ get_rtc_time(&tm);
++ p += sprintf(p,"rtc_time\t: %02d:%02d:%02d\n"
++ "rtc_date\t: %04d-%02d-%02d\n"
++ "rtc_epoch\t: %04lu\n",
++ tm.tm_hour, tm.tm_min, tm.tm_sec,
++ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch);
++ get_rtc_alm_time(&tm);
++ p += sprintf(p, "alarm\t\t: ");
++ if (tm.tm_hour <= 24)
++ p += sprintf(p, "%02d:", tm.tm_hour);
++ else
++ p += sprintf(p, "**:");
++ if (tm.tm_min <= 59)
++ p += sprintf(p, "%02d:", tm.tm_min);
++ else
++ p += sprintf(p, "**:");
++ if (tm.tm_sec <= 59)
++ p += sprintf(p, "%02d\n", tm.tm_sec);
++ else
++ p += sprintf(p, "**\n");
++ return p - buf;
++}
++
++static int rtc_read_proc(char *page, char **start, off_t off,int count, int *eof, void *data)
++{
++ int len = rtc_proc_output (page);
++
++ if (len <= off+count) *eof = 1;
++ *start = page + off;
++ len -= off;
++ if (len>count) len = count;
++ if (len<0) len = 0;
++ return len;
++}
++
++static int __init str9100_rtc_init(void)
++{
++ int error;
++
++ error = misc_register(&rtc_dev);
++ if (error) {
++ printk(KERN_ERR "rtc: unable to get misc minor\n");
++ return error;
++ }
++ printk(KERN_INFO "STR9100 Real Time Clock Driver v" STR9100_RTC_VERSION "\n");
++ rtc_str9100_hwinit(0,0,0,0);
++ HAL_RTC_ENABLE();
++ request_irq(INTC_RTC_BIT_INDEX, rtc_fire, 0, DEVICE_NAME, NULL);
++ create_proc_read_entry ("driver/rtc", 0, 0, rtc_read_proc, NULL);
++ local_rtc_offset = 0;
++ set_rtc_offset = current_rtc_time = 0;
++ return 0;
++}
++
++static void __exit str9100_rtc_exit (void)
++{
++ char buf[64];
++
++ HAL_RTC_DISABLE();
++ cleanup_sysctl();
++ sprintf (buf,"driver/%s",DEVICE_NAME);
++ remove_proc_entry (buf, NULL);
++ misc_deregister(&rtc_dev);
++ free_irq (INTC_RTC_BIT_INDEX, NULL);
++}
++
++module_init(str9100_rtc_init);
++module_exit(str9100_rtc_exit);
++
++MODULE_LICENSE("GPL");
+diff -rupN linux-2.6.35.11/arch/arm/mach-str9100/str9100_setup.c linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_setup.c
+--- linux-2.6.35.11/arch/arm/mach-str9100/str9100_setup.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_setup.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,357 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/config.h>
++#include <linux/major.h>
++#include <linux/fs.h>
++#include <linux/platform_device.h>
++#include <linux/serial.h>
++#include <linux/tty.h>
++#include <linux/serial_8250.h>
++
++#include <asm/io.h>
++#include <asm/pgtable.h>
++#include <asm/page.h>
++#include <asm/mach/map.h>
++#include <asm/setup.h>
++#include <asm/system.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/mach-types.h>
++#include <asm/mach/arch.h>
++
++#define STR9100_UART_XTAL 14769230
++
++#define EARLY_REGISTER_CONSOLE
++
++/*
++ * Standard IO mapping
++ */
++static struct map_desc str9100_std_desc[] __initdata = {
++ {
++ .virtual = SYSVA_FLASH_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_FLASH_BASE_ADDR),
++ .length = SZ_8M,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_SMC_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_SMC_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_DDR_SDRAM_CONTROLLER_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_DDR_SDRAM_CONTROLLER_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_DMAC_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_DMAC_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_GSW_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_GSW_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_HNAT_SRAM_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_HNAT_SRAM_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_MISC_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_MISC_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_POWER_MANAGEMENT_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_POWER_MANAGEMENT_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_UART_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_UART_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_TIMER_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_TIMER_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_WATCHDOG_TIMER_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_WATCHDOG_TIMER_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_RTC_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_RTC_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_GPIO_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_GPIO_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_INTC_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_INTC_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_PCMCIA_CONTROLLER_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_PCMCIA_CONTROLLER_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_PCI_BRIDGE_CONFIG_DATA_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_PCI_BRIDGE_CONFIG_DATA_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_PCI_BRIDGE_CONFIG_ADDR_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_PCI_BRIDGE_CONFIG_ADDR_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_USB11_CONFIG_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_USB11_CONFIG_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_USB11_OPERATION_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_USB11_OPERATION_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_USB20_CONFIG_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_USB20_CONFIG_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }, {
++ .virtual = SYSVA_USB20_OPERATION_BASE_ADDR,
++ .pfn = __phys_to_pfn(SYSPA_USB20_OPERATION_BASE_ADDR),
++ .length = SZ_4K,
++ .type = MT_DEVICE
++ }
++};
++
++#ifdef EARLY_REGISTER_CONSOLE
++static struct uart_port str9100_serial_ports[] = {
++ {
++ .membase = (char*)(SYSVA_UART_BASE_ADDR),
++ .mapbase = (SYSPA_UART_BASE_ADDR),
++ .irq = INTC_UART_BIT_INDEX,
++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ .iotype = UPIO_MEM,
++ .regshift = 2,
++ .uartclk = STR9100_UART_XTAL,
++ .line = 0,
++ .type = PORT_16550A,
++ .fifosize = 16
++ }
++};
++#else
++static struct resource str9100_uart0_resources[] = {
++ [0] = {
++ .start = SYSPA_UART_BASE_ADDR,
++ .end = SYSPA_UART_BASE_ADDR + 0xff,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = INTC_UART_BIT_INDEX,
++ .end = INTC_UART_BIT_INDEX,
++ .flags = IORESOURCE_IRQ
++ }
++};
++
++static struct plat_serial8250_port str9100_uart0_data[] = {
++ {
++ .membase = (char*)(SYSVA_UART_BASE_ADDR),
++ .mapbase = (SYSPA_UART_BASE_ADDR),
++ .irq = INTC_UART_BIT_INDEX,
++ .uartclk = STR9100_UART_XTAL,
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
++ },
++ { },
++};
++
++static struct platform_device str9100_uart0_device = {
++ .name = "serial8250",
++ .id = 0,
++ .dev.platform_data = str9100_uart0_data,
++ .num_resources = 2,
++ .resource = str9100_uart0_resources,
++};
++#endif
++
++static u64 usb_dmamask = 0xffffffffULL;
++static struct resource str9100_usb11_resources[] = {
++ [0] = {
++ .start = SYSPA_USB11_CONFIG_BASE_ADDR,
++ .end = SYSPA_USB11_CONFIG_BASE_ADDR + SZ_1M - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = INTC_USB11_BIT_INDEX,
++ .end = INTC_USB11_BIT_INDEX,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device str9100_usb11_device = {
++ .name = "str9100-ohci",
++ .id = -1,
++ .dev = {
++ .dma_mask = &usb_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = str9100_usb11_resources,
++ .num_resources = ARRAY_SIZE(str9100_usb11_resources),
++};
++
++static struct resource str9100_usb20_resources[] = {
++ [0] = {
++ .start = SYSPA_USB20_CONFIG_BASE_ADDR,
++ .end = SYSPA_USB20_CONFIG_BASE_ADDR + SZ_1M - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = INTC_USB20_BIT_INDEX,
++ .end = INTC_USB20_BIT_INDEX,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device str9100_usb20_device = {
++ .name = "str9100-ehci",
++ .id = -1,
++ .dev = {
++ .dma_mask = &usb_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .resource = str9100_usb20_resources,
++ .num_resources = ARRAY_SIZE(str9100_usb20_resources),
++};
++
++static struct platform_device *str9100_devices[] __initdata = {
++#ifndef EARLY_REGISTER_CONSOLE
++ &str9100_uart0_device,
++#endif
++ &str9100_usb11_device,
++ &str9100_usb20_device
++};
++
++static void __init str9100_fixup(struct machine_desc *desc,
++ struct tag *tags, char **cmdline, struct meminfo *mi)
++{
++ mi->nr_banks = 1;
++ mi->bank[0].start = CONFIG_SYSTEM_DRAM_BASE;
++ mi->bank[0].size = CONFIG_SYSTEM_DRAM_SIZE << 20;
++ mi->bank[0].node = 0;
++}
++
++/* ######################################################################### */
++#ifdef CONFIG_CPU_ISPAD_ENABLE
++extern unsigned long __ispad_begin;
++extern int str9100_enable_ispad(unsigned long);
++#endif
++u32 CPU_clock;
++u32 AHB_clock;
++u32 APB_clock;
++// This function is called just after the
++// page table and cpu have been initialized
++void __init str9100_early_init(void)
++{
++ switch ((PWRMGT_RESET_LATCH_CONFIGURATION_REG >> 6) & 0x03) {
++ case 0x00:
++ CPU_clock = 175000000;
++ break;
++
++ case 0x01:
++ CPU_clock = 200000000;
++ break;
++
++ case 0x02:
++ CPU_clock = 225000000;
++ break;
++
++ case 0x03:
++ CPU_clock = 250000000;
++ break;
++ }
++
++ AHB_clock = CPU_clock >> 1;
++ APB_clock = AHB_clock >> 1;
++
++ printk("CPU clock at %dMHz\n", CPU_clock / 1000000);
++ printk("AHB clock at %dMHz\n", AHB_clock / 1000000);
++ printk("APB clock at %dMHz\n", APB_clock / 1000000);
++
++#ifdef CONFIG_CPU_ISPAD_ENABLE
++ str9100_enable_ispad((unsigned long)&__ispad_begin);
++#endif
++}
++/* ######################################################################### */
++
++void __init str9100_init(void)
++{
++#if 1
++ platform_add_devices(str9100_devices, ARRAY_SIZE(str9100_devices));
++#else
++#ifndef EARLY_REGISTER_CONSOLE
++ platform_device_register(&str9100_uart0_device);
++#endif
++ platform_device_register(&str9100_usb11_device);
++ platform_device_register(&str9100_usb20_device);
++#endif
++}
++
++extern void str9100_register_map_desc(struct map_desc *map, int count);
++void __init str9100_map_io(void)
++{
++ iotable_init(str9100_std_desc, ARRAY_SIZE(str9100_std_desc));
++ str9100_register_map_desc(str9100_std_desc, ARRAY_SIZE(str9100_std_desc));
++#ifdef EARLY_REGISTER_CONSOLE
++ early_serial_setup(&str9100_serial_ports[0]);
++#endif
++}
++
++extern void str9100_init_irq(void);
++extern struct sys_timer str9100_timer;
++
++MACHINE_START(STR9100, "STAR STR9100")
++ .phys_io = SYSPA_UART_BASE_ADDR,
++ .io_pg_offst = ((SYSVA_UART_BASE_ADDR) >> 18) & 0xfffc, // virtual, physical
++ .fixup = str9100_fixup,
++ .map_io = str9100_map_io,
++ .init_irq = str9100_init_irq,
++ .timer = &str9100_timer,
++ .boot_params = 0x0100,
++ .init_machine = str9100_init,
++MACHINE_END
++
+diff -rupN linux-2.6.35.11/arch/arm/mach-str9100/str9100_timer.c linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_timer.c
+--- linux-2.6.35.11/arch/arm/mach-str9100/str9100_timer.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mach-str9100/str9100_timer.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,219 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/interrupt.h>
++#include <linux/time.h>
++#include <linux/init.h>
++#include <linux/timex.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/uaccess.h>
++#include <asm/mach/irq.h>
++#include <asm/mach/time.h>
++
++#if 1
++// for timer clock < 100MHz
++#define uSECS_PER_TICK (1000000 / APB_clock)
++#define TICKS2USECS(x) ((x) * uSECS_PER_TICK)
++#else
++// for timer clock >= 100MHz
++#define TICKS_PER_uSEC (APB_clock / 1000000)
++#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
++#endif
++
++extern u32 APB_clock;
++static u32 timer_counter_value;
++
++static inline unsigned int str9100_read_timer_counter(void)
++{
++ return TIMER1_COUNTER_REG;
++}
++
++static inline unsigned int str9100_read_timer_interrupt_status(void)
++{
++ return TIMER_INTERRUPT_STATUS_REG;
++}
++
++static inline void str9100_clear_timer_interrupt_status(unsigned int irq)
++{
++ TIMER_INTERRUPT_STATUS_REG &= ~(1 << TIMER1_OVERFLOW_INTERRUPT_BIT_INDEX);
++}
++
++static void str9100_setup_timer(unsigned int counter_value)
++{
++ unsigned long control_value;
++ unsigned long mask_value;
++
++ control_value = TIMER_CONTROL_REG;
++ mask_value = TIMER_INTERRUPT_MASK_REG;
++
++ TIMER1_COUNTER_REG = counter_value;
++ TIMER1_AUTO_RELOAD_VALUE_REG = counter_value;
++ TIMER1_MATCH_VALUE1_REG = 0;
++ TIMER1_MATCH_VALUE2_REG = 0;
++
++ // Clock Source: PCLK
++ control_value &= ~(1 << TIMER1_CLOCK_SOURCE_BIT_INDEX);
++
++ // Down Count Mode
++ control_value |= (1 << TIMER1_UP_DOWN_COUNT_BIT_INDEX);
++
++ // un-mask overflow, match2 and match1 interrupt sources
++ mask_value &= ~(0x7);
++
++ // mask match2 and match1 interrupt sources
++ mask_value |= 0x03;
++
++ TIMER_CONTROL_REG = control_value;
++ TIMER_INTERRUPT_MASK_REG = mask_value;
++}
++
++static void str9100_timer_enable(void)
++{
++ unsigned long control_value;
++
++ control_value = TIMER_CONTROL_REG;
++
++ // enable overflow mode
++ control_value |= (1 << TIMER1_OVERFLOW_ENABLE_BIT_INDEX);
++
++ // enable the timer
++ control_value |= (1 << TIMER1_ENABLE_BIT_INDEX);
++
++ TIMER_CONTROL_REG = control_value;
++}
++
++static void str9100_timer_disable(void)
++{
++ unsigned long control_value;
++
++ control_value = TIMER_CONTROL_REG;
++
++ // disable overflow mode
++ control_value &= ~(1 << TIMER1_OVERFLOW_ENABLE_BIT_INDEX);
++
++ // disable the timer
++ control_value &= ~(1 << TIMER1_ENABLE_BIT_INDEX);
++
++ TIMER_CONTROL_REG = control_value;
++}
++
++/*
++ * Returns number of us since last clock interrupt. Note that interrupts
++ * will have been disabled by do_gettimeoffset()
++ */
++static unsigned long str9100_gettimeoffset(void)
++{
++ unsigned long ticks1, ticks2;
++ unsigned long interrupt_status;
++
++ /*
++ * Get the current number of ticks. Note that there is a race
++ * condition between us reading the timer and checking for
++ * an interrupt. We get around this by ensuring that the
++ * counter has not reloaded between our two reads.
++ */
++ ticks2 = str9100_read_timer_counter();
++ do {
++ ticks1 = ticks2;
++ interrupt_status = str9100_read_timer_interrupt_status();
++ ticks2 = str9100_read_timer_counter();
++ } while (ticks2 > ticks1);
++
++ /*
++ * Number of ticks since last interrupt
++ */
++ ticks1 = timer_counter_value - ticks2;
++
++ /*
++ * Interrupt pending? If so, we've reloaded once already.
++ */
++ if (interrupt_status) {
++ ticks1 += timer_counter_value;
++ }
++
++ /*
++ * Convert the ticks to usecs
++ */
++ return TICKS2USECS(ticks1);
++}
++
++/*
++ * IRQ handler for the timer
++ */
++static irqreturn_t
++str9100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++ write_seqlock(&xtime_lock);
++
++ str9100_clear_timer_interrupt_status((unsigned int)irq);
++ /* 2008/05/12 Richard
++ timer_tick(regs);
++ */
++ timer_tick();
++
++ write_sequnlock(&xtime_lock);
++
++ return IRQ_HANDLED;
++}
++
++static struct irqaction str9100_timer_irq = {
++ .name = "STR9100 Timer Tick",
++/* 2008/05/12 Richard
++ .flags = SA_INTERRUPT | SA_TIMER,
++ */
++ .flags = IRQF_DISABLED | IRQF_TIMER,
++ .handler = str9100_timer_interrupt,
++};
++
++/*
++ * Set up timer interrupt, and return the current time in seconds.
++ */
++static void __init str9100_timer_init(void)
++{
++ /*
++ * prepare timer-related values
++ */
++ timer_counter_value = APB_clock / HZ;
++
++ /*
++ * setup timer-related values
++ */
++ str9100_setup_timer(timer_counter_value);
++
++ /*
++ * Make irqs happen for the system timer
++ */
++ setup_irq(INTC_TIMER1_BIT_INDEX, &str9100_timer_irq);
++
++ str9100_timer_enable();
++}
++
++struct sys_timer str9100_timer = {
++ .init = str9100_timer_init,
++ .offset = str9100_gettimeoffset,
++};
++
+diff -rupN linux-2.6.35.11/arch/arm/Makefile linux-2.6.35.11-ts7500/arch/arm/Makefile
+--- linux-2.6.35.11/arch/arm/Makefile 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/Makefile 2011-03-14 11:18:24.000000000 -0400
+@@ -18,6 +18,7 @@ endif
+ OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
+ GZFLAGS :=-9
+ #KBUILD_CFLAGS +=-pipe
++KBUILD_CFLAGS +=-pipe -gdwarf-2
+ # Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
+ KBUILD_CFLAGS +=$(call cc-option,-marm,)
+
+@@ -186,6 +187,10 @@ machine-$(CONFIG_MACH_SPEAR300) := spea
+ machine-$(CONFIG_MACH_SPEAR310) := spear3xx
+ machine-$(CONFIG_MACH_SPEAR320) := spear3xx
+ machine-$(CONFIG_MACH_SPEAR600) := spear6xx
++machine-$(CONFIG_ARCH_STR9100) := str9100
++machine-$(CONFIG_ARCH_STR8100) := str8100
++
++
+
+ # Platform directory name. This list is sorted alphanumerically
+ # by CONFIG_* macro name.
+diff -rupN linux-2.6.35.11/arch/arm/Makefile.orig linux-2.6.35.11-ts7500/arch/arm/Makefile.orig
+--- linux-2.6.35.11/arch/arm/Makefile.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/Makefile.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,294 @@
++#
++# arch/arm/Makefile
++#
++# This file is included by the global makefile so that you can add your own
++# architecture-specific flags and dependencies.
++#
++# 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-2001 by Russell King
++
++LDFLAGS_vmlinux :=-p --no-undefined -X
++ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
++LDFLAGS_vmlinux += --be8
++endif
++
++OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
++GZFLAGS :=-9
++#KBUILD_CFLAGS +=-pipe
++# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
++KBUILD_CFLAGS +=$(call cc-option,-marm,)
++
++# Do not use arch/arm/defconfig - it's always outdated.
++# Select a platform tht is kept up-to-date
++KBUILD_DEFCONFIG := versatile_defconfig
++
++# defines filename extension depending memory management type.
++ifeq ($(CONFIG_MMU),)
++MMUEXT := -nommu
++endif
++
++ifeq ($(CONFIG_FRAME_POINTER),y)
++KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
++endif
++
++ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
++KBUILD_CPPFLAGS += -mbig-endian
++AS += -EB
++LD += -EB
++else
++KBUILD_CPPFLAGS += -mlittle-endian
++AS += -EL
++LD += -EL
++endif
++
++comma = ,
++
++# This selects which instruction set is used.
++# Note that GCC does not numerically define an architecture version
++# macro, but instead defines a whole series of macros which makes
++# testing for a specific architecture or later rather impossible.
++arch-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7-a,-march=armv5t -Wa$(comma)-march=armv7-a)
++arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
++# Only override the compiler option if ARMv6. The ARMv6K extensions are
++# always available in ARMv7
++ifeq ($(CONFIG_CPU_32v6),y)
++arch-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k)
++endif
++arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t)
++arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t
++arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4
++arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3
++
++# This selects how we optimise for the processor.
++tune-$(CONFIG_CPU_ARM610) :=-mtune=arm610
++tune-$(CONFIG_CPU_ARM710) :=-mtune=arm710
++tune-$(CONFIG_CPU_ARM7TDMI) :=-mtune=arm7tdmi
++tune-$(CONFIG_CPU_ARM720T) :=-mtune=arm7tdmi
++tune-$(CONFIG_CPU_ARM740T) :=-mtune=arm7tdmi
++tune-$(CONFIG_CPU_ARM9TDMI) :=-mtune=arm9tdmi
++tune-$(CONFIG_CPU_ARM940T) :=-mtune=arm9tdmi
++tune-$(CONFIG_CPU_ARM946E) :=$(call cc-option,-mtune=arm9e,-mtune=arm9tdmi)
++tune-$(CONFIG_CPU_ARM920T) :=-mtune=arm9tdmi
++tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi
++tune-$(CONFIG_CPU_ARM925T) :=-mtune=arm9tdmi
++tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi
++tune-$(CONFIG_CPU_FA526) :=-mtune=arm9tdmi
++tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110
++tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
++tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
++tune-$(CONFIG_CPU_XSC3) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
++tune-$(CONFIG_CPU_FEROCEON) :=$(call cc-option,-mtune=marvell-f,-mtune=xscale)
++tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
++
++ifeq ($(CONFIG_AEABI),y)
++CFLAGS_ABI :=-mabi=aapcs-linux -mno-thumb-interwork
++else
++CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,)
++endif
++
++ifeq ($(CONFIG_ARM_UNWIND),y)
++CFLAGS_ABI +=-funwind-tables
++endif
++
++ifeq ($(CONFIG_THUMB2_KERNEL),y)
++AFLAGS_AUTOIT :=$(call as-option,-Wa$(comma)-mimplicit-it=always,-Wa$(comma)-mauto-it)
++AFLAGS_NOWARN :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W)
++CFLAGS_THUMB2 :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN)
++AFLAGS_THUMB2 :=$(CFLAGS_THUMB2) -Wa$(comma)-mthumb
++endif
++
++# Need -Uarm for gcc < 3.x
++KBUILD_CFLAGS +=$(CFLAGS_ABI) $(CFLAGS_THUMB2) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
++KBUILD_AFLAGS +=$(CFLAGS_ABI) $(AFLAGS_THUMB2) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float
++
++CHECKFLAGS += -D__arm__
++
++#Default value
++head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
++textofs-y := 0x00008000
++textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000
++# We don't want the htc bootloader to corrupt kernel during resume
++textofs-$(CONFIG_PM_H1940) := 0x00108000
++# SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memory
++ifeq ($(CONFIG_ARCH_SA1100),y)
++textofs-$(CONFIG_SA1111) := 0x00208000
++endif
++
++# Machine directory name. This list is sorted alphanumerically
++# by CONFIG_* macro name.
++machine-$(CONFIG_ARCH_AAEC2000) := aaec2000
++machine-$(CONFIG_ARCH_AT91) := at91
++machine-$(CONFIG_ARCH_BCMRING) := bcmring
++machine-$(CONFIG_ARCH_CLPS711X) := clps711x
++machine-$(CONFIG_ARCH_CNS3XXX) := cns3xxx
++machine-$(CONFIG_ARCH_DAVINCI) := davinci
++machine-$(CONFIG_ARCH_DOVE) := dove
++machine-$(CONFIG_ARCH_EBSA110) := ebsa110
++machine-$(CONFIG_ARCH_EP93XX) := ep93xx
++machine-$(CONFIG_ARCH_GEMINI) := gemini
++machine-$(CONFIG_ARCH_H720X) := h720x
++machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
++machine-$(CONFIG_ARCH_IOP13XX) := iop13xx
++machine-$(CONFIG_ARCH_IOP32X) := iop32x
++machine-$(CONFIG_ARCH_IOP33X) := iop33x
++machine-$(CONFIG_ARCH_IXP2000) := ixp2000
++machine-$(CONFIG_ARCH_IXP23XX) := ixp23xx
++machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx
++machine-$(CONFIG_ARCH_KIRKWOOD) := kirkwood
++machine-$(CONFIG_ARCH_KS8695) := ks8695
++machine-$(CONFIG_ARCH_L7200) := l7200
++machine-$(CONFIG_ARCH_LH7A40X) := lh7a40x
++machine-$(CONFIG_ARCH_LOKI) := loki
++machine-$(CONFIG_ARCH_MMP) := mmp
++machine-$(CONFIG_ARCH_MSM) := msm
++machine-$(CONFIG_ARCH_MV78XX0) := mv78xx0
++machine-$(CONFIG_ARCH_MX1) := mx1
++machine-$(CONFIG_ARCH_MX2) := mx2
++machine-$(CONFIG_ARCH_MX25) := mx25
++machine-$(CONFIG_ARCH_MX3) := mx3
++machine-$(CONFIG_ARCH_MX5) := mx5
++machine-$(CONFIG_ARCH_MXC91231) := mxc91231
++machine-$(CONFIG_ARCH_NETX) := netx
++machine-$(CONFIG_ARCH_NOMADIK) := nomadik
++machine-$(CONFIG_ARCH_NS9XXX) := ns9xxx
++machine-$(CONFIG_ARCH_OMAP1) := omap1
++machine-$(CONFIG_ARCH_OMAP2) := omap2
++machine-$(CONFIG_ARCH_OMAP3) := omap2
++machine-$(CONFIG_ARCH_OMAP4) := omap2
++machine-$(CONFIG_ARCH_ORION5X) := orion5x
++machine-$(CONFIG_ARCH_PNX4008) := pnx4008
++machine-$(CONFIG_ARCH_PXA) := pxa
++machine-$(CONFIG_ARCH_REALVIEW) := realview
++machine-$(CONFIG_ARCH_RPC) := rpc
++machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2416 s3c2440 s3c2443
++machine-$(CONFIG_ARCH_S3C24A0) := s3c24a0
++machine-$(CONFIG_ARCH_S3C64XX) := s3c64xx
++machine-$(CONFIG_ARCH_S5P6440) := s5p6440
++machine-$(CONFIG_ARCH_S5P6442) := s5p6442
++machine-$(CONFIG_ARCH_S5PC100) := s5pc100
++machine-$(CONFIG_ARCH_S5PV210) := s5pv210
++machine-$(CONFIG_ARCH_SA1100) := sa1100
++machine-$(CONFIG_ARCH_SHARK) := shark
++machine-$(CONFIG_ARCH_SHMOBILE) := shmobile
++machine-$(CONFIG_ARCH_STMP378X) := stmp378x
++machine-$(CONFIG_ARCH_STMP37XX) := stmp37xx
++machine-$(CONFIG_ARCH_U300) := u300
++machine-$(CONFIG_ARCH_U8500) := ux500
++machine-$(CONFIG_ARCH_VERSATILE) := versatile
++machine-$(CONFIG_ARCH_VEXPRESS) := vexpress
++machine-$(CONFIG_ARCH_W90X900) := w90x900
++machine-$(CONFIG_ARCH_NUC93X) := nuc93x
++machine-$(CONFIG_FOOTBRIDGE) := footbridge
++machine-$(CONFIG_MACH_SPEAR300) := spear3xx
++machine-$(CONFIG_MACH_SPEAR310) := spear3xx
++machine-$(CONFIG_MACH_SPEAR320) := spear3xx
++machine-$(CONFIG_MACH_SPEAR600) := spear6xx
++
++# Platform directory name. This list is sorted alphanumerically
++# by CONFIG_* macro name.
++plat-$(CONFIG_ARCH_MXC) := mxc
++plat-$(CONFIG_ARCH_OMAP) := omap
++plat-$(CONFIG_ARCH_S3C64XX) := samsung
++plat-$(CONFIG_ARCH_STMP3XXX) := stmp3xxx
++plat-$(CONFIG_PLAT_IOP) := iop
++plat-$(CONFIG_PLAT_NOMADIK) := nomadik
++plat-$(CONFIG_PLAT_ORION) := orion
++plat-$(CONFIG_PLAT_PXA) := pxa
++plat-$(CONFIG_PLAT_S3C24XX) := s3c24xx samsung
++plat-$(CONFIG_PLAT_S5P) := s5p samsung
++plat-$(CONFIG_PLAT_SPEAR) := spear
++plat-$(CONFIG_PLAT_VERSATILE) := versatile
++
++ifeq ($(CONFIG_ARCH_EBSA110),y)
++# This is what happens if you forget the IOCS16 line.
++# PCMCIA cards stop working.
++CFLAGS_3c589_cs.o :=-DISA_SIXTEEN_BIT_PERIPHERAL
++export CFLAGS_3c589_cs.o
++endif
++
++# The byte offset of the kernel image in RAM from the start of RAM.
++TEXT_OFFSET := $(textofs-y)
++
++# The first directory contains additional information for the boot setup code
++ifneq ($(machine-y),)
++MACHINE := arch/arm/mach-$(word 1,$(machine-y))/
++else
++MACHINE :=
++endif
++
++machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
++platdirs := $(patsubst %,arch/arm/plat-%/,$(plat-y))
++
++ifeq ($(KBUILD_SRC),)
++KBUILD_CPPFLAGS += $(patsubst %,-I%include,$(machdirs) $(platdirs))
++else
++KBUILD_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs) $(platdirs))
++endif
++
++export TEXT_OFFSET GZFLAGS MMUEXT
++
++# Do we have FASTFPE?
++FASTFPE :=arch/arm/fastfpe
++ifeq ($(FASTFPE),$(wildcard $(FASTFPE)))
++FASTFPE_OBJ :=$(FASTFPE)/
++endif
++
++# If we have a machine-specific directory, then include it in the build.
++core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
++core-y += $(machdirs) $(platdirs)
++core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/
++core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)
++core-$(CONFIG_VFP) += arch/arm/vfp/
++
++drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
++
++libs-y := arch/arm/lib/ $(libs-y)
++
++# Default target when executing plain make
++ifeq ($(CONFIG_XIP_KERNEL),y)
++KBUILD_IMAGE := xipImage
++else
++KBUILD_IMAGE := zImage
++endif
++
++all: $(KBUILD_IMAGE)
++
++boot := arch/arm/boot
++
++archprepare:
++ $(Q)$(MAKE) $(build)=arch/arm/tools include/generated/mach-types.h
++
++# Convert bzImage to zImage
++bzImage: zImage
++
++zImage Image xipImage bootpImage uImage: vmlinux
++ $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
++
++zinstall install: vmlinux
++ $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
++
++# We use MRPROPER_FILES and CLEAN_FILES now
++archclean:
++ $(Q)$(MAKE) $(clean)=$(boot)
++
++# My testing targets (bypasses dependencies)
++bp:; $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/bootpImage
++i zi:; $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
++
++
++define archhelp
++ echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
++ echo ' Image - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
++ echo '* xipImage - XIP kernel image, if configured (arch/$(ARCH)/boot/xipImage)'
++ echo ' uImage - U-Boot wrapped zImage'
++ echo ' bootpImage - Combined zImage and initial RAM disk'
++ echo ' (supply initrd image via make variable INITRD=<path>)'
++ echo ' install - Install uncompressed kernel'
++ echo ' zinstall - Install compressed kernel'
++ echo ' Install using (your) ~/bin/$(INSTALLKERNEL) or'
++ echo ' (distribution) /sbin/$(INSTALLKERNEL) or'
++ echo ' install to $$(INSTALL_PATH) and run lilo'
++endef
+diff -rupN linux-2.6.35.11/arch/arm/mm/cache-fa.S linux-2.6.35.11-ts7500/arch/arm/mm/cache-fa.S
+--- linux-2.6.35.11/arch/arm/mm/cache-fa.S 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mm/cache-fa.S 2011-03-14 11:18:24.000000000 -0400
+@@ -1,3 +1,4 @@
++#if (1)
+ /*
+ * linux/arch/arm/mm/cache-fa.S
+ *
+@@ -34,6 +35,7 @@
+ #define CACHE_DSIZE 16384
+ #endif
+
++
+ /* FIXME: put optimal value here. Current one is just estimation */
+ #define CACHE_DLIMIT (CACHE_DSIZE * 2)
+
+@@ -142,7 +144,9 @@ ENTRY(fa_flush_kern_dcache_area)
+ cmp r0, r1
+ blo 1b
+ mov r0, #0
++/*
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
++*/
+ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
+ mov pc, lr
+
+@@ -157,7 +161,7 @@ ENTRY(fa_flush_kern_dcache_area)
+ * - start - virtual start address
+ * - end - virtual end address
+ */
+-fa_dma_inv_range:
++ENTRY(fa_dma_inv_range)
+ tst r0, #CACHE_DLINESIZE - 1
+ bic r0, r0, #CACHE_DLINESIZE - 1
+ mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D entry
+@@ -180,7 +184,7 @@ fa_dma_inv_range:
+ * - start - virtual start address
+ * - end - virtual end address
+ */
+-fa_dma_clean_range:
++ENTRY(fa_dma_clean_range)
+ bic r0, r0, #CACHE_DLINESIZE - 1
+ 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
+ add r0, r0, #CACHE_DLINESIZE
+@@ -229,6 +233,10 @@ ENTRY(fa_dma_unmap_area)
+ mov pc, lr
+ ENDPROC(fa_dma_unmap_area)
+
++
++
++
++
+ __INITDATA
+
+ .type fa_cache_fns, #object
+@@ -243,3 +251,408 @@ ENTRY(fa_cache_fns)
+ .long fa_dma_unmap_area
+ .long fa_dma_flush_range
+ .size fa_cache_fns, . - fa_cache_fns
++#else
++
++/* Most of the following is from 2.6.24-cavium */
++
++/*
++ * linux/arch/arm/mm/cache-fa.S
++ *
++ * Copyright (C) 2005 Faraday Corp.
++ *
++ * 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.
++ *
++ * Processors: FA520 FA526 FA626
++ * 03/31/2005 : Luke Lee created, modified from cache-v4wb.S
++ * 04/06/2005 : 1. Read CR0-1 and determine the cache size dynamically,
++ * to suit all Faraday CPU series
++ * 2. Fixed all functions
++ * 04/08/2005 : insert CONFIG_CPU_ICACHE_DISABLE and CONFIG_CPU_DCACHE_DISABLE
++ * 04/12/2005 : TODO: make this processor dependent or a self-modifying code to
++ * inline cache len/size info into the instructions, as reading cache
++ * size and len info in memory could cause another cache miss.
++ * 05/05/2005 : Modify fa_flush_user_cache_range to comply APCS.
++ * 05/19/2005 : Adjust for boundary conditions.
++ */
++//#include <linux/config.h>
++#include <linux/linkage.h>
++#include <linux/init.h>
++#include <mach/hardware.h>
++#include <asm/page.h>
++#include "proc-macros.S"
++
++#define CACHE_DLINESIZE 16
++#define CACHE_DSIZE 16384
++#define CACHE_ILINESIZE 16
++#define CACHE_ISIZE 16384
++
++/*
++ * initialize_cache_info()
++ *
++ * Automatic detection of DSIZE, DLEN, ISIZE, ILEN variables according to
++ * system register CR0-1
++ * Destroyed register: r0, r1, r2, r3, ip
++ */
++ .align
++ENTRY(fa_initialize_cache_info)
++ mov r3, #1 @ r3 always = 1
++ adr ip, __fa_cache_ilen
++
++ mrc p15, 0, r0, c0, c0, 1
++ /* ILEN */
++ and r1, r0, #3 @ bits [1:0]
++ add r1, r1, #3 @ cache line size is at least 8 bytes (2^3)
++ mov r2, r3, lsl r1 @ r2 = 1<<r1
++ str r2, [ip], #4
++ /* ISIZE */
++ mov r1, r0, lsr #6 @ bits [8:6]
++ and r1, r1, #7
++ add r1, r1, #9 @ cache size is at least 512 bytes (2^9)
++ mov r2, r3, lsl r1
++ str r2, [ip], #4
++ /* DLEN */
++ mov r1, r0, lsr #12
++ and r1, r1, #3 @ bits [13:12]
++ add r1, r1, #3 @ cache line size is at least 8 bytes (2^3)
++ mov r2, r3, lsl r1 @ r2 = 1<<r1
++ str r2, [ip], #4
++ /* DSIZE */
++ mov r1, r0, lsr #18 @ bits [20:18]
++ and r1, r1, #7
++ add r1, r1, #9 @ cache size is at least 512 bytes (2^9)
++ mov r2, r3, lsl r1
++ str r2, [ip]
++ mov pc, lr
++
++ /* Warning : Do not change the order ! Successive codes depends on this */
++ .align
++ .globl __fa_cache_ilen, __fa_cache_isize, __fa_cache_dlen, __fa_cache_dsize
++__fa_cache_ilen:
++ .word 0 @ instruction cache line length
++__fa_cache_isize:
++ .word 0 @ instruction cache size
++__fa_cache_dlen:
++ .word 0 @ data cahce line length
++__fa_cache_dsize:
++ .word 0 @ data cache size
++
++/*
++ * flush_user_cache_all()
++ *
++ * Clean and invalidate all cache entries in a particular address
++ * space.
++ */
++ENTRY(fa_flush_user_cache_all)
++ /* FALLTHROUGH */
++/*
++ * flush_kern_cache_all()
++ *
++ * Clean and invalidate the entire cache.
++ */
++ENTRY(fa_flush_kern_cache_all)
++ mov ip, #0
++
++#ifndef CONFIG_CPU_ICACHE_DISABLE
++ mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
++#endif
++
++__flush_whole_cache:
++
++#ifndef CONFIG_CPU_DCACHE_DISABLE
++ mov ip, #0
++# ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++ mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
++# else
++ mcr p15, 0, ip, c7,c14, 0 @ clean/invalidate D cache
++# endif
++#endif /*CONFIG_CPU_DCACHE_DISABLE*/
++
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++ mcr p15, 0, ip, c7, c10, 4 @ drain write buffer
++#endif
++
++#ifdef CONFIG_CPU_FA_BTB
++ mcr p15, 0, ip, c7, c5, 6 @ invalidate BTB
++ nop
++ nop
++#endif
++
++ mov pc, lr
++
++/*
++ * flush_user_cache_range(start, end, flags)
++ *
++ * Invalidate a range of cache entries in the specified
++ * address space.
++ *
++ * - start - start address (inclusive, page aligned)
++ * - end - end address (exclusive, page aligned)
++ * - flags - vma_area_struct flags describing address space
++ */
++ENTRY(fa_flush_user_cache_range)
++ mov ip, #0
++ sub r3, r1, r0 @ calculate total size
++#ifndef CONFIG_CPU_ICACHE_DISABLE
++ tst r2, #VM_EXEC @ executable region?
++ mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
++#endif
++
++#ifndef CONFIG_CPU_DCACHE_DISABLE
++ cmp r3, #CACHE_DSIZE @ total size >= limit?
++ bhs __flush_whole_cache @ flush whole D cache
++
++1:
++
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
++#else
++ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
++#endif
++ add r0, r0, #CACHE_DLINESIZE
++ cmp r0, r1
++ bls 1b
++#endif /* CONFIG_CPU_DCACHE_DISABLE */
++
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++ tst r2, #VM_EXEC
++ mcreq p15, 0, r4, c7, c10, 4 @ drain write buffer
++#endif
++
++#ifdef CONFIG_CPU_FA_BTB
++ tst r2, #VM_EXEC
++ mov ip, #0
++ mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB
++ nop
++ nop
++#endif
++ mov pc, lr
++
++/*
++ * flush_kern_dcache_page(void *page)
++ *
++ * Ensure no D cache aliasing occurs, either with itself or
++ * the I cache
++ *
++ * - addr - page aligned address
++ */
++ENTRY(fa_flush_kern_dcache_page)
++ add r1, r0, #PAGE_SZ
++ /* fall through */
++
++/*
++ * coherent_kern_range(start, end)
++ *
++ * Ensure coherency between the Icache and the Dcache in the
++ * region described by start. If you have non-snooping
++ * Harvard caches, you need to implement this function.
++ *
++ * - start - virtual start address
++ * - end - virtual end address
++ */
++ENTRY(fa_coherent_kern_range)
++ /* fall through */
++
++/*
++ * coherent_user_range(start, end)
++ *
++ * Ensure coherency between the Icache and the Dcache in the
++ * region described by start. If you have non-snooping
++ * Harvard caches, you need to implement this function.
++ *
++ * - start - virtual start address
++ * - end - virtual end address
++ */
++ENTRY(fa_coherent_user_range)
++ bic r0, r0, #CACHE_DLINESIZE-1
++
++#if !(defined(CONFIG_CPU_DCACHE_DISABLE) && defined(CONFIG_CPU_ICACHE_DISABLE))
++1:
++#ifndef CONFIG_CPU_DCACHE_DISABLE
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++ mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
++#else
++ mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
++#endif
++#endif /* CONFIG_CPU_DCACHE_DISABLE */
++
++#ifndef CONFIG_CPU_ICACHE_DISABLE
++ mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
++#endif
++ add r0, r0, #CACHE_DLINESIZE
++ cmp r0, r1
++ bls 1b @ Luke Lee 05/19/2005 blo->bls
++#endif /* !(defined(CONFIG_CPU_DCACHE_DISABLE) && defined(CONFIG_CPU_ICACHE_DISABLE)) */
++
++ mov ip, #0
++#ifdef CONFIG_CPU_FA_BTB
++ mcr p15, 0, ip, c7, c5, 6 @ invalidate BTB
++ nop
++ nop
++#endif
++
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++ mcr p15, 0, ip, c7, c10, 4 @ drain WB
++#endif
++
++ mov pc, lr
++
++/*
++ * dma_inv_range(start, end)
++ *
++ * Invalidate (discard) the specified virtual address range.
++ * May not write back any entries. If 'start' or 'end'
++ * are not cache line aligned, those lines must be written
++ * back.
++ *
++ * - start - virtual start address
++ * - end - virtual end address
++ */
++ENTRY(fa_dma_inv_range)
++
++#ifndef CONFIG_CPU_DCACHE_DISABLE
++
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++ tst r0, #CACHE_DLINESIZE -1
++ bic r0, r0, #CACHE_DLINESIZE -1
++ mcrne p15, 0, r0, c7, c10, 1 @ clean boundary D entry
++ mcr p15, 0, r1, c7, c10, 1 @ clean boundary D entry
++#else
++ bic r0, r0, #CACHE_DLINESIZE -1
++#endif
++
++1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
++ add r0, r0, #CACHE_DLINESIZE
++ cmp r0, r1
++ bls 1b @ Luke Lee 05/19/2005 blo->bls
++#endif /* CONFIG_CPU_DCACHE_DISABLE */
++
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++ mov r0, #0
++ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
++#endif
++ mov pc, lr
++
++
++
++
++
++
++
++
++/***** The following was lifted from 2.6.34 */
++/*
++ * flush_kern_dcache_area(void *addr, size_t size)
++ *
++ * Ensure that the data held in the page kaddr is written back
++ * to the page in question.
++ *
++ * - addr - kernel address
++ * - size - size of region
++ */
++ENTRY(fa_flush_kern_dcache_area)
++ add r1, r0, r1
++1: mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line
++ add r0, r0, #CACHE_DLINESIZE
++ cmp r0, r1
++ blo 1b
++ mov r0, #0
++ mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
++ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
++ mov pc, lr
++
++/*
++ * dma_map_area(start, size, dir)
++ * - start - kernel virtual start address
++ * - size - size of region
++ * - dir - DMA direction
++ */
++ENTRY(fa_dma_map_area)
++ add r1, r1, r0
++ cmp r2, #DMA_TO_DEVICE
++ beq fa_dma_clean_range
++ bcs fa_dma_inv_range
++ b fa_dma_flush_range
++ENDPROC(fa_dma_map_area)
++
++/*
++ * dma_unmap_area(start, size, dir)
++ * - start - kernel virtual start address
++ * - size - size of region
++ * - dir - DMA direction
++ */
++ENTRY(fa_dma_unmap_area)
++ mov pc, lr
++ENDPROC(fa_dma_unmap_area)
++
++
++/********************/
++
++
++
++
++
++
++
++
++
++/*
++ * dma_clean_range(start, end)
++ *
++ * Clean (write back) the specified virtual address range.
++ *
++ * - start - virtual start address
++ * - end - virtual end address
++ */
++ENTRY(fa_dma_clean_range)
++
++#ifndef CONFIG_CPU_DCACHE_DISABLE
++
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++ bic r0, r0, #CACHE_DLINESIZE - 1
++1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
++ add r0, r0, #CACHE_DLINESIZE
++ cmp r0, r1
++ bls 1b @ Luke Lee 05/19/2005 blo->bls
++
++#endif
++#endif /* CONFIG_CPU_DCACHE_DISABLE */
++
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++ mov r0, #0
++ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
++#endif
++ mov pc, lr
++
++/*
++ * dma_flush_range(start, end)
++ *
++ * Clean and invalidate the specified virtual address range.
++ *
++ * - start - virtual start address
++ * - end - virtual end address
++ *
++ * This is actually the same as fa_coherent_kern_range()
++ */
++ .globl fa_dma_flush_range
++ .set fa_dma_flush_range, fa_coherent_kern_range
++
++ __INITDATA
++
++ .type fa_cache_fns, #object
++ENTRY(fa_cache_fns)
++ .long fa_flush_kern_cache_all
++ .long fa_flush_user_cache_all
++ .long fa_flush_user_cache_range
++ .long fa_coherent_kern_range
++ .long fa_coherent_user_range
++ .long fa_flush_kern_dcache_page
++ .long fa_dma_inv_range
++ .long fa_dma_clean_range
++ .long fa_dma_flush_range
++ .size fa_cache_fns, . - fa_cache_fns
++
++
++
++#endif
+diff -rupN linux-2.6.35.11/arch/arm/mm/copypage-fa.c linux-2.6.35.11-ts7500/arch/arm/mm/copypage-fa.c
+--- linux-2.6.35.11/arch/arm/mm/copypage-fa.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mm/copypage-fa.c 2011-03-14 11:18:24.000000000 -0400
+@@ -14,6 +14,7 @@
+ #include <linux/init.h>
+ #include <linux/highmem.h>
+
++#include <asm/page.h>
+ /*
+ * Faraday optimised copy_user_page
+ */
+diff -rupN linux-2.6.35.11/arch/arm/mm/dma-mapping.c linux-2.6.35.11-ts7500/arch/arm/mm/dma-mapping.c
+--- linux-2.6.35.11/arch/arm/mm/dma-mapping.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mm/dma-mapping.c 2011-03-14 11:18:24.000000000 -0400
+@@ -576,7 +576,8 @@ EXPORT_SYMBOL(dma_unmap_sg);
+ * @nents: number of buffers to map (returned from dma_map_sg)
+ * @dir: DMA transfer direction (same as was passed to dma_map_sg)
+ */
+-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
++void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist
++*sg,
+ int nents, enum dma_data_direction dir)
+ {
+ struct scatterlist *s;
+diff -rupN linux-2.6.35.11/arch/arm/mm/dma-mapping.c.orig linux-2.6.35.11-ts7500/arch/arm/mm/dma-mapping.c.orig
+--- linux-2.6.35.11/arch/arm/mm/dma-mapping.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mm/dma-mapping.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,618 @@
++/*
++ * linux/arch/arm/mm/dma-mapping.c
++ *
++ * Copyright (C) 2000-2004 Russell King
++ *
++ * 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.
++ *
++ * DMA uncached mapping support.
++ */
++#include <linux/module.h>
++#include <linux/mm.h>
++#include <linux/gfp.h>
++#include <linux/errno.h>
++#include <linux/list.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++
++#include <asm/memory.h>
++#include <asm/highmem.h>
++#include <asm/cacheflush.h>
++#include <asm/tlbflush.h>
++#include <asm/sizes.h>
++
++static u64 get_coherent_dma_mask(struct device *dev)
++{
++ u64 mask = ISA_DMA_THRESHOLD;
++
++ if (dev) {
++ mask = dev->coherent_dma_mask;
++
++ /*
++ * Sanity check the DMA mask - it must be non-zero, and
++ * must be able to be satisfied by a DMA allocation.
++ */
++ if (mask == 0) {
++ dev_warn(dev, "coherent DMA mask is unset\n");
++ return 0;
++ }
++
++ if ((~mask) & ISA_DMA_THRESHOLD) {
++ dev_warn(dev, "coherent DMA mask %#llx is smaller "
++ "than system GFP_DMA mask %#llx\n",
++ mask, (unsigned long long)ISA_DMA_THRESHOLD);
++ return 0;
++ }
++ }
++
++ return mask;
++}
++
++/*
++ * Allocate a DMA buffer for 'dev' of size 'size' using the
++ * specified gfp mask. Note that 'size' must be page aligned.
++ */
++static struct page *__dma_alloc_buffer(struct device *dev, size_t size, gfp_t gfp)
++{
++ unsigned long order = get_order(size);
++ struct page *page, *p, *e;
++ void *ptr;
++ u64 mask = get_coherent_dma_mask(dev);
++
++#ifdef CONFIG_DMA_API_DEBUG
++ u64 limit = (mask + 1) & ~mask;
++ if (limit && size >= limit) {
++ dev_warn(dev, "coherent allocation too big (requested %#x mask %#llx)\n",
++ size, mask);
++ return NULL;
++ }
++#endif
++
++ if (!mask)
++ return NULL;
++
++ if (mask < 0xffffffffULL)
++ gfp |= GFP_DMA;
++
++ page = alloc_pages(gfp, order);
++ if (!page)
++ return NULL;
++
++ /*
++ * Now split the huge page and free the excess pages
++ */
++ split_page(page, order);
++ for (p = page + (size >> PAGE_SHIFT), e = page + (1 << order); p < e; p++)
++ __free_page(p);
++
++ /*
++ * Ensure that the allocated pages are zeroed, and that any data
++ * lurking in the kernel direct-mapped region is invalidated.
++ */
++ ptr = page_address(page);
++ memset(ptr, 0, size);
++ dmac_flush_range(ptr, ptr + size);
++ outer_flush_range(__pa(ptr), __pa(ptr) + size);
++
++ return page;
++}
++
++/*
++ * Free a DMA buffer. 'size' must be page aligned.
++ */
++static void __dma_free_buffer(struct page *page, size_t size)
++{
++ struct page *e = page + (size >> PAGE_SHIFT);
++
++ while (page < e) {
++ __free_page(page);
++ page++;
++ }
++}
++
++#ifdef CONFIG_MMU
++/* Sanity check size */
++#if (CONSISTENT_DMA_SIZE % SZ_2M)
++#error "CONSISTENT_DMA_SIZE must be multiple of 2MiB"
++#endif
++
++#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
++#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT)
++#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT)
++
++/*
++ * These are the page tables (2MB each) covering uncached, DMA consistent allocations
++ */
++static pte_t *consistent_pte[NUM_CONSISTENT_PTES];
++
++#include "vmregion.h"
++
++static struct arm_vmregion_head consistent_head = {
++ .vm_lock = __SPIN_LOCK_UNLOCKED(&consistent_head.vm_lock),
++ .vm_list = LIST_HEAD_INIT(consistent_head.vm_list),
++ .vm_start = CONSISTENT_BASE,
++ .vm_end = CONSISTENT_END,
++};
++
++#ifdef CONFIG_HUGETLB_PAGE
++#error ARM Coherent DMA allocator does not (yet) support huge TLB
++#endif
++
++/*
++ * Initialise the consistent memory allocation.
++ */
++static int __init consistent_init(void)
++{
++ int ret = 0;
++ pgd_t *pgd;
++ pmd_t *pmd;
++ pte_t *pte;
++ int i = 0;
++ u32 base = CONSISTENT_BASE;
++
++ do {
++ pgd = pgd_offset(&init_mm, base);
++ pmd = pmd_alloc(&init_mm, pgd, base);
++ if (!pmd) {
++ printk(KERN_ERR "%s: no pmd tables\n", __func__);
++ ret = -ENOMEM;
++ break;
++ }
++ WARN_ON(!pmd_none(*pmd));
++
++ pte = pte_alloc_kernel(pmd, base);
++ if (!pte) {
++ printk(KERN_ERR "%s: no pte tables\n", __func__);
++ ret = -ENOMEM;
++ break;
++ }
++
++ consistent_pte[i++] = pte;
++ base += (1 << PGDIR_SHIFT);
++ } while (base < CONSISTENT_END);
++
++ return ret;
++}
++
++core_initcall(consistent_init);
++
++static void *
++__dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot)
++{
++ struct arm_vmregion *c;
++
++ if (!consistent_pte[0]) {
++ printk(KERN_ERR "%s: not initialised\n", __func__);
++ dump_stack();
++ return NULL;
++ }
++
++ /*
++ * Allocate a virtual address in the consistent mapping region.
++ */
++ c = arm_vmregion_alloc(&consistent_head, size,
++ gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
++ if (c) {
++ pte_t *pte;
++ int idx = CONSISTENT_PTE_INDEX(c->vm_start);
++ u32 off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);
++
++ pte = consistent_pte[idx] + off;
++ c->vm_pages = page;
++
++ do {
++ BUG_ON(!pte_none(*pte));
++
++ set_pte_ext(pte, mk_pte(page, prot), 0);
++ page++;
++ pte++;
++ off++;
++ if (off >= PTRS_PER_PTE) {
++ off = 0;
++ pte = consistent_pte[++idx];
++ }
++ } while (size -= PAGE_SIZE);
++
++ return (void *)c->vm_start;
++ }
++ return NULL;
++}
++
++static void __dma_free_remap(void *cpu_addr, size_t size)
++{
++ struct arm_vmregion *c;
++ unsigned long addr;
++ pte_t *ptep;
++ int idx;
++ u32 off;
++
++ c = arm_vmregion_find_remove(&consistent_head, (unsigned long)cpu_addr);
++ if (!c) {
++ printk(KERN_ERR "%s: trying to free invalid coherent area: %p\n",
++ __func__, cpu_addr);
++ dump_stack();
++ return;
++ }
++
++ if ((c->vm_end - c->vm_start) != size) {
++ printk(KERN_ERR "%s: freeing wrong coherent size (%ld != %d)\n",
++ __func__, c->vm_end - c->vm_start, size);
++ dump_stack();
++ size = c->vm_end - c->vm_start;
++ }
++
++ idx = CONSISTENT_PTE_INDEX(c->vm_start);
++ off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);
++ ptep = consistent_pte[idx] + off;
++ addr = c->vm_start;
++ do {
++ pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
++
++ ptep++;
++ addr += PAGE_SIZE;
++ off++;
++ if (off >= PTRS_PER_PTE) {
++ off = 0;
++ ptep = consistent_pte[++idx];
++ }
++
++ if (pte_none(pte) || !pte_present(pte))
++ printk(KERN_CRIT "%s: bad page in kernel page table\n",
++ __func__);
++ } while (size -= PAGE_SIZE);
++
++ flush_tlb_kernel_range(c->vm_start, c->vm_end);
++
++ arm_vmregion_free(&consistent_head, c);
++}
++
++#else /* !CONFIG_MMU */
++
++#define __dma_alloc_remap(page, size, gfp, prot) page_address(page)
++#define __dma_free_remap(addr, size) do { } while (0)
++
++#endif /* CONFIG_MMU */
++
++static void *
++__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
++ pgprot_t prot)
++{
++ struct page *page;
++ void *addr;
++
++ *handle = ~0;
++ size = PAGE_ALIGN(size);
++
++ page = __dma_alloc_buffer(dev, size, gfp);
++ if (!page)
++ return NULL;
++
++ if (!arch_is_coherent())
++ addr = __dma_alloc_remap(page, size, gfp, prot);
++ else
++ addr = page_address(page);
++
++ if (addr)
++ *handle = page_to_dma(dev, page);
++
++ return addr;
++}
++
++/*
++ * Allocate DMA-coherent memory space and return both the kernel remapped
++ * virtual and bus address for that space.
++ */
++void *
++dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
++{
++ void *memory;
++
++ if (dma_alloc_from_coherent(dev, size, handle, &memory))
++ return memory;
++
++ return __dma_alloc(dev, size, handle, gfp,
++ pgprot_dmacoherent(pgprot_kernel));
++}
++EXPORT_SYMBOL(dma_alloc_coherent);
++
++/*
++ * Allocate a writecombining region, in much the same way as
++ * dma_alloc_coherent above.
++ */
++void *
++dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
++{
++ return __dma_alloc(dev, size, handle, gfp,
++ pgprot_writecombine(pgprot_kernel));
++}
++EXPORT_SYMBOL(dma_alloc_writecombine);
++
++static int dma_mmap(struct device *dev, struct vm_area_struct *vma,
++ void *cpu_addr, dma_addr_t dma_addr, size_t size)
++{
++ int ret = -ENXIO;
++#ifdef CONFIG_MMU
++ unsigned long user_size, kern_size;
++ struct arm_vmregion *c;
++
++ user_size = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
++
++ c = arm_vmregion_find(&consistent_head, (unsigned long)cpu_addr);
++ if (c) {
++ unsigned long off = vma->vm_pgoff;
++
++ kern_size = (c->vm_end - c->vm_start) >> PAGE_SHIFT;
++
++ if (off < kern_size &&
++ user_size <= (kern_size - off)) {
++ ret = remap_pfn_range(vma, vma->vm_start,
++ page_to_pfn(c->vm_pages) + off,
++ user_size << PAGE_SHIFT,
++ vma->vm_page_prot);
++ }
++ }
++#endif /* CONFIG_MMU */
++
++ return ret;
++}
++
++int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
++ void *cpu_addr, dma_addr_t dma_addr, size_t size)
++{
++ vma->vm_page_prot = pgprot_dmacoherent(vma->vm_page_prot);
++ return dma_mmap(dev, vma, cpu_addr, dma_addr, size);
++}
++EXPORT_SYMBOL(dma_mmap_coherent);
++
++int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma,
++ void *cpu_addr, dma_addr_t dma_addr, size_t size)
++{
++ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
++ return dma_mmap(dev, vma, cpu_addr, dma_addr, size);
++}
++EXPORT_SYMBOL(dma_mmap_writecombine);
++
++/*
++ * free a page as defined by the above mapping.
++ * Must not be called with IRQs disabled.
++ */
++void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle)
++{
++ WARN_ON(irqs_disabled());
++
++ if (dma_release_from_coherent(dev, get_order(size), cpu_addr))
++ return;
++
++ size = PAGE_ALIGN(size);
++
++ if (!arch_is_coherent())
++ __dma_free_remap(cpu_addr, size);
++
++ __dma_free_buffer(dma_to_page(dev, handle), size);
++}
++EXPORT_SYMBOL(dma_free_coherent);
++
++/*
++ * Make an area consistent for devices.
++ * Note: Drivers should NOT use this function directly, as it will break
++ * platforms with CONFIG_DMABOUNCE.
++ * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
++ */
++void ___dma_single_cpu_to_dev(const void *kaddr, size_t size,
++ enum dma_data_direction dir)
++{
++ unsigned long paddr;
++
++ BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1));
++
++ dmac_map_area(kaddr, size, dir);
++
++ paddr = __pa(kaddr);
++ if (dir == DMA_FROM_DEVICE) {
++ outer_inv_range(paddr, paddr + size);
++ } else {
++ outer_clean_range(paddr, paddr + size);
++ }
++ /* FIXME: non-speculating: flush on bidirectional mappings? */
++}
++EXPORT_SYMBOL(___dma_single_cpu_to_dev);
++
++void ___dma_single_dev_to_cpu(const void *kaddr, size_t size,
++ enum dma_data_direction dir)
++{
++ BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1));
++
++ /* FIXME: non-speculating: not required */
++ /* don't bother invalidating if DMA to device */
++ if (dir != DMA_TO_DEVICE) {
++ unsigned long paddr = __pa(kaddr);
++ outer_inv_range(paddr, paddr + size);
++ }
++
++ dmac_unmap_area(kaddr, size, dir);
++}
++EXPORT_SYMBOL(___dma_single_dev_to_cpu);
++
++static void dma_cache_maint_page(struct page *page, unsigned long offset,
++ size_t size, enum dma_data_direction dir,
++ void (*op)(const void *, size_t, int))
++{
++ /*
++ * A single sg entry may refer to multiple physically contiguous
++ * pages. But we still need to process highmem pages individually.
++ * If highmem is not configured then the bulk of this loop gets
++ * optimized out.
++ */
++ size_t left = size;
++ do {
++ size_t len = left;
++ void *vaddr;
++
++ if (PageHighMem(page)) {
++ if (len + offset > PAGE_SIZE) {
++ if (offset >= PAGE_SIZE) {
++ page += offset / PAGE_SIZE;
++ offset %= PAGE_SIZE;
++ }
++ len = PAGE_SIZE - offset;
++ }
++ vaddr = kmap_high_get(page);
++ if (vaddr) {
++ vaddr += offset;
++ op(vaddr, len, dir);
++ kunmap_high(page);
++ } else if (cache_is_vipt()) {
++ pte_t saved_pte;
++ vaddr = kmap_high_l1_vipt(page, &saved_pte);
++ op(vaddr + offset, len, dir);
++ kunmap_high_l1_vipt(page, saved_pte);
++ }
++ } else {
++ vaddr = page_address(page) + offset;
++ op(vaddr, len, dir);
++ }
++ offset = 0;
++ page++;
++ left -= len;
++ } while (left);
++}
++
++void ___dma_page_cpu_to_dev(struct page *page, unsigned long off,
++ size_t size, enum dma_data_direction dir)
++{
++ unsigned long paddr;
++
++ dma_cache_maint_page(page, off, size, dir, dmac_map_area);
++
++ paddr = page_to_phys(page) + off;
++ if (dir == DMA_FROM_DEVICE) {
++ outer_inv_range(paddr, paddr + size);
++ } else {
++ outer_clean_range(paddr, paddr + size);
++ }
++ /* FIXME: non-speculating: flush on bidirectional mappings? */
++}
++EXPORT_SYMBOL(___dma_page_cpu_to_dev);
++
++void ___dma_page_dev_to_cpu(struct page *page, unsigned long off,
++ size_t size, enum dma_data_direction dir)
++{
++ unsigned long paddr = page_to_phys(page) + off;
++
++ /* FIXME: non-speculating: not required */
++ /* don't bother invalidating if DMA to device */
++ if (dir != DMA_TO_DEVICE)
++ outer_inv_range(paddr, paddr + size);
++
++ dma_cache_maint_page(page, off, size, dir, dmac_unmap_area);
++}
++EXPORT_SYMBOL(___dma_page_dev_to_cpu);
++
++/**
++ * dma_map_sg - map a set of SG buffers for streaming mode DMA
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @sg: list of buffers
++ * @nents: number of buffers to map
++ * @dir: DMA transfer direction
++ *
++ * Map a set of buffers described by scatterlist in streaming mode for DMA.
++ * This is the scatter-gather version of the dma_map_single interface.
++ * Here the scatter gather list elements are each tagged with the
++ * appropriate dma address and length. They are obtained via
++ * sg_dma_{address,length}.
++ *
++ * Device ownership issues as mentioned for dma_map_single are the same
++ * here.
++ */
++int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction dir)
++{
++ struct scatterlist *s;
++ int i, j;
++
++ for_each_sg(sg, s, nents, i) {
++ s->dma_address = dma_map_page(dev, sg_page(s), s->offset,
++ s->length, dir);
++ if (dma_mapping_error(dev, s->dma_address))
++ goto bad_mapping;
++ }
++ return nents;
++
++ bad_mapping:
++ for_each_sg(sg, s, i, j)
++ dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
++ return 0;
++}
++EXPORT_SYMBOL(dma_map_sg);
++
++/**
++ * dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @sg: list of buffers
++ * @nents: number of buffers to unmap (returned from dma_map_sg)
++ * @dir: DMA transfer direction (same as was passed to dma_map_sg)
++ *
++ * Unmap a set of streaming mode DMA translations. Again, CPU access
++ * rules concerning calls here are the same as for dma_unmap_single().
++ */
++void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction dir)
++{
++ struct scatterlist *s;
++ int i;
++
++ for_each_sg(sg, s, nents, i)
++ dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
++}
++EXPORT_SYMBOL(dma_unmap_sg);
++
++/**
++ * dma_sync_sg_for_cpu
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @sg: list of buffers
++ * @nents: number of buffers to map (returned from dma_map_sg)
++ * @dir: DMA transfer direction (same as was passed to dma_map_sg)
++ */
++void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
++ int nents, enum dma_data_direction dir)
++{
++ struct scatterlist *s;
++ int i;
++
++ for_each_sg(sg, s, nents, i) {
++ if (!dmabounce_sync_for_cpu(dev, sg_dma_address(s), 0,
++ sg_dma_len(s), dir))
++ continue;
++
++ __dma_page_dev_to_cpu(sg_page(s), s->offset,
++ s->length, dir);
++ }
++}
++EXPORT_SYMBOL(dma_sync_sg_for_cpu);
++
++/**
++ * dma_sync_sg_for_device
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @sg: list of buffers
++ * @nents: number of buffers to map (returned from dma_map_sg)
++ * @dir: DMA transfer direction (same as was passed to dma_map_sg)
++ */
++void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
++ int nents, enum dma_data_direction dir)
++{
++ struct scatterlist *s;
++ int i;
++
++ for_each_sg(sg, s, nents, i) {
++ if (!dmabounce_sync_for_device(dev, sg_dma_address(s), 0,
++ sg_dma_len(s), dir))
++ continue;
++
++ __dma_page_cpu_to_dev(sg_page(s), s->offset,
++ s->length, dir);
++ }
++}
++EXPORT_SYMBOL(dma_sync_sg_for_device);
+diff -rupN linux-2.6.35.11/arch/arm/mm/flush.c linux-2.6.35.11-ts7500/arch/arm/mm/flush.c
+--- linux-2.6.35.11/arch/arm/mm/flush.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mm/flush.c 2011-03-14 11:18:24.000000000 -0400
+@@ -290,7 +290,7 @@ void __flush_anon_page(struct vm_area_st
+ * userspace address only.
+ */
+ flush_pfn_alias(pfn, vmaddr);
+- __flush_icache_all();
++ __flush_icache_all();
+ }
+
+ /*
+diff -rupN linux-2.6.35.11/arch/arm/mm/Kconfig linux-2.6.35.11-ts7500/arch/arm/mm/Kconfig
+--- linux-2.6.35.11/arch/arm/mm/Kconfig 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mm/Kconfig 2011-03-14 11:18:24.000000000 -0400
+@@ -142,6 +142,54 @@ config CPU_ARM922T
+ Say Y if you want support for the ARM922T processor.
+ Otherwise, say N.
+
++# FA520/FA526/FA626
++
++choice
++ prompt "Faraday processor (ARM9 compatible) type"
++ default CPU_FA526
++ depends on ARCH_STR9100 || ARCH_STR8100
++
++#config CPU_FA520
++# bool "FA520 processor"
++# depends on ARCH_STR9100 || ARCH_STR8100
++# select CPU_32v4
++# select CPU_ABRT_EV4
++# select CPU_CACHE_FA
++# select CPU_CACHE_VIVT
++# select CPU_COPY_V4WB
++# select CPU_TLB_FA
++# help
++# //TODO: FA520 help info
++
++config CPU_FA526
++ bool "FA526 processor"
++ depends on ARCH_STR9100 || ARCH_STR8100
++ select CPU_32v4
++ select CPU_PABRT_LEGACY
++ select CPU_ABRT_EV4
++ select CPU_CP15_MMU
++ select CPU_CACHE_FA
++ select CPU_CACHE_VIVT
++ select CPU_COPY_FA if MMU
++ select CPU_TLB_FA if MMU
++ help
++ //TODO: FA526 help info
++
++#config CPU_FA626
++# bool "FA626 processor"
++# depends on ARCH_STR9100 || ARCH_STR8100
++# select CPU_32v4
++# select CPU_ABRT_EV4
++# select CPU_CACHE_FA
++# select CPU_CACHE_VIPT
++# select CPU_COPY_V4WB
++# select CPU_TLB_FA
++# help
++# //TODO: FA626 help info
++
++endchoice
++
++
+ # ARM925T
+ config CPU_ARM925T
+ bool "Support ARM925T processor" if ARCH_OMAP1
+@@ -180,22 +228,22 @@ config CPU_ARM926T
+ Otherwise, say N.
+
+ # FA526
+-config CPU_FA526
+- bool
+- select CPU_32v4
+- select CPU_ABRT_EV4
+- select CPU_PABRT_LEGACY
+- select CPU_CACHE_VIVT
+- select CPU_CP15_MMU
+- select CPU_CACHE_FA
+- select CPU_COPY_FA if MMU
+- select CPU_TLB_FA if MMU
+- help
+- The FA526 is a version of the ARMv4 compatible processor with
+- Branch Target Buffer, Unified TLB and cache line size 16.
+-
+- Say Y if you want support for the FA526 processor.
+- Otherwise, say N.
++#config CPU_FA526
++# bool
++# select CPU_32v4
++# select CPU_ABRT_EV4
++# select CPU_PABRT_LEGACY
++# select CPU_CACHE_VIVT
++# select CPU_CP15_MMU
++# select CPU_CACHE_FA
++# select CPU_COPY_FA if MMU
++# select CPU_TLB_FA if MMU
++# help
++# The FA526 is a version of the ARMv4 compatible processor with
++# Branch Target Buffer, Unified TLB and cache line size 16.
++#
++# Say Y if you want support for the FA526 processor.
++# Otherwise, say N.
+
+ # ARM940T
+ config CPU_ARM940T
+@@ -566,6 +614,7 @@ config CPU_TLB_FA
+ and invalidate instruction cache entry. Branch target buffer is
+ also supported.
+
++
+ config CPU_TLB_V6
+ bool
+
+@@ -664,14 +713,16 @@ config CPU_HIGH_VECTOR
+
+ config CPU_ICACHE_DISABLE
+ bool "Disable I-Cache (I-bit)"
+- depends on CPU_CP15 && !(CPU_ARM610 || CPU_ARM710 || CPU_ARM720T || CPU_ARM740T || CPU_XSCALE || CPU_XSC3)
++# depends on CPU_CP15 && !(CPU_ARM610 || CPU_ARM710 || CPU_ARM720T || CPU_ARM740T || CPU_XSCALE || CPU_XSC3 || CPU_FA520 || CPU_FA526 || CPU_FA626)
++ depends on CPU_CP15
+ help
+ Say Y here to disable the processor instruction cache. Unless
+ you have a reason not to or are unsure, say N.
+
+ config CPU_DCACHE_DISABLE
+ bool "Disable D-Cache (C-bit)"
+- depends on CPU_CP15
++# depends on CPU_CP15 && !(CPU_FA520 || CPU_FA526 || CPU_FA626)
++ depends on CPU_CP15
+ help
+ Say Y here to disable the processor data cache. Unless
+ you have a reason not to or are unsure, say N.
+@@ -697,6 +748,19 @@ config CPU_DCACHE_WRITETHROUGH
+ Say Y here to use the data cache in writethrough mode. Unless you
+ specifically require this or are unsure, say N.
+
++config CPU_FA_BTB
++ bool "BTB support (EXPERIMENTAL)"
++ depends on CPU_FA520 || CPU_FA526 || CPU_FA626
++ default y
++ help
++ //TODO: FA BTB
++
++config CPU_FA_WB_DISABLE
++ bool "Disable write buffer (EXPERIMENTAL)"
++ depends on CPU_FA520 || CPU_FA526 || CPU_FA626
++ help
++ //TODO: FA write buffer
++
+ config CPU_CACHE_ROUND_ROBIN
+ bool "Round robin I and D cache replacement algorithm"
+ depends on (CPU_ARM926T || CPU_ARM946E || CPU_ARM1020) && (!CPU_ICACHE_DISABLE || !CPU_DCACHE_DISABLE)
+diff -rupN linux-2.6.35.11/arch/arm/mm/proc-fa526.S linux-2.6.35.11-ts7500/arch/arm/mm/proc-fa526.S
+--- linux-2.6.35.11/arch/arm/mm/proc-fa526.S 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mm/proc-fa526.S 2011-03-14 11:18:24.000000000 -0400
+@@ -1,3 +1,4 @@
++#if (1)
+ /*
+ * linux/arch/arm/mm/proc-fa526.S: MMU functions for FA526
+ *
+@@ -138,6 +139,7 @@ ENTRY(cpu_fa526_set_pte_ext)
+ #endif
+ mov pc, lr
+
++
+ __INIT
+
+ .type __fa526_setup, #function
+@@ -246,3 +248,428 @@ __fa526_proc_info:
+ .long fa_user_fns
+ .long fa_cache_fns
+ .size __fa526_proc_info, . - __fa526_proc_info
++
++#else
++/*
++ * linux/arch/arm/mm/proc-fa526.S: MMU functions for FA526
++ *
++ * Copyright (C) 2005 Faraday Corp.
++ *
++ * 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
++ *
++ *
++ * These are the low level assembler for performing cache and TLB
++ * functions on the fa526.
++ *
++ * Written by : Luke Lee
++ */
++#include <linux/linkage.h>
++//#include <linux/config.h>
++#include <linux/init.h>
++#include <asm/assembler.h>
++#include <asm/pgtable.h>
++/* scott.test
++#include <asm/procinfo.h>
++*/
++#include <mach/hardware.h>
++#include <asm/page.h>
++#include <asm/ptrace.h>
++#include <asm/system.h>
++#include "proc-macros.S"
++
++#define CACHE_DLINESIZE 16
++
++ .text
++/*
++ * cpu_fa526_proc_init()
++ */
++ENTRY(cpu_fa526_proc_init)
++ /* MMU is already ON here, ICACHE, DCACHE conditionally disabled */
++
++ mov r0, #1
++ nop
++ nop
++ mcr p15, 0, r0, c1, c1, 0 @ turn-on ECR
++ nop
++ nop
++
++ mrc p15, 0, r0, c1, c0, 0 @ read ctrl register
++
++#ifdef CONFIG_CPU_FA_BTB
++ orr r0, r0, #CR_Z
++#else
++ bic r0, r0, #CR_Z
++#endif
++#ifdef CONFIG_CPU_FA_WB_DISABLE
++ mov r1, #0
++ mcr p15, 0, r1, c7, c10, 4 @ drain write buffer
++ nop
++ nop
++ bic r0, r0, #CR_W
++#else
++ orr r0, r0, #CR_W
++#endif
++#ifdef CONFIG_CPU_DCACHE_DISABLE
++ bic r0, r0, #CR_C
++#else
++ orr r0, r0, #CR_C
++#endif
++#ifdef CONFIG_CPU_ICACHE_DISABLE
++ bic r0, r0, #CR_I
++#else
++ orr r0, r0, #CR_I
++#endif
++
++ nop
++ nop
++ mcr p15, 0, r0, c1, c0, 0
++ nop
++ nop
++
++ mov r5, lr
++ bl fa_initialize_cache_info @ destroy r0~r4
++ mov pc, r5 @ return
++
++
++/*
++ * cpu_fa526_proc_fin()
++ */
++ENTRY(cpu_fa526_proc_fin)
++ stmfd sp!, {lr}
++ mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
++ msr cpsr_c, ip
++
++ bl fa_flush_kern_cache_all
++ mrc p15, 0, r0, c1, c0, 0 @ ctrl register
++ bic r0, r0, #0x1000 @ ...i............
++ bic r0, r0, #0x000e @ ............wca.
++ mcr p15, 0, r0, c1, c0, 0 @ disable caches
++
++ nop
++ nop
++ ldmfd sp!, {pc}
++
++/*
++ * cpu_fa526_reset(loc)
++ *
++ * Perform a soft reset of the system. Put the CPU into the
++ * same state as it would be if it had been reset, and branch
++ * to what would be the reset vector.
++ *
++ * loc: location to jump to for soft reset
++ */
++ .align 4
++ENTRY(cpu_fa526_reset)
++ mov ip, #0
++ mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++ mcr p15, 0, ip, c7, c10, 4 @ drain WB
++#endif
++ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
++ mrc p15, 0, ip, c1, c0, 0 @ ctrl register
++ bic ip, ip, #0x000f @ ............wcam
++ bic ip, ip, #0x1100 @ ...i...s........
++
++ bic ip, ip, #0x0800 @ BTB off
++ mcr p15, 0, ip, c1, c0, 0 @ ctrl register
++ nop
++ nop
++ mov pc, r0
++
++/*
++ * cpu_fa526_do_idle()
++ */
++ .align 4
++ENTRY(cpu_fa526_do_idle)
++
++#ifdef CONFIG_CPU_FA_IDLE
++ nop
++ nop
++ mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt (IDLE mode)
++#endif
++ mov pc, lr
++
++
++ENTRY(cpu_fa526_dcache_clean_area)
++
++#ifndef CONFIG_CPU_DCACHE_DISABLE
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
++ add r0, r0, #CACHE_DLINESIZE
++ subs r1, r1, #CACHE_DLINESIZE
++ bhi 1b
++#endif
++#endif
++ mov pc, lr
++
++
++/* =============================== PageTable ============================== */
++
++/*
++ * cpu_fa526_switch_mm(pgd)
++ *
++ * Set the translation base pointer to be as described by pgd.
++ *
++ * pgd: new page tables
++ */
++ .align 4
++
++ .globl fault_address
++fault_address:
++ .long 0
++
++ENTRY(cpu_fa526_switch_mm)
++
++ mov ip, #0
++#ifndef CONFIG_CPU_DCACHE_DISABLE
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++ mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
++#else
++ mcr p15, 0, ip, c7, c14, 0 @ Clean and invalidate whole DCache
++#endif
++#endif /*CONFIG_CPU_DCACHE_DISABLE*/
++
++#ifndef CONFIG_CPU_ICACHE_DISABLE
++ mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
++#endif
++
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++ mcr p15, 0, ip, c7, c10, 4 @ drain WB
++#endif
++
++#ifdef CONFIG_CPU_FA_BTB
++ mcr p15, 0, ip, c7, c5, 6 @ invalidate BTB since mm changed
++ nop
++ nop
++#endif
++ bic r0, r0, #0xff @ clear bits [7:0]
++ bic r0, r0, #0x3f00 @ clear bits [13:8]
++ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
++ mcr p15, 0, ip, c8, c7, 0 @ invalidate UTLB
++ nop
++ nop
++ mov pc, lr
++
++/*
++ * cpu_fa526_set_pte_ext(ptep, pte, ext)
++ *
++ * Set a PTE and flush it out
++ */
++ .align 4
++ENTRY(cpu_fa526_set_pte_ext)
++ str r1, [r0], #-2048 @ linux version
++
++ eor r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
++
++ bic r2, r1, #PTE_SMALL_AP_MASK
++ bic r2, r2, #PTE_TYPE_MASK
++ orr r2, r2, #PTE_TYPE_SMALL
++
++ tst r1, #L_PTE_USER @ User?
++ orrne r2, r2, #PTE_SMALL_AP_URO_SRW
++
++ tst r1, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty?
++ orreq r2, r2, #PTE_SMALL_AP_UNO_SRW
++
++ tst r1, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young?
++ movne r2, #0
++
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++ eor r3, r2, #0x0a @ C & small page? 1010
++ tst r3, #0x0b @ 1011
++ biceq r2, r2, #4
++#endif
++ str r2, [r0] @ hardware version
++
++ mov r2, #0
++ mcr p15, 0, r2, c7, c10, 0 @ clean D cache all
++
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++ mcr p15, 0, r2, c7, c10, 4 @ drain WB
++#endif
++#ifdef CONFIG_CPU_FA_BTB
++ mcr p15, 0, r2, c7, c5, 6 @ invalidate BTB
++ nop
++ nop
++#endif
++ mov pc, lr
++
++
++#ifdef CONFIG_DEBUG_LL
++str_fa526_setup: .asciz "str_fa526_setup\n"
++str_fa526_setup_done: .asciz "str_fa526_setup_done\n"
++.align 4
++#endif
++ __INIT
++
++ .type __fa526_setup, #function
++__fa526_setup:
++#ifdef CONFIG_DEBUG_LL
++ adr r0, str_fa526_setup
++ bl printascii
++#endif
++ /* On return of this routine, r0 must carry correct flags for CFG register */
++ mov r0, #0
++ mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4
++ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
++ mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4
++
++ mcr p15, 0, r0, c7, c5, 5 @ invalidate IScratchpad RAM
++
++ mov r0, #1
++ mcr p15, 0, r0, c1, c1, 0 @ turn-on ECR
++
++ mrc p15, 0, r0, c9, c1, 0 @ DScratchpad
++ bic r0, r0, #1
++ mcr p15, 0, r0, c9, c1, 0
++ mrc p15, 0, r0, c9, c1, 1 @ IScratchpad
++ bic r0, r0, #1
++ mcr p15, 0, r0, c9, c1, 1
++
++ mov r0, #0
++ mcr p15, 0, r0, c1, c1, 0 @ turn-off ECR
++
++#ifdef CONFIG_CPU_FA_BTB
++ mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB All
++ nop
++ nop
++#endif
++
++ mov r0, #0x1f @ Domains 0, 1 = manager, 2 = client
++ mcr p15, 0, r0, c3, c0 @ load domain access register
++
++ mrc p15, 0, r0, c1, c0 @ get control register v4
++ ldr r5, fa526_cr1_clear
++ bic r0, r0, r5
++ ldr r5, fa526_cr1_set
++ orr r0, r0, r5
++
++#ifdef CONFIG_CPU_FA_BTB
++ orr r0, r0, #CR_Z
++#else
++ bic r0, r0, #CR_Z
++#endif
++#ifdef CONFIG_CPU_FA_WB_DISABLE
++ mov r12, #0
++ mcr p15, 0, r12, c7, c10, 4 @ drain write buffer
++ nop
++ nop
++ bic r0, r0, #CR_W @ .... .... .... 1...
++#else
++ orr r0, r0, #CR_W
++#endif
++
++#ifdef CONFIG_DEBUG_LL
++ adr r0, str_fa526_setup_done
++ bl printascii
++#endif
++
++ mov pc, lr
++ .size __fa526_setup, . - __fa526_setup
++
++ /*
++ * .RVI ZFRS BLDP WCAM
++ * ..11 0001 .111 1101
++ *
++ */
++ .type fa526_cr1_clear, #object
++ .type fa526_cr1_set, #object
++fa526_cr1_clear:
++ .word 0x3f3f
++fa526_cr1_set:
++ .word 0x317D
++
++ __INITDATA
++
++/*
++ * Purpose : Function pointers used to access above functions - all calls
++ * come through these
++ */
++ .type fa526_processor_functions, #object
++fa526_processor_functions:
++ .word v4_early_abort
++ .word legacy_pabort @ Ian added
++ .word cpu_fa526_proc_init
++ .word cpu_fa526_proc_fin
++ .word cpu_fa526_reset
++ .word cpu_fa526_do_idle
++ .word cpu_fa526_dcache_clean_area
++ .word cpu_fa526_switch_mm
++ .word cpu_fa526_set_pte_ext
++ .size fa526_processor_functions, . - fa526_processor_functions
++
++ .section ".rodata"
++
++ .type cpu_arch_name, #object
++cpu_arch_name:
++ .asciz "armv4"
++ .size cpu_arch_name, . - cpu_arch_name
++
++ .type cpu_elf_name, #object
++cpu_elf_name:
++ .asciz "v4"
++ .size cpu_elf_name, . - cpu_elf_name
++
++ .type cpu_fa526_name, #object
++cpu_fa526_name:
++ .ascii "FA526"
++#ifndef CONFIG_CPU_ICACHE_DISABLE
++ .ascii "i"
++#endif
++#ifndef CONFIG_CPU_DCACHE_DISABLE
++ .ascii "d"
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++ .ascii "(wt)"
++#else
++ .ascii "(wb)"
++#endif
++#endif
++ .ascii "\0"
++ .size cpu_fa526_name, . - cpu_fa526_name
++
++ .align
++
++ .section ".proc.info.init", #alloc, #execinstr
++
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++#define __PMD_SECT_BUFFERABLE 0
++#else
++#define __PMD_SECT_BUFFERABLE PMD_SECT_BUFFERABLE
++#endif
++
++ .type __fa526_proc_info,#object
++__fa526_proc_info:
++ .long 0x66015261
++ .long 0xff01fff1
++ .long PMD_TYPE_SECT | \
++ __PMD_SECT_BUFFERABLE | \
++ PMD_SECT_CACHEABLE | \
++ PMD_BIT4 | \
++ PMD_SECT_AP_WRITE | \
++ PMD_SECT_AP_READ
++ .long PMD_TYPE_SECT | \
++ PMD_SECT_AP_WRITE | \
++ PMD_SECT_AP_READ
++ b __fa526_setup
++ .long cpu_arch_name
++ .long cpu_elf_name
++ .long HWCAP_SWP | HWCAP_HALF
++ .long cpu_fa526_name
++ .long fa526_processor_functions
++ .long fa_tlb_fns
++ .long fa_user_fns
++ .long fa_cache_fns
++ .size __fa526_proc_info, . - __fa526_proc_info
++#endif
+diff -rupN linux-2.6.35.11/arch/arm/mm/proc-fa526.S.orig linux-2.6.35.11-ts7500/arch/arm/mm/proc-fa526.S.orig
+--- linux-2.6.35.11/arch/arm/mm/proc-fa526.S.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mm/proc-fa526.S.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,248 @@
++/*
++ * linux/arch/arm/mm/proc-fa526.S: MMU functions for FA526
++ *
++ * Written by : Luke Lee
++ * Copyright (C) 2005 Faraday Corp.
++ * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas at teltonika.lt>
++ *
++ * 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.
++ *
++ *
++ * These are the low level assembler for performing cache and TLB
++ * functions on the fa526.
++ */
++#include <linux/linkage.h>
++#include <linux/init.h>
++#include <asm/assembler.h>
++#include <asm/hwcap.h>
++#include <asm/pgtable-hwdef.h>
++#include <asm/pgtable.h>
++#include <asm/page.h>
++#include <asm/ptrace.h>
++#include <asm/system.h>
++
++#include "proc-macros.S"
++
++#define CACHE_DLINESIZE 16
++
++ .text
++/*
++ * cpu_fa526_proc_init()
++ */
++ENTRY(cpu_fa526_proc_init)
++ mov pc, lr
++
++/*
++ * cpu_fa526_proc_fin()
++ */
++ENTRY(cpu_fa526_proc_fin)
++ stmfd sp!, {lr}
++ mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
++ msr cpsr_c, ip
++ bl fa_flush_kern_cache_all
++ mrc p15, 0, r0, c1, c0, 0 @ ctrl register
++ bic r0, r0, #0x1000 @ ...i............
++ bic r0, r0, #0x000e @ ............wca.
++ mcr p15, 0, r0, c1, c0, 0 @ disable caches
++ nop
++ nop
++ ldmfd sp!, {pc}
++
++/*
++ * cpu_fa526_reset(loc)
++ *
++ * Perform a soft reset of the system. Put the CPU into the
++ * same state as it would be if it had been reset, and branch
++ * to what would be the reset vector.
++ *
++ * loc: location to jump to for soft reset
++ */
++ .align 4
++ENTRY(cpu_fa526_reset)
++/* TODO: Use CP8 if possible... */
++ mov ip, #0
++ mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
++ mcr p15, 0, ip, c7, c10, 4 @ drain WB
++#ifdef CONFIG_MMU
++ mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
++#endif
++ mrc p15, 0, ip, c1, c0, 0 @ ctrl register
++ bic ip, ip, #0x000f @ ............wcam
++ bic ip, ip, #0x1100 @ ...i...s........
++ bic ip, ip, #0x0800 @ BTB off
++ mcr p15, 0, ip, c1, c0, 0 @ ctrl register
++ nop
++ nop
++ mov pc, r0
++
++/*
++ * cpu_fa526_do_idle()
++ */
++ .align 4
++ENTRY(cpu_fa526_do_idle)
++ mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
++ mov pc, lr
++
++
++ENTRY(cpu_fa526_dcache_clean_area)
++1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
++ add r0, r0, #CACHE_DLINESIZE
++ subs r1, r1, #CACHE_DLINESIZE
++ bhi 1b
++ mcr p15, 0, r0, c7, c10, 4 @ drain WB
++ mov pc, lr
++
++/* =============================== PageTable ============================== */
++
++/*
++ * cpu_fa526_switch_mm(pgd)
++ *
++ * Set the translation base pointer to be as described by pgd.
++ *
++ * pgd: new page tables
++ */
++ .align 4
++ENTRY(cpu_fa526_switch_mm)
++#ifdef CONFIG_MMU
++ mov ip, #0
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++ mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
++#else
++ mcr p15, 0, ip, c7, c14, 0 @ clean and invalidate whole D cache
++#endif
++ mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
++ mcr p15, 0, ip, c7, c5, 6 @ invalidate BTB since mm changed
++ mcr p15, 0, ip, c7, c10, 4 @ data write barrier
++ mcr p15, 0, ip, c7, c5, 4 @ prefetch flush
++ mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
++ mcr p15, 0, ip, c8, c7, 0 @ invalidate UTLB
++#endif
++ mov pc, lr
++
++/*
++ * cpu_fa526_set_pte_ext(ptep, pte, ext)
++ *
++ * Set a PTE and flush it out
++ */
++ .align 4
++ENTRY(cpu_fa526_set_pte_ext)
++#ifdef CONFIG_MMU
++ armv3_set_pte_ext
++ mov r0, r0
++ mcr p15, 0, r0, c7, c10, 1 @ clean D entry
++ mov r0, #0
++ mcr p15, 0, r0, c7, c10, 4 @ drain WB
++#endif
++ mov pc, lr
++
++ __INIT
++
++ .type __fa526_setup, #function
++__fa526_setup:
++ /* On return of this routine, r0 must carry correct flags for CFG register */
++ mov r0, #0
++ mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4
++ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
++#ifdef CONFIG_MMU
++ mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4
++#endif
++ mcr p15, 0, r0, c7, c5, 5 @ invalidate IScratchpad RAM
++
++ mov r0, #1
++ mcr p15, 0, r0, c1, c1, 0 @ turn-on ECR
++
++ mov r0, #0
++ mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB All
++ mcr p15, 0, r0, c7, c10, 4 @ data write barrier
++ mcr p15, 0, r0, c7, c5, 4 @ prefetch flush
++
++ mov r0, #0x1f @ Domains 0, 1 = manager, 2 = client
++ mcr p15, 0, r0, c3, c0 @ load domain access register
++
++ mrc p15, 0, r0, c1, c0 @ get control register v4
++ ldr r5, fa526_cr1_clear
++ bic r0, r0, r5
++ ldr r5, fa526_cr1_set
++ orr r0, r0, r5
++ mov pc, lr
++ .size __fa526_setup, . - __fa526_setup
++
++ /*
++ * .RVI ZFRS BLDP WCAM
++ * ..11 1001 .111 1101
++ *
++ */
++ .type fa526_cr1_clear, #object
++ .type fa526_cr1_set, #object
++fa526_cr1_clear:
++ .word 0x3f3f
++fa526_cr1_set:
++ .word 0x397D
++
++ __INITDATA
++
++/*
++ * Purpose : Function pointers used to access above functions - all calls
++ * come through these
++ */
++ .type fa526_processor_functions, #object
++fa526_processor_functions:
++ .word v4_early_abort
++ .word legacy_pabort
++ .word cpu_fa526_proc_init
++ .word cpu_fa526_proc_fin
++ .word cpu_fa526_reset
++ .word cpu_fa526_do_idle
++ .word cpu_fa526_dcache_clean_area
++ .word cpu_fa526_switch_mm
++ .word cpu_fa526_set_pte_ext
++ .size fa526_processor_functions, . - fa526_processor_functions
++
++ .section ".rodata"
++
++ .type cpu_arch_name, #object
++cpu_arch_name:
++ .asciz "armv4"
++ .size cpu_arch_name, . - cpu_arch_name
++
++ .type cpu_elf_name, #object
++cpu_elf_name:
++ .asciz "v4"
++ .size cpu_elf_name, . - cpu_elf_name
++
++ .type cpu_fa526_name, #object
++cpu_fa526_name:
++ .asciz "FA526"
++ .size cpu_fa526_name, . - cpu_fa526_name
++
++ .align
++
++ .section ".proc.info.init", #alloc, #execinstr
++
++ .type __fa526_proc_info,#object
++__fa526_proc_info:
++ .long 0x66015261
++ .long 0xff01fff1
++ .long PMD_TYPE_SECT | \
++ PMD_SECT_BUFFERABLE | \
++ PMD_SECT_CACHEABLE | \
++ PMD_BIT4 | \
++ PMD_SECT_AP_WRITE | \
++ PMD_SECT_AP_READ
++ .long PMD_TYPE_SECT | \
++ PMD_BIT4 | \
++ PMD_SECT_AP_WRITE | \
++ PMD_SECT_AP_READ
++ b __fa526_setup
++ .long cpu_arch_name
++ .long cpu_elf_name
++ .long HWCAP_SWP | HWCAP_HALF
++ .long cpu_fa526_name
++ .long fa526_processor_functions
++ .long fa_tlb_fns
++ .long fa_user_fns
++ .long fa_cache_fns
++ .size __fa526_proc_info, . - __fa526_proc_info
+diff -rupN linux-2.6.35.11/arch/arm/mm/tlb-fa.S linux-2.6.35.11-ts7500/arch/arm/mm/tlb-fa.S
+--- linux-2.6.35.11/arch/arm/mm/tlb-fa.S 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/mm/tlb-fa.S 2011-03-14 11:18:24.000000000 -0400
+@@ -1,3 +1,4 @@
++#if (0)
+ /*
+ * linux/arch/arm/mm/tlb-fa.S
+ *
+@@ -73,3 +74,103 @@ ENTRY(fa_tlb_fns)
+ .long fa_flush_kern_tlb_range
+ .long fa_tlb_flags
+ .size fa_tlb_fns, . - fa_tlb_fns
++#else
++/*
++ * linux/arch/arm/mm/tlb-fa.S
++ *
++ * Copyright (C) 2005 Faraday Corp.
++ *
++ * 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.
++ *
++ * ARM architecture version 4, Faraday variation.
++ * This assume an unified TLBs, with a write buffer, and branch target buffer (BTB)
++ *
++ * Processors: FA520 FA526 FA626
++ * 03/31/2005 : Created by Luke Lee, modified from tlb-v4wbi.S
++ * 05/06/2005 : Fixed buggy CPU versions that did not invalidate the associated
++ * data cache entries when invalidating TLB entries.
++ */
++#include <linux/linkage.h>
++#include <linux/init.h>
++#include <asm/asm-offsets.h>
++//#include <asm/constants.h>
++#include <asm/tlbflush.h>
++#include "proc-macros.S"
++
++
++/*
++ * flush_user_tlb_range(start, end, mm)
++ *
++ * Invalidate a range of TLB entries in the specified address space.
++ *
++ * - start - range start address
++ * - end - range end address
++ * - mm - mm_struct describing address space
++ */
++ .align 4
++ENTRY(fa_flush_user_tlb_range)
++
++ vma_vm_mm ip, r2
++ act_mm r3 @ get current->active_mm
++ eors r3, ip, r3 @ == mm ?
++ movne pc, lr @ no, we dont do anything
++ mov r3, #0
++
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++ mcr p15, 0, r3, c7, c10, 4 @ drain WB
++#endif
++
++ vma_vm_flags r2, r2
++ bic r0, r0, #0x0ff
++ bic r0, r0, #0xf00
++
++1: mcr p15, 0, r0, c8, c7, 1 @ invalidate UTLB entry
++ add r0, r0, #PAGE_SZ
++ cmp r0, r1
++ bls 1b @ Luke Lee 05/19/2005 blo -> bls
++
++#ifdef CONFIG_CPU_FA_BTB
++ mcr p15, 0, r3, c7, c5, 6 @ invalidate BTB
++ nop
++ nop
++#endif
++ mov pc, lr
++
++
++ENTRY(fa_flush_kern_tlb_range)
++ mov r3, #0
++
++ mcr p15, 0, r3, c7, c10, 0 @ clean Dcache all 06/03/2005
++
++#ifndef CONFIG_CPU_FA_WB_DISABLE
++ mcr p15, 0, r3, c7, c10, 4 @ drain WB
++#endif
++
++ bic r0, r0, #0x0ff
++ bic r0, r0, #0xf00
++1:
++ mcr p15, 0, r0, c8, c7, 1 @ invalidate UTLB entry
++ add r0, r0, #PAGE_SZ
++ cmp r0, r1
++ bls 1b @ Luke Lee 05/19/2005 blo -> bls
++
++#ifdef CONFIG_CPU_FA_BTB
++ mcr p15, 0, r3, c7, c5, 6 @ invalidate BTB
++ nop
++ nop
++#endif
++ mov pc, lr
++
++
++ __INITDATA
++
++ .type fa_tlb_fns, #object
++ENTRY(fa_tlb_fns)
++ .long fa_flush_user_tlb_range
++ .long fa_flush_kern_tlb_range
++ .long fa_tlb_flags
++ .size fa_tlb_fns, . - fa_tlb_fns
++
++#endif
+diff -rupN linux-2.6.35.11/arch/arm/tools/mach-types linux-2.6.35.11-ts7500/arch/arm/tools/mach-types
+--- linux-2.6.35.11/arch/arm/tools/mach-types 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/tools/mach-types 2011-03-14 11:39:00.000000000 -0400
+@@ -2950,3 +2950,4 @@ davinci_dm365_dvr MACH_DAVINCI_DM365_DVR
+ netviz MACH_NETVIZ NETVIZ 2964
+ flexibity MACH_FLEXIBITY FLEXIBITY 2965
+ wlan_computer MACH_WLAN_COMPUTER WLAN_COMPUTER 2966
++str8100 ARCH_STR8100 STR8100 2001
+diff -rupN linux-2.6.35.11/arch/arm/tools/mach-types~ linux-2.6.35.11-ts7500/arch/arm/tools/mach-types~
+--- linux-2.6.35.11/arch/arm/tools/mach-types~ 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/tools/mach-types~ 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,2952 @@
++# Database of machine macros and numbers
++#
++# This file is linux/arch/arm/tools/mach-types
++#
++# Up to date versions of this file can be obtained from:
++#
++# http://www.arm.linux.org.uk/developer/machines/download.php
++#
++# Please do not send patches to this file; it is automatically generated!
++# To add an entry into this database, please see Documentation/arm/README,
++# or visit:
++#
++# http://www.arm.linux.org.uk/developer/machines/?action=new
++#
++# Last update: Mon Jul 12 21:10:14 2010
++#
++# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
++#
++ebsa110 ARCH_EBSA110 EBSA110 0
++riscpc ARCH_RPC RISCPC 1
++nexuspci ARCH_NEXUSPCI NEXUSPCI 3
++ebsa285 ARCH_EBSA285 EBSA285 4
++netwinder ARCH_NETWINDER NETWINDER 5
++cats ARCH_CATS CATS 6
++tbox ARCH_TBOX TBOX 7
++co285 ARCH_CO285 CO285 8
++clps7110 ARCH_CLPS7110 CLPS7110 9
++archimedes ARCH_ARC ARCHIMEDES 10
++a5k ARCH_A5K A5K 11
++etoile ARCH_ETOILE ETOILE 12
++lacie_nas ARCH_LACIE_NAS LACIE_NAS 13
++clps7500 ARCH_CLPS7500 CLPS7500 14
++shark ARCH_SHARK SHARK 15
++brutus SA1100_BRUTUS BRUTUS 16
++personal_server ARCH_PERSONAL_SERVER PERSONAL_SERVER 17
++itsy SA1100_ITSY ITSY 18
++l7200 ARCH_L7200 L7200 19
++pleb SA1100_PLEB PLEB 20
++integrator ARCH_INTEGRATOR INTEGRATOR 21
++h3600 SA1100_H3600 H3600 22
++ixp1200 ARCH_IXP1200 IXP1200 23
++p720t ARCH_P720T P720T 24
++assabet SA1100_ASSABET ASSABET 25
++victor SA1100_VICTOR VICTOR 26
++lart SA1100_LART LART 27
++ranger SA1100_RANGER RANGER 28
++graphicsclient SA1100_GRAPHICSCLIENT GRAPHICSCLIENT 29
++xp860 SA1100_XP860 XP860 30
++cerf SA1100_CERF CERF 31
++nanoengine SA1100_NANOENGINE NANOENGINE 32
++fpic SA1100_FPIC FPIC 33
++extenex1 SA1100_EXTENEX1 EXTENEX1 34
++sherman SA1100_SHERMAN SHERMAN 35
++accelent_sa SA1100_ACCELENT ACCELENT_SA 36
++accelent_l7200 ARCH_L7200_ACCELENT ACCELENT_L7200 37
++netport SA1100_NETPORT NETPORT 38
++pangolin SA1100_PANGOLIN PANGOLIN 39
++yopy SA1100_YOPY YOPY 40
++coolidge SA1100_COOLIDGE COOLIDGE 41
++huw_webpanel SA1100_HUW_WEBPANEL HUW_WEBPANEL 42
++spotme ARCH_SPOTME SPOTME 43
++freebird ARCH_FREEBIRD FREEBIRD 44
++ti925 ARCH_TI925 TI925 45
++riscstation ARCH_RISCSTATION RISCSTATION 46
++cavy SA1100_CAVY CAVY 47
++jornada720 SA1100_JORNADA720 JORNADA720 48
++omnimeter SA1100_OMNIMETER OMNIMETER 49
++edb7211 ARCH_EDB7211 EDB7211 50
++citygo SA1100_CITYGO CITYGO 51
++pfs168 SA1100_PFS168 PFS168 52
++spot SA1100_SPOT SPOT 53
++flexanet SA1100_FLEXANET FLEXANET 54
++webpal ARCH_WEBPAL WEBPAL 55
++linpda SA1100_LINPDA LINPDA 56
++anakin ARCH_ANAKIN ANAKIN 57
++mvi SA1100_MVI MVI 58
++jupiter SA1100_JUPITER JUPITER 59
++psionw ARCH_PSIONW PSIONW 60
++aln SA1100_ALN ALN 61
++epxa ARCH_CAMELOT CAMELOT 62
++gds2200 SA1100_GDS2200 GDS2200 63
++netbook SA1100_PSION_SERIES7 PSION_SERIES7 64
++xfile SA1100_XFILE XFILE 65
++accelent_ep9312 ARCH_ACCELENT_EP9312 ACCELENT_EP9312 66
++ic200 ARCH_IC200 IC200 67
++creditlart SA1100_CREDITLART CREDITLART 68
++htm SA1100_HTM HTM 69
++iq80310 ARCH_IQ80310 IQ80310 70
++freebot SA1100_FREEBOT FREEBOT 71
++entel ARCH_ENTEL ENTEL 72
++enp3510 ARCH_ENP3510 ENP3510 73
++trizeps SA1100_TRIZEPS TRIZEPS 74
++nesa SA1100_NESA NESA 75
++venus ARCH_VENUS VENUS 76
++tardis ARCH_TARDIS TARDIS 77
++mercury ARCH_MERCURY MERCURY 78
++empeg SA1100_EMPEG EMPEG 79
++adi_evb ARCH_I80200FCC I80200FCC 80
++itt_cpb SA1100_ITT_CPB ITT_CPB 81
++svc SA1100_SVC SVC 82
++alpha2 SA1100_ALPHA2 ALPHA2 84
++alpha1 SA1100_ALPHA1 ALPHA1 85
++netarm ARCH_NETARM NETARM 86
++simpad SA1100_SIMPAD SIMPAD 87
++pda1 ARCH_PDA1 PDA1 88
++lubbock ARCH_LUBBOCK LUBBOCK 89
++aniko ARCH_ANIKO ANIKO 90
++clep7212 ARCH_CLEP7212 CLEP7212 91
++cs89712 ARCH_CS89712 CS89712 92
++weararm SA1100_WEARARM WEARARM 93
++possio_px SA1100_POSSIO_PX POSSIO_PX 94
++sidearm SA1100_SIDEARM SIDEARM 95
++stork SA1100_STORK STORK 96
++shannon SA1100_SHANNON SHANNON 97
++ace ARCH_ACE ACE 98
++ballyarm SA1100_BALLYARM BALLYARM 99
++simputer SA1100_SIMPUTER SIMPUTER 100
++nexterm SA1100_NEXTERM NEXTERM 101
++sa1100_elf SA1100_SA1100_ELF SA1100_ELF 102
++gator SA1100_GATOR GATOR 103
++granite ARCH_GRANITE GRANITE 104
++consus SA1100_CONSUS CONSUS 105
++aaed2000 ARCH_AAED2000 AAED2000 106
++cdb89712 ARCH_CDB89712 CDB89712 107
++graphicsmaster SA1100_GRAPHICSMASTER GRAPHICSMASTER 108
++adsbitsy SA1100_ADSBITSY ADSBITSY 109
++pxa_idp ARCH_PXA_IDP PXA_IDP 110
++plce ARCH_PLCE PLCE 111
++pt_system3 SA1100_PT_SYSTEM3 PT_SYSTEM3 112
++murphy ARCH_MEDALB MEDALB 113
++eagle ARCH_EAGLE EAGLE 114
++dsc21 ARCH_DSC21 DSC21 115
++dsc24 ARCH_DSC24 DSC24 116
++ti5472 ARCH_TI5472 TI5472 117
++autcpu12 ARCH_AUTCPU12 AUTCPU12 118
++uengine ARCH_UENGINE UENGINE 119
++bluestem SA1100_BLUESTEM BLUESTEM 120
++xingu8 ARCH_XINGU8 XINGU8 121
++bushstb ARCH_BUSHSTB BUSHSTB 122
++epsilon1 SA1100_EPSILON1 EPSILON1 123
++balloon SA1100_BALLOON BALLOON 124
++puppy ARCH_PUPPY PUPPY 125
++elroy SA1100_ELROY ELROY 126
++gms720 ARCH_GMS720 GMS720 127
++s24x ARCH_S24X S24X 128
++jtel_clep7312 ARCH_JTEL_CLEP7312 JTEL_CLEP7312 129
++cx821xx ARCH_CX821XX CX821XX 130
++edb7312 ARCH_EDB7312 EDB7312 131
++bsa1110 SA1100_BSA1110 BSA1110 132
++powerpin ARCH_POWERPIN POWERPIN 133
++openarm ARCH_OPENARM OPENARM 134
++whitechapel SA1100_WHITECHAPEL WHITECHAPEL 135
++h3100 SA1100_H3100 H3100 136
++h3800 SA1100_H3800 H3800 137
++blue_v1 ARCH_BLUE_V1 BLUE_V1 138
++pxa_cerf ARCH_PXA_CERF PXA_CERF 139
++arm7tevb ARCH_ARM7TEVB ARM7TEVB 140
++d7400 SA1100_D7400 D7400 141
++piranha ARCH_PIRANHA PIRANHA 142
++sbcamelot SA1100_SBCAMELOT SBCAMELOT 143
++kings SA1100_KINGS KINGS 144
++smdk2400 ARCH_SMDK2400 SMDK2400 145
++collie SA1100_COLLIE COLLIE 146
++idr ARCH_IDR IDR 147
++badge4 SA1100_BADGE4 BADGE4 148
++webnet ARCH_WEBNET WEBNET 149
++d7300 SA1100_D7300 D7300 150
++cep SA1100_CEP CEP 151
++fortunet ARCH_FORTUNET FORTUNET 152
++vc547x ARCH_VC547X VC547X 153
++filewalker SA1100_FILEWALKER FILEWALKER 154
++netgateway SA1100_NETGATEWAY NETGATEWAY 155
++symbol2800 SA1100_SYMBOL2800 SYMBOL2800 156
++suns SA1100_SUNS SUNS 157
++frodo SA1100_FRODO FRODO 158
++ms301 SA1100_MACH_TYTE_MS301 MACH_TYTE_MS301 159
++mx1ads ARCH_MX1ADS MX1ADS 160
++h7201 ARCH_H7201 H7201 161
++h7202 ARCH_H7202 H7202 162
++amico ARCH_AMICO AMICO 163
++iam SA1100_IAM IAM 164
++tt530 SA1100_TT530 TT530 165
++sam2400 ARCH_SAM2400 SAM2400 166
++jornada56x SA1100_JORNADA56X JORNADA56X 167
++active SA1100_ACTIVE ACTIVE 168
++iq80321 ARCH_IQ80321 IQ80321 169
++wid SA1100_WID WID 170
++sabinal ARCH_SABINAL SABINAL 171
++ixp425_matacumbe ARCH_IXP425_MATACUMBE IXP425_MATACUMBE 172
++miniprint SA1100_MINIPRINT MINIPRINT 173
++adm510x ARCH_ADM510X ADM510X 174
++svs200 SA1100_SVS200 SVS200 175
++atg_tcu ARCH_ATG_TCU ATG_TCU 176
++jornada820 SA1100_JORNADA820 JORNADA820 177
++s3c44b0 ARCH_S3C44B0 S3C44B0 178
++margis2 ARCH_MARGIS2 MARGIS2 179
++ks8695 ARCH_KS8695 KS8695 180
++brh ARCH_BRH BRH 181
++s3c2410 ARCH_S3C2410 S3C2410 182
++possio_px30 ARCH_POSSIO_PX30 POSSIO_PX30 183
++s3c2800 ARCH_S3C2800 S3C2800 184
++fleetwood SA1100_FLEETWOOD FLEETWOOD 185
++omaha ARCH_OMAHA OMAHA 186
++ta7 ARCH_TA7 TA7 187
++nova SA1100_NOVA NOVA 188
++hmk ARCH_HMK HMK 189
++karo ARCH_KARO KARO 190
++fester SA1100_FESTER FESTER 191
++gpi ARCH_GPI GPI 192
++smdk2410 ARCH_SMDK2410 SMDK2410 193
++i519 ARCH_I519 I519 194
++nexio SA1100_NEXIO NEXIO 195
++bitbox SA1100_BITBOX BITBOX 196
++g200 SA1100_G200 G200 197
++gill SA1100_GILL GILL 198
++pxa_mercury ARCH_PXA_MERCURY PXA_MERCURY 199
++ceiva ARCH_CEIVA CEIVA 200
++fret SA1100_FRET FRET 201
++emailphone SA1100_EMAILPHONE EMAILPHONE 202
++h3900 ARCH_H3900 H3900 203
++pxa1 ARCH_PXA1 PXA1 204
++koan369 SA1100_KOAN369 KOAN369 205
++cogent ARCH_COGENT COGENT 206
++esl_simputer ARCH_ESL_SIMPUTER ESL_SIMPUTER 207
++esl_simputer_clr ARCH_ESL_SIMPUTER_CLR ESL_SIMPUTER_CLR 208
++esl_simputer_bw ARCH_ESL_SIMPUTER_BW ESL_SIMPUTER_BW 209
++hhp_cradle ARCH_HHP_CRADLE HHP_CRADLE 210
++he500 ARCH_HE500 HE500 211
++inhandelf2 SA1100_INHANDELF2 INHANDELF2 212
++inhandftip SA1100_INHANDFTIP INHANDFTIP 213
++dnp1110 SA1100_DNP1110 DNP1110 214
++pnp1110 SA1100_PNP1110 PNP1110 215
++csb226 ARCH_CSB226 CSB226 216
++arnold SA1100_ARNOLD ARNOLD 217
++voiceblue MACH_VOICEBLUE VOICEBLUE 218
++jz8028 ARCH_JZ8028 JZ8028 219
++h5400 ARCH_H5400 H5400 220
++forte SA1100_FORTE FORTE 221
++acam SA1100_ACAM ACAM 222
++abox SA1100_ABOX ABOX 223
++atmel ARCH_ATMEL ATMEL 224
++sitsang ARCH_SITSANG SITSANG 225
++cpu1110lcdnet SA1100_CPU1110LCDNET CPU1110LCDNET 226
++mpl_vcma9 ARCH_MPL_VCMA9 MPL_VCMA9 227
++opus_a1 ARCH_OPUS_A1 OPUS_A1 228
++daytona ARCH_DAYTONA DAYTONA 229
++killbear SA1100_KILLBEAR KILLBEAR 230
++yoho ARCH_YOHO YOHO 231
++jasper ARCH_JASPER JASPER 232
++dsc25 ARCH_DSC25 DSC25 233
++omap_innovator MACH_OMAP_INNOVATOR OMAP_INNOVATOR 234
++mnci ARCH_RAMSES RAMSES 235
++s28x ARCH_S28X S28X 236
++mport3 ARCH_MPORT3 MPORT3 237
++pxa_eagle250 ARCH_PXA_EAGLE250 PXA_EAGLE250 238
++pdb ARCH_PDB PDB 239
++blue_2g SA1100_BLUE_2G BLUE_2G 240
++bluearch SA1100_BLUEARCH BLUEARCH 241
++ixdp2400 ARCH_IXDP2400 IXDP2400 242
++ixdp2800 ARCH_IXDP2800 IXDP2800 243
++explorer SA1100_EXPLORER EXPLORER 244
++ixdp425 ARCH_IXDP425 IXDP425 245
++chimp ARCH_CHIMP CHIMP 246
++stork_nest ARCH_STORK_NEST STORK_NEST 247
++stork_egg ARCH_STORK_EGG STORK_EGG 248
++wismo SA1100_WISMO WISMO 249
++ezlinx ARCH_EZLINX EZLINX 250
++at91rm9200 ARCH_AT91RM9200 AT91RM9200 251
++adtech_orion ARCH_ADTECH_ORION ADTECH_ORION 252
++neptune ARCH_NEPTUNE NEPTUNE 253
++hackkit SA1100_HACKKIT HACKKIT 254
++pxa_wins30 ARCH_PXA_WINS30 PXA_WINS30 255
++lavinna SA1100_LAVINNA LAVINNA 256
++pxa_uengine ARCH_PXA_UENGINE PXA_UENGINE 257
++innokom ARCH_INNOKOM INNOKOM 258
++bms ARCH_BMS BMS 259
++ixcdp1100 ARCH_IXCDP1100 IXCDP1100 260
++prpmc1100 ARCH_PRPMC1100 PRPMC1100 261
++at91rm9200dk ARCH_AT91RM9200DK AT91RM9200DK 262
++armstick ARCH_ARMSTICK ARMSTICK 263
++armonie ARCH_ARMONIE ARMONIE 264
++mport1 ARCH_MPORT1 MPORT1 265
++s3c5410 ARCH_S3C5410 S3C5410 266
++zcp320a ARCH_ZCP320A ZCP320A 267
++i_box ARCH_I_BOX I_BOX 268
++stlc1502 ARCH_STLC1502 STLC1502 269
++siren ARCH_SIREN SIREN 270
++greenlake ARCH_GREENLAKE GREENLAKE 271
++argus ARCH_ARGUS ARGUS 272
++combadge SA1100_COMBADGE COMBADGE 273
++rokepxa ARCH_ROKEPXA ROKEPXA 274
++cintegrator ARCH_CINTEGRATOR CINTEGRATOR 275
++guidea07 ARCH_GUIDEA07 GUIDEA07 276
++tat257 ARCH_TAT257 TAT257 277
++igp2425 ARCH_IGP2425 IGP2425 278
++bluegrama ARCH_BLUEGRAMMA BLUEGRAMMA 279
++ipod ARCH_IPOD IPOD 280
++adsbitsyx ARCH_ADSBITSYX ADSBITSYX 281
++trizeps2 ARCH_TRIZEPS2 TRIZEPS2 282
++viper ARCH_VIPER VIPER 283
++adsbitsyplus SA1100_ADSBITSYPLUS ADSBITSYPLUS 284
++adsagc SA1100_ADSAGC ADSAGC 285
++stp7312 ARCH_STP7312 STP7312 286
++nx_phnx MACH_NX_PHNX NX_PHNX 287
++wep_ep250 ARCH_WEP_EP250 WEP_EP250 288
++inhandelf3 ARCH_INHANDELF3 INHANDELF3 289
++adi_coyote ARCH_ADI_COYOTE ADI_COYOTE 290
++iyonix ARCH_IYONIX IYONIX 291
++damicam1 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292
++meg03 ARCH_MEG03 MEG03 293
++pxa_whitechapel ARCH_PXA_WHITECHAPEL PXA_WHITECHAPEL 294
++nwsc ARCH_NWSC NWSC 295
++nwlarm ARCH_NWLARM NWLARM 296
++ixp425_mguard ARCH_IXP425_MGUARD IXP425_MGUARD 297
++pxa_netdcu4 ARCH_PXA_NETDCU4 PXA_NETDCU4 298
++ixdp2401 ARCH_IXDP2401 IXDP2401 299
++ixdp2801 ARCH_IXDP2801 IXDP2801 300
++zodiac ARCH_ZODIAC ZODIAC 301
++armmodul ARCH_ARMMODUL ARMMODUL 302
++ketop SA1100_KETOP KETOP 303
++av7200 ARCH_AV7200 AV7200 304
++arch_ti925 ARCH_ARCH_TI925 ARCH_TI925 305
++acq200 ARCH_ACQ200 ACQ200 306
++pt_dafit SA1100_PT_DAFIT PT_DAFIT 307
++ihba ARCH_IHBA IHBA 308
++quinque ARCH_QUINQUE QUINQUE 309
++nimbraone ARCH_NIMBRAONE NIMBRAONE 310
++nimbra29x ARCH_NIMBRA29X NIMBRA29X 311
++nimbra210 ARCH_NIMBRA210 NIMBRA210 312
++hhp_d95xx ARCH_HHP_D95XX HHP_D95XX 313
++labarm ARCH_LABARM LABARM 314
++m825xx ARCH_M825XX M825XX 315
++m7100 SA1100_M7100 M7100 316
++nipc2 ARCH_NIPC2 NIPC2 317
++fu7202 ARCH_FU7202 FU7202 318
++adsagx ARCH_ADSAGX ADSAGX 319
++pxa_pooh ARCH_PXA_POOH PXA_POOH 320
++bandon ARCH_BANDON BANDON 321
++pcm7210 ARCH_PCM7210 PCM7210 322
++nms9200 ARCH_NMS9200 NMS9200 323
++logodl ARCH_LOGODL LOGODL 324
++m7140 SA1100_M7140 M7140 325
++korebot ARCH_KOREBOT KOREBOT 326
++iq31244 ARCH_IQ31244 IQ31244 327
++koan393 SA1100_KOAN393 KOAN393 328
++inhandftip3 ARCH_INHANDFTIP3 INHANDFTIP3 329
++gonzo ARCH_GONZO GONZO 330
++bast ARCH_BAST BAST 331
++scanpass ARCH_SCANPASS SCANPASS 332
++ep7312_pooh ARCH_EP7312_POOH EP7312_POOH 333
++ta7s ARCH_TA7S TA7S 334
++ta7v ARCH_TA7V TA7V 335
++icarus SA1100_ICARUS ICARUS 336
++h1900 ARCH_H1900 H1900 337
++gemini SA1100_GEMINI GEMINI 338
++axim ARCH_AXIM AXIM 339
++audiotron ARCH_AUDIOTRON AUDIOTRON 340
++h2200 ARCH_H2200 H2200 341
++loox600 ARCH_LOOX600 LOOX600 342
++niop ARCH_NIOP NIOP 343
++dm310 ARCH_DM310 DM310 344
++seedpxa_c2 ARCH_SEEDPXA_C2 SEEDPXA_C2 345
++ixp4xx_mguardpci ARCH_IXP4XX_MGUARD_PCI IXP4XX_MGUARD_PCI 346
++h1940 ARCH_H1940 H1940 347
++scorpio ARCH_SCORPIO SCORPIO 348
++viva ARCH_VIVA VIVA 349
++pxa_xcard ARCH_PXA_XCARD PXA_XCARD 350
++csb335 ARCH_CSB335 CSB335 351
++ixrd425 ARCH_IXRD425 IXRD425 352
++iq80315 ARCH_IQ80315 IQ80315 353
++nmp7312 ARCH_NMP7312 NMP7312 354
++cx861xx ARCH_CX861XX CX861XX 355
++enp2611 ARCH_ENP2611 ENP2611 356
++xda SA1100_XDA XDA 357
++csir_ims ARCH_CSIR_IMS CSIR_IMS 358
++ixp421_dnaeeth ARCH_IXP421_DNAEETH IXP421_DNAEETH 359
++pocketserv9200 ARCH_POCKETSERV9200 POCKETSERV9200 360
++toto ARCH_TOTO TOTO 361
++s3c2440 ARCH_S3C2440 S3C2440 362
++ks8695p ARCH_KS8695P KS8695P 363
++se4000 ARCH_SE4000 SE4000 364
++quadriceps ARCH_QUADRICEPS QUADRICEPS 365
++bronco ARCH_BRONCO BRONCO 366
++esl_wireless_tab ARCH_ESL_WIRELESS_TAB ESL_WIRELESS_TAB 367
++esl_sofcomp ARCH_ESL_SOFCOMP ESL_SOFCOMP 368
++s5c7375 ARCH_S5C7375 S5C7375 369
++spearhead ARCH_SPEARHEAD SPEARHEAD 370
++pantera ARCH_PANTERA PANTERA 371
++prayoglite ARCH_PRAYOGLITE PRAYOGLITE 372
++gumstix ARCH_GUMSTIX GUMSTIX 373
++rcube ARCH_RCUBE RCUBE 374
++rea_olv ARCH_REA_OLV REA_OLV 375
++pxa_iphone ARCH_PXA_IPHONE PXA_IPHONE 376
++s3c3410 ARCH_S3C3410 S3C3410 377
++espd_4510b ARCH_ESPD_4510B ESPD_4510B 378
++mp1x ARCH_MP1X MP1X 379
++at91rm9200tb ARCH_AT91RM9200TB AT91RM9200TB 380
++adsvgx ARCH_ADSVGX ADSVGX 381
++omap_h2 MACH_OMAP_H2 OMAP_H2 382
++pelee ARCH_PELEE PELEE 383
++e740 MACH_E740 E740 384
++iq80331 ARCH_IQ80331 IQ80331 385
++versatile_pb ARCH_VERSATILE_PB VERSATILE_PB 387
++kev7a400 MACH_KEV7A400 KEV7A400 388
++lpd7a400 MACH_LPD7A400 LPD7A400 389
++lpd7a404 MACH_LPD7A404 LPD7A404 390
++fujitsu_camelot ARCH_FUJITSU_CAMELOT FUJITSU_CAMELOT 391
++janus2m ARCH_JANUS2M JANUS2M 392
++embtf MACH_EMBTF EMBTF 393
++hpm MACH_HPM HPM 394
++smdk2410tk MACH_SMDK2410TK SMDK2410TK 395
++smdk2410aj MACH_SMDK2410AJ SMDK2410AJ 396
++streetracer MACH_STREETRACER STREETRACER 397
++eframe MACH_EFRAME EFRAME 398
++csb337 MACH_CSB337 CSB337 399
++pxa_lark MACH_PXA_LARK PXA_LARK 400
++pxa_pnp2110 MACH_PNP2110 PNP2110 401
++tcc72x MACH_TCC72X TCC72X 402
++altair MACH_ALTAIR ALTAIR 403
++kc3 MACH_KC3 KC3 404
++sinteftd MACH_SINTEFTD SINTEFTD 405
++mainstone MACH_MAINSTONE MAINSTONE 406
++aday4x MACH_ADAY4X ADAY4X 407
++lite300 MACH_LITE300 LITE300 408
++s5c7376 MACH_S5C7376 S5C7376 409
++mt02 MACH_MT02 MT02 410
++mport3s MACH_MPORT3S MPORT3S 411
++ra_alpha MACH_RA_ALPHA RA_ALPHA 412
++xcep MACH_XCEP XCEP 413
++arcom_vulcan MACH_ARCOM_VULCAN ARCOM_VULCAN 414
++stargate MACH_STARGATE STARGATE 415
++armadilloj MACH_ARMADILLOJ ARMADILLOJ 416
++elroy_jack MACH_ELROY_JACK ELROY_JACK 417
++backend MACH_BACKEND BACKEND 418
++s5linbox MACH_S5LINBOX S5LINBOX 419
++nomadik MACH_NOMADIK NOMADIK 420
++ia_cpu_9200 MACH_IA_CPU_9200 IA_CPU_9200 421
++at91_bja1 MACH_AT91_BJA1 AT91_BJA1 422
++corgi MACH_CORGI CORGI 423
++poodle MACH_POODLE POODLE 424
++ten MACH_TEN TEN 425
++roverp5p MACH_ROVERP5P ROVERP5P 426
++sc2700 MACH_SC2700 SC2700 427
++ex_eagle MACH_EX_EAGLE EX_EAGLE 428
++nx_pxa12 MACH_NX_PXA12 NX_PXA12 429
++nx_pxa5 MACH_NX_PXA5 NX_PXA5 430
++blackboard2 MACH_BLACKBOARD2 BLACKBOARD2 431
++i819 MACH_I819 I819 432
++ixmb995e MACH_IXMB995E IXMB995E 433
++skyrider MACH_SKYRIDER SKYRIDER 434
++skyhawk MACH_SKYHAWK SKYHAWK 435
++enterprise MACH_ENTERPRISE ENTERPRISE 436
++dep2410 MACH_DEP2410 DEP2410 437
++armcore MACH_ARMCORE ARMCORE 438
++hobbit MACH_HOBBIT HOBBIT 439
++h7210 MACH_H7210 H7210 440
++pxa_netdcu5 MACH_PXA_NETDCU5 PXA_NETDCU5 441
++acc MACH_ACC ACC 442
++esl_sarva MACH_ESL_SARVA ESL_SARVA 443
++xm250 MACH_XM250 XM250 444
++t6tc1xb MACH_T6TC1XB T6TC1XB 445
++ess710 MACH_ESS710 ESS710 446
++mx31ads MACH_MX31ADS MX31ADS 447
++himalaya MACH_HIMALAYA HIMALAYA 448
++bolfenk MACH_BOLFENK BOLFENK 449
++at91rm9200kr MACH_AT91RM9200KR AT91RM9200KR 450
++edb9312 MACH_EDB9312 EDB9312 451
++omap_generic MACH_OMAP_GENERIC OMAP_GENERIC 452
++aximx3 MACH_AXIMX3 AXIMX3 453
++eb67xdip MACH_EB67XDIP EB67XDIP 454
++webtxs MACH_WEBTXS WEBTXS 455
++hawk MACH_HAWK HAWK 456
++ccat91sbc001 MACH_CCAT91SBC001 CCAT91SBC001 457
++expresso MACH_EXPRESSO EXPRESSO 458
++h4000 MACH_H4000 H4000 459
++dino MACH_DINO DINO 460
++ml675k MACH_ML675K ML675K 461
++edb9301 MACH_EDB9301 EDB9301 462
++edb9315 MACH_EDB9315 EDB9315 463
++reciva_tt MACH_RECIVA_TT RECIVA_TT 464
++cstcb01 MACH_CSTCB01 CSTCB01 465
++cstcb1 MACH_CSTCB1 CSTCB1 466
++shadwell MACH_SHADWELL SHADWELL 467
++goepel263 MACH_GOEPEL263 GOEPEL263 468
++acq100 MACH_ACQ100 ACQ100 469
++mx1fs2 MACH_MX1FS2 MX1FS2 470
++hiptop_g1 MACH_HIPTOP_G1 HIPTOP_G1 471
++sparky MACH_SPARKY SPARKY 472
++ns9750 MACH_NS9750 NS9750 473
++phoenix MACH_PHOENIX PHOENIX 474
++vr1000 MACH_VR1000 VR1000 475
++deisterpxa MACH_DEISTERPXA DEISTERPXA 476
++bcm1160 MACH_BCM1160 BCM1160 477
++pcm022 MACH_PCM022 PCM022 478
++adsgcx MACH_ADSGCX ADSGCX 479
++dreadnaught MACH_DREADNAUGHT DREADNAUGHT 480
++dm320 MACH_DM320 DM320 481
++markov MACH_MARKOV MARKOV 482
++cos7a400 MACH_COS7A400 COS7A400 483
++milano MACH_MILANO MILANO 484
++ue9328 MACH_UE9328 UE9328 485
++uex255 MACH_UEX255 UEX255 486
++ue2410 MACH_UE2410 UE2410 487
++a620 MACH_A620 A620 488
++ocelot MACH_OCELOT OCELOT 489
++cheetah MACH_CHEETAH CHEETAH 490
++omap_perseus2 MACH_OMAP_PERSEUS2 OMAP_PERSEUS2 491
++zvue MACH_ZVUE ZVUE 492
++roverp1 MACH_ROVERP1 ROVERP1 493
++asidial2 MACH_ASIDIAL2 ASIDIAL2 494
++s3c24a0 MACH_S3C24A0 S3C24A0 495
++e800 MACH_E800 E800 496
++e750 MACH_E750 E750 497
++s3c5500 MACH_S3C5500 S3C5500 498
++smdk5500 MACH_SMDK5500 SMDK5500 499
++signalsync MACH_SIGNALSYNC SIGNALSYNC 500
++nbc MACH_NBC NBC 501
++kodiak MACH_KODIAK KODIAK 502
++netbookpro MACH_NETBOOKPRO NETBOOKPRO 503
++hw90200 MACH_HW90200 HW90200 504
++condor MACH_CONDOR CONDOR 505
++cup MACH_CUP CUP 506
++kite MACH_KITE KITE 507
++scb9328 MACH_SCB9328 SCB9328 508
++omap_h3 MACH_OMAP_H3 OMAP_H3 509
++omap_h4 MACH_OMAP_H4 OMAP_H4 510
++n10 MACH_N10 N10 511
++montejade MACH_MONTAJADE MONTAJADE 512
++sg560 MACH_SG560 SG560 513
++dp1000 MACH_DP1000 DP1000 514
++omap_osk MACH_OMAP_OSK OMAP_OSK 515
++rg100v3 MACH_RG100V3 RG100V3 516
++mx2ads MACH_MX2ADS MX2ADS 517
++pxa_kilo MACH_PXA_KILO PXA_KILO 518
++ixp4xx_eagle MACH_IXP4XX_EAGLE IXP4XX_EAGLE 519
++tosa MACH_TOSA TOSA 520
++mb2520f MACH_MB2520F MB2520F 521
++emc1000 MACH_EMC1000 EMC1000 522
++tidsc25 MACH_TIDSC25 TIDSC25 523
++akcpmxl MACH_AKCPMXL AKCPMXL 524
++av3xx MACH_AV3XX AV3XX 525
++avila MACH_AVILA AVILA 526
++pxa_mpm10 MACH_PXA_MPM10 PXA_MPM10 527
++pxa_kyanite MACH_PXA_KYANITE PXA_KYANITE 528
++sgold MACH_SGOLD SGOLD 529
++oscar MACH_OSCAR OSCAR 530
++epxa4usb2 MACH_EPXA4USB2 EPXA4USB2 531
++xsengine MACH_XSENGINE XSENGINE 532
++ip600 MACH_IP600 IP600 533
++mcan2 MACH_MCAN2 MCAN2 534
++ddi_blueridge MACH_DDI_BLUERIDGE DDI_BLUERIDGE 535
++skyminder MACH_SKYMINDER SKYMINDER 536
++lpd79520 MACH_LPD79520 LPD79520 537
++edb9302 MACH_EDB9302 EDB9302 538
++hw90340 MACH_HW90340 HW90340 539
++cip_box MACH_CIP_BOX CIP_BOX 540
++ivpn MACH_IVPN IVPN 541
++rsoc2 MACH_RSOC2 RSOC2 542
++husky MACH_HUSKY HUSKY 543
++boxer MACH_BOXER BOXER 544
++shepherd MACH_SHEPHERD SHEPHERD 545
++aml42800aa MACH_AML42800AA AML42800AA 546
++lpc2294 MACH_LPC2294 LPC2294 548
++switchgrass MACH_SWITCHGRASS SWITCHGRASS 549
++ens_cmu MACH_ENS_CMU ENS_CMU 550
++mm6_sdb MACH_MM6_SDB MM6_SDB 551
++saturn MACH_SATURN SATURN 552
++i30030evb MACH_I30030EVB I30030EVB 553
++mxc27530evb MACH_MXC27530EVB MXC27530EVB 554
++smdk2800 MACH_SMDK2800 SMDK2800 555
++mtwilson MACH_MTWILSON MTWILSON 556
++ziti MACH_ZITI ZITI 557
++grandfather MACH_GRANDFATHER GRANDFATHER 558
++tengine MACH_TENGINE TENGINE 559
++s3c2460 MACH_S3C2460 S3C2460 560
++pdm MACH_PDM PDM 561
++h4700 MACH_H4700 H4700 562
++h6300 MACH_H6300 H6300 563
++rz1700 MACH_RZ1700 RZ1700 564
++a716 MACH_A716 A716 565
++estk2440a MACH_ESTK2440A ESTK2440A 566
++atwixp425 MACH_ATWIXP425 ATWIXP425 567
++csb336 MACH_CSB336 CSB336 568
++rirm2 MACH_RIRM2 RIRM2 569
++cx23518 MACH_CX23518 CX23518 570
++cx2351x MACH_CX2351X CX2351X 571
++computime MACH_COMPUTIME COMPUTIME 572
++izarus MACH_IZARUS IZARUS 573
++pxa_rts MACH_RTS RTS 574
++se5100 MACH_SE5100 SE5100 575
++s3c2510 MACH_S3C2510 S3C2510 576
++csb437tl MACH_CSB437TL CSB437TL 577
++slauson MACH_SLAUSON SLAUSON 578
++pearlriver MACH_PEARLRIVER PEARLRIVER 579
++tdc_p210 MACH_TDC_P210 TDC_P210 580
++sg580 MACH_SG580 SG580 581
++wrsbcarm7 MACH_WRSBCARM7 WRSBCARM7 582
++ipd MACH_IPD IPD 583
++pxa_dnp2110 MACH_PXA_DNP2110 PXA_DNP2110 584
++xaeniax MACH_XAENIAX XAENIAX 585
++somn4250 MACH_SOMN4250 SOMN4250 586
++pleb2 MACH_PLEB2 PLEB2 587
++cornwallis MACH_CORNWALLIS CORNWALLIS 588
++gurney_drv MACH_GURNEY_DRV GURNEY_DRV 589
++chaffee MACH_CHAFFEE CHAFFEE 590
++rms101 MACH_RMS101 RMS101 591
++rx3715 MACH_RX3715 RX3715 592
++swift MACH_SWIFT SWIFT 593
++roverp7 MACH_ROVERP7 ROVERP7 594
++pr818s MACH_PR818S PR818S 595
++trxpro MACH_TRXPRO TRXPRO 596
++nslu2 MACH_NSLU2 NSLU2 597
++e400 MACH_E400 E400 598
++trab MACH_TRAB TRAB 599
++cmc_pu2 MACH_CMC_PU2 CMC_PU2 600
++fulcrum MACH_FULCRUM FULCRUM 601
++netgate42x MACH_NETGATE42X NETGATE42X 602
++str710 MACH_STR710 STR710 603
++ixdpg425 MACH_IXDPG425 IXDPG425 604
++tomtomgo MACH_TOMTOMGO TOMTOMGO 605
++versatile_ab MACH_VERSATILE_AB VERSATILE_AB 606
++edb9307 MACH_EDB9307 EDB9307 607
++sg565 MACH_SG565 SG565 608
++lpd79524 MACH_LPD79524 LPD79524 609
++lpd79525 MACH_LPD79525 LPD79525 610
++rms100 MACH_RMS100 RMS100 611
++kb9200 MACH_KB9200 KB9200 612
++sx1 MACH_SX1 SX1 613
++hms39c7092 MACH_HMS39C7092 HMS39C7092 614
++armadillo MACH_ARMADILLO ARMADILLO 615
++ipcu MACH_IPCU IPCU 616
++loox720 MACH_LOOX720 LOOX720 617
++ixdp465 MACH_IXDP465 IXDP465 618
++ixdp2351 MACH_IXDP2351 IXDP2351 619
++adsvix MACH_ADSVIX ADSVIX 620
++dm270 MACH_DM270 DM270 621
++socltplus MACH_SOCLTPLUS SOCLTPLUS 622
++ecia MACH_ECIA ECIA 623
++cm4008 MACH_CM4008 CM4008 624
++p2001 MACH_P2001 P2001 625
++twister MACH_TWISTER TWISTER 626
++mudshark MACH_MUDSHARK MUDSHARK 627
++hb2 MACH_HB2 HB2 628
++iq80332 MACH_IQ80332 IQ80332 629
++sendt MACH_SENDT SENDT 630
++mx2jazz MACH_MX2JAZZ MX2JAZZ 631
++multiio MACH_MULTIIO MULTIIO 632
++hrdisplay MACH_HRDISPLAY HRDISPLAY 633
++mxc27530ads MACH_MXC27530ADS MXC27530ADS 634
++trizeps3 MACH_TRIZEPS3 TRIZEPS3 635
++zefeerdza MACH_ZEFEERDZA ZEFEERDZA 636
++zefeerdzb MACH_ZEFEERDZB ZEFEERDZB 637
++zefeerdzg MACH_ZEFEERDZG ZEFEERDZG 638
++zefeerdzn MACH_ZEFEERDZN ZEFEERDZN 639
++zefeerdzq MACH_ZEFEERDZQ ZEFEERDZQ 640
++gtwx5715 MACH_GTWX5715 GTWX5715 641
++astro_jack MACH_ASTRO_JACK ASTRO_JACK 643
++tip03 MACH_TIP03 TIP03 644
++a9200ec MACH_A9200EC A9200EC 645
++pnx0105 MACH_PNX0105 PNX0105 646
++adcpoecpu MACH_ADCPOECPU ADCPOECPU 647
++csb637 MACH_CSB637 CSB637 648
++mb9200 MACH_MB9200 MB9200 650
++kulun MACH_KULUN KULUN 651
++snapper MACH_SNAPPER SNAPPER 652
++optima MACH_OPTIMA OPTIMA 653
++dlhsbc MACH_DLHSBC DLHSBC 654
++x30 MACH_X30 X30 655
++n30 MACH_N30 N30 656
++manga_ks8695 MACH_MANGA_KS8695 MANGA_KS8695 657
++ajax MACH_AJAX AJAX 658
++nec_mp900 MACH_NEC_MP900 NEC_MP900 659
++vvtk1000 MACH_VVTK1000 VVTK1000 661
++kafa MACH_KAFA KAFA 662
++vvtk3000 MACH_VVTK3000 VVTK3000 663
++pimx1 MACH_PIMX1 PIMX1 664
++ollie MACH_OLLIE OLLIE 665
++skymax MACH_SKYMAX SKYMAX 666
++jazz MACH_JAZZ JAZZ 667
++tel_t3 MACH_TEL_T3 TEL_T3 668
++aisino_fcr255 MACH_AISINO_FCR255 AISINO_FCR255 669
++btweb MACH_BTWEB BTWEB 670
++dbg_lh79520 MACH_DBG_LH79520 DBG_LH79520 671
++cm41xx MACH_CM41XX CM41XX 672
++ts72xx MACH_TS72XX TS72XX 673
++nggpxa MACH_NGGPXA NGGPXA 674
++csb535 MACH_CSB535 CSB535 675
++csb536 MACH_CSB536 CSB536 676
++pxa_trakpod MACH_PXA_TRAKPOD PXA_TRAKPOD 677
++praxis MACH_PRAXIS PRAXIS 678
++lh75411 MACH_LH75411 LH75411 679
++otom MACH_OTOM OTOM 680
++nexcoder_2440 MACH_NEXCODER_2440 NEXCODER_2440 681
++loox410 MACH_LOOX410 LOOX410 682
++westlake MACH_WESTLAKE WESTLAKE 683
++nsb MACH_NSB NSB 684
++esl_sarva_stn MACH_ESL_SARVA_STN ESL_SARVA_STN 685
++esl_sarva_tft MACH_ESL_SARVA_TFT ESL_SARVA_TFT 686
++esl_sarva_iad MACH_ESL_SARVA_IAD ESL_SARVA_IAD 687
++esl_sarva_acc MACH_ESL_SARVA_ACC ESL_SARVA_ACC 688
++typhoon MACH_TYPHOON TYPHOON 689
++cnav MACH_CNAV CNAV 690
++a730 MACH_A730 A730 691
++netstar MACH_NETSTAR NETSTAR 692
++supercon MACH_PHASEFALE_SUPERCON PHASEFALE_SUPERCON 693
++shiva1100 MACH_SHIVA1100 SHIVA1100 694
++etexsc MACH_ETEXSC ETEXSC 695
++ixdpg465 MACH_IXDPG465 IXDPG465 696
++a9m2410 MACH_A9M2410 A9M2410 697
++a9m2440 MACH_A9M2440 A9M2440 698
++a9m9750 MACH_A9M9750 A9M9750 699
++a9m9360 MACH_A9M9360 A9M9360 700
++unc90 MACH_UNC90 UNC90 701
++eco920 MACH_ECO920 ECO920 702
++satview MACH_SATVIEW SATVIEW 703
++roadrunner MACH_ROADRUNNER ROADRUNNER 704
++at91rm9200ek MACH_AT91RM9200EK AT91RM9200EK 705
++gp32 MACH_GP32 GP32 706
++gem MACH_GEM GEM 707
++i858 MACH_I858 I858 708
++hx2750 MACH_HX2750 HX2750 709
++mxc91131evb MACH_MXC91131EVB MXC91131EVB 710
++p700 MACH_P700 P700 711
++cpe MACH_CPE CPE 712
++spitz MACH_SPITZ SPITZ 713
++nimbra340 MACH_NIMBRA340 NIMBRA340 714
++lpc22xx MACH_LPC22XX LPC22XX 715
++omap_comet3 MACH_COMET3 COMET3 716
++omap_comet4 MACH_COMET4 COMET4 717
++csb625 MACH_CSB625 CSB625 718
++fortunet2 MACH_FORTUNET2 FORTUNET2 719
++s5h2200 MACH_S5H2200 S5H2200 720
++optorm920 MACH_OPTORM920 OPTORM920 721
++adsbitsyxb MACH_ADSBITSYXB ADSBITSYXB 722
++adssphere MACH_ADSSPHERE ADSSPHERE 723
++adsportal MACH_ADSPORTAL ADSPORTAL 724
++ln2410sbc MACH_LN2410SBC LN2410SBC 725
++cb3rufc MACH_CB3RUFC CB3RUFC 726
++mp2usb MACH_MP2USB MP2USB 727
++ntnp425c MACH_NTNP425C NTNP425C 728
++colibri MACH_COLIBRI COLIBRI 729
++pcm7220 MACH_PCM7220 PCM7220 730
++gateway7001 MACH_GATEWAY7001 GATEWAY7001 731
++pcm027 MACH_PCM027 PCM027 732
++cmpxa MACH_CMPXA CMPXA 733
++anubis MACH_ANUBIS ANUBIS 734
++ite8152 MACH_ITE8152 ITE8152 735
++lpc3xxx MACH_LPC3XXX LPC3XXX 736
++puppeteer MACH_PUPPETEER PUPPETEER 737
++e570 MACH_E570 E570 739
++x50 MACH_X50 X50 740
++recon MACH_RECON RECON 741
++xboardgp8 MACH_XBOARDGP8 XBOARDGP8 742
++fpic2 MACH_FPIC2 FPIC2 743
++akita MACH_AKITA AKITA 744
++a81 MACH_A81 A81 745
++svm_sc25x MACH_SVM_SC25X SVM_SC25X 746
++vt020 MACH_VADATECH020 VADATECH020 747
++tli MACH_TLI TLI 748
++edb9315lc MACH_EDB9315LC EDB9315LC 749
++passec MACH_PASSEC PASSEC 750
++ds_tiger MACH_DS_TIGER DS_TIGER 751
++e310 MACH_E310 E310 752
++e330 MACH_E330 E330 753
++rt3000 MACH_RT3000 RT3000 754
++nokia770 MACH_NOKIA770 NOKIA770 755
++pnx0106 MACH_PNX0106 PNX0106 756
++hx21xx MACH_HX21XX HX21XX 757
++faraday MACH_FARADAY FARADAY 758
++sbc9312 MACH_SBC9312 SBC9312 759
++batman MACH_BATMAN BATMAN 760
++jpd201 MACH_JPD201 JPD201 761
++mipsa MACH_MIPSA MIPSA 762
++kacom MACH_KACOM KACOM 763
++swarcocpu MACH_SWARCOCPU SWARCOCPU 764
++swarcodsl MACH_SWARCODSL SWARCODSL 765
++blueangel MACH_BLUEANGEL BLUEANGEL 766
++hairygrama MACH_HAIRYGRAMA HAIRYGRAMA 767
++banff MACH_BANFF BANFF 768
++carmeva MACH_CARMEVA CARMEVA 769
++sam255 MACH_SAM255 SAM255 770
++ppm10 MACH_PPM10 PPM10 771
++edb9315a MACH_EDB9315A EDB9315A 772
++sunset MACH_SUNSET SUNSET 773
++stargate2 MACH_STARGATE2 STARGATE2 774
++intelmote2 MACH_INTELMOTE2 INTELMOTE2 775
++trizeps4 MACH_TRIZEPS4 TRIZEPS4 776
++mainstone2 MACH_MAINSTONE2 MAINSTONE2 777
++ez_ixp42x MACH_EZ_IXP42X EZ_IXP42X 778
++tapwave_zodiac MACH_TAPWAVE_ZODIAC TAPWAVE_ZODIAC 779
++universalmeter MACH_UNIVERSALMETER UNIVERSALMETER 780
++hicoarm9 MACH_HICOARM9 HICOARM9 781
++pnx4008 MACH_PNX4008 PNX4008 782
++kws6000 MACH_KWS6000 KWS6000 783
++portux920t MACH_PORTUX920T PORTUX920T 784
++ez_x5 MACH_EZ_X5 EZ_X5 785
++omap_rudolph MACH_OMAP_RUDOLPH OMAP_RUDOLPH 786
++cpuat91 MACH_CPUAT91 CPUAT91 787
++rea9200 MACH_REA9200 REA9200 788
++acts_pune_sa1110 MACH_ACTS_PUNE_SA1110 ACTS_PUNE_SA1110 789
++ixp425 MACH_IXP425 IXP425 790
++i30030ads MACH_I30030ADS I30030ADS 791
++perch MACH_PERCH PERCH 792
++eis05r1 MACH_EIS05R1 EIS05R1 793
++pepperpad MACH_PEPPERPAD PEPPERPAD 794
++sb3010 MACH_SB3010 SB3010 795
++rm9200 MACH_RM9200 RM9200 796
++dma03 MACH_DMA03 DMA03 797
++road_s101 MACH_ROAD_S101 ROAD_S101 798
++iq81340sc MACH_IQ81340SC IQ81340SC 799
++iq_nextgen_b MACH_IQ_NEXTGEN_B IQ_NEXTGEN_B 800
++iq81340mc MACH_IQ81340MC IQ81340MC 801
++iq_nextgen_d MACH_IQ_NEXTGEN_D IQ_NEXTGEN_D 802
++iq_nextgen_e MACH_IQ_NEXTGEN_E IQ_NEXTGEN_E 803
++mallow_at91 MACH_MALLOW_AT91 MALLOW_AT91 804
++cybertracker_i MACH_CYBERTRACKER_I CYBERTRACKER_I 805
++gesbc931x MACH_GESBC931X GESBC931X 806
++centipad MACH_CENTIPAD CENTIPAD 807
++armsoc MACH_ARMSOC ARMSOC 808
++se4200 MACH_SE4200 SE4200 809
++ems197a MACH_EMS197A EMS197A 810
++micro9 MACH_MICRO9 MICRO9 811
++micro9l MACH_MICRO9L MICRO9L 812
++uc5471dsp MACH_UC5471DSP UC5471DSP 813
++sj5471eng MACH_SJ5471ENG SJ5471ENG 814
++none MACH_CMPXA26X CMPXA26X 815
++nc1 MACH_NC NC 816
++omap_palmte MACH_OMAP_PALMTE OMAP_PALMTE 817
++ajax52x MACH_AJAX52X AJAX52X 818
++siriustar MACH_SIRIUSTAR SIRIUSTAR 819
++iodata_hdlg MACH_IODATA_HDLG IODATA_HDLG 820
++at91rm9200utl MACH_AT91RM9200UTL AT91RM9200UTL 821
++biosafe MACH_BIOSAFE BIOSAFE 822
++mp1000 MACH_MP1000 MP1000 823
++parsy MACH_PARSY PARSY 824
++ccxp270 MACH_CCXP CCXP 825
++omap_gsample MACH_OMAP_GSAMPLE OMAP_GSAMPLE 826
++realview_eb MACH_REALVIEW_EB REALVIEW_EB 827
++samoa MACH_SAMOA SAMOA 828
++palmt3 MACH_PALMT3 PALMT3 829
++i878 MACH_I878 I878 830
++borzoi MACH_BORZOI BORZOI 831
++gecko MACH_GECKO GECKO 832
++ds101 MACH_DS101 DS101 833
++omap_palmtt2 MACH_OMAP_PALMTT2 OMAP_PALMTT2 834
++palmld MACH_PALMLD PALMLD 835
++cc9c MACH_CC9C CC9C 836
++sbc1670 MACH_SBC1670 SBC1670 837
++ixdp28x5 MACH_IXDP28X5 IXDP28X5 838
++omap_palmtt MACH_OMAP_PALMTT OMAP_PALMTT 839
++ml696k MACH_ML696K ML696K 840
++arcom_zeus MACH_ARCOM_ZEUS ARCOM_ZEUS 841
++osiris MACH_OSIRIS OSIRIS 842
++maestro MACH_MAESTRO MAESTRO 843
++palmte2 MACH_PALMTE2 PALMTE2 844
++ixbbm MACH_IXBBM IXBBM 845
++mx27ads MACH_MX27ADS MX27ADS 846
++ax8004 MACH_AX8004 AX8004 847
++at91sam9261ek MACH_AT91SAM9261EK AT91SAM9261EK 848
++loft MACH_LOFT LOFT 849
++magpie MACH_MAGPIE MAGPIE 850
++mx21ads MACH_MX21ADS MX21ADS 851
++mb87m3400 MACH_MB87M3400 MB87M3400 852
++mguard_delta MACH_MGUARD_DELTA MGUARD_DELTA 853
++davinci_dvdp MACH_DAVINCI_DVDP DAVINCI_DVDP 854
++htcuniversal MACH_HTCUNIVERSAL HTCUNIVERSAL 855
++tpad MACH_TPAD TPAD 856
++roverp3 MACH_ROVERP3 ROVERP3 857
++jornada928 MACH_JORNADA928 JORNADA928 858
++mv88fxx81 MACH_MV88FXX81 MV88FXX81 859
++stmp36xx MACH_STMP36XX STMP36XX 860
++sxni79524 MACH_SXNI79524 SXNI79524 861
++ams_delta MACH_AMS_DELTA AMS_DELTA 862
++uranium MACH_URANIUM URANIUM 863
++ucon MACH_UCON UCON 864
++nas100d MACH_NAS100D NAS100D 865
++l083 MACH_L083_1000 L083_1000 866
++ezx MACH_EZX EZX 867
++pnx5220 MACH_PNX5220 PNX5220 868
++butte MACH_BUTTE BUTTE 869
++srm2 MACH_SRM2 SRM2 870
++dsbr MACH_DSBR DSBR 871
++crystalball MACH_CRYSTALBALL CRYSTALBALL 872
++tinypxa27x MACH_TINYPXA27X TINYPXA27X 873
++herbie MACH_HERBIE HERBIE 874
++magician MACH_MAGICIAN MAGICIAN 875
++cm4002 MACH_CM4002 CM4002 876
++b4 MACH_B4 B4 877
++maui MACH_MAUI MAUI 878
++cybertracker_g MACH_CYBERTRACKER_G CYBERTRACKER_G 879
++nxdkn MACH_NXDKN NXDKN 880
++mio8390 MACH_MIO8390 MIO8390 881
++omi_board MACH_OMI_BOARD OMI_BOARD 882
++mx21civ MACH_MX21CIV MX21CIV 883
++mahi_cdac MACH_MAHI_CDAC MAHI_CDAC 884
++palmtx MACH_PALMTX PALMTX 885
++s3c2413 MACH_S3C2413 S3C2413 887
++samsys_ep0 MACH_SAMSYS_EP0 SAMSYS_EP0 888
++wg302v1 MACH_WG302V1 WG302V1 889
++wg302v2 MACH_WG302V2 WG302V2 890
++eb42x MACH_EB42X EB42X 891
++iq331es MACH_IQ331ES IQ331ES 892
++cosydsp MACH_COSYDSP COSYDSP 893
++uplat7d_proto MACH_UPLAT7D UPLAT7D 894
++ptdavinci MACH_PTDAVINCI PTDAVINCI 895
++mbus MACH_MBUS MBUS 896
++nadia2vb MACH_NADIA2VB NADIA2VB 897
++r1000 MACH_R1000 R1000 898
++hw90250 MACH_HW90250 HW90250 899
++omap_2430sdp MACH_OMAP_2430SDP OMAP_2430SDP 900
++davinci_evm MACH_DAVINCI_EVM DAVINCI_EVM 901
++omap_tornado MACH_OMAP_TORNADO OMAP_TORNADO 902
++olocreek MACH_OLOCREEK OLOCREEK 903
++palmz72 MACH_PALMZ72 PALMZ72 904
++nxdb500 MACH_NXDB500 NXDB500 905
++apf9328 MACH_APF9328 APF9328 906
++omap_wipoq MACH_OMAP_WIPOQ OMAP_WIPOQ 907
++omap_twip MACH_OMAP_TWIP OMAP_TWIP 908
++treo650 MACH_TREO650 TREO650 909
++acumen MACH_ACUMEN ACUMEN 910
++xp100 MACH_XP100 XP100 911
++fs2410 MACH_FS2410 FS2410 912
++pxa270_cerf MACH_PXA270_CERF PXA270_CERF 913
++sq2ftlpalm MACH_SQ2FTLPALM SQ2FTLPALM 914
++bsemserver MACH_BSEMSERVER BSEMSERVER 915
++netclient MACH_NETCLIENT NETCLIENT 916
++palmt5 MACH_PALMT5 PALMT5 917
++palmtc MACH_PALMTC PALMTC 918
++omap_apollon MACH_OMAP_APOLLON OMAP_APOLLON 919
++mxc30030evb MACH_MXC30030EVB MXC30030EVB 920
++rea_cpu2 MACH_REA_2D REA_2D 921
++eti3e524 MACH_TI3E524 TI3E524 922
++ateb9200 MACH_ATEB9200 ATEB9200 923
++auckland MACH_AUCKLAND AUCKLAND 924
++ak3220m MACH_AK3320M AK3320M 925
++duramax MACH_DURAMAX DURAMAX 926
++n35 MACH_N35 N35 927
++pronghorn MACH_PRONGHORN PRONGHORN 928
++fundy MACH_FUNDY FUNDY 929
++logicpd_pxa270 MACH_LOGICPD_PXA270 LOGICPD_PXA270 930
++cpu777 MACH_CPU777 CPU777 931
++simicon9201 MACH_SIMICON9201 SIMICON9201 932
++leap2_hpm MACH_LEAP2_HPM LEAP2_HPM 933
++cm922txa10 MACH_CM922TXA10 CM922TXA10 934
++sandgate MACH_PXA PXA 935
++sandgate2 MACH_SANDGATE2 SANDGATE2 936
++sandgate2g MACH_SANDGATE2G SANDGATE2G 937
++sandgate2p MACH_SANDGATE2P SANDGATE2P 938
++fred_jack MACH_FRED_JACK FRED_JACK 939
++ttg_color1 MACH_TTG_COLOR1 TTG_COLOR1 940
++nxeb500hmi MACH_NXEB500HMI NXEB500HMI 941
++netdcu8 MACH_NETDCU8 NETDCU8 942
++ng_fvx538 MACH_NG_FVX538 NG_FVX538 944
++ng_fvs338 MACH_NG_FVS338 NG_FVS338 945
++pnx4103 MACH_PNX4103 PNX4103 946
++hesdb MACH_HESDB HESDB 947
++xsilo MACH_XSILO XSILO 948
++espresso MACH_ESPRESSO ESPRESSO 949
++emlc MACH_EMLC EMLC 950
++sisteron MACH_SISTERON SISTERON 951
++rx1950 MACH_RX1950 RX1950 952
++tsc_venus MACH_TSC_VENUS TSC_VENUS 953
++ds101j MACH_DS101J DS101J 954
++mxc30030ads MACH_MXC30030ADS MXC30030ADS 955
++fujitsu_wimaxsoc MACH_FUJITSU_WIMAXSOC FUJITSU_WIMAXSOC 956
++dualpcmodem MACH_DUALPCMODEM DUALPCMODEM 957
++gesbc9312 MACH_GESBC9312 GESBC9312 958
++htcapache MACH_HTCAPACHE HTCAPACHE 959
++ixdp435 MACH_IXDP435 IXDP435 960
++catprovt100 MACH_CATPROVT100 CATPROVT100 961
++picotux1xx MACH_PICOTUX1XX PICOTUX1XX 962
++picotux2xx MACH_PICOTUX2XX PICOTUX2XX 963
++dsmg600 MACH_DSMG600 DSMG600 964
++empc2 MACH_EMPC2 EMPC2 965
++ventura MACH_VENTURA VENTURA 966
++phidget_sbc MACH_PHIDGET_SBC PHIDGET_SBC 967
++ij3k MACH_IJ3K IJ3K 968
++pisgah MACH_PISGAH PISGAH 969
++omap_fsample MACH_OMAP_FSAMPLE OMAP_FSAMPLE 970
++sg720 MACH_SG720 SG720 971
++redfox MACH_REDFOX REDFOX 972
++mysh_ep9315_1 MACH_MYSH_EP9315_1 MYSH_EP9315_1 973
++tpf106 MACH_TPF106 TPF106 974
++at91rm9200kg MACH_AT91RM9200KG AT91RM9200KG 975
++rcmt2 MACH_SLEDB SLEDB 976
++ontrack MACH_ONTRACK ONTRACK 977
++pm1200 MACH_PM1200 PM1200 978
++ess24562 MACH_ESS24XXX ESS24XXX 979
++coremp7 MACH_COREMP7 COREMP7 980
++nexcoder_6446 MACH_NEXCODER_6446 NEXCODER_6446 981
++stvc8380 MACH_STVC8380 STVC8380 982
++teklynx MACH_TEKLYNX TEKLYNX 983
++carbonado MACH_CARBONADO CARBONADO 984
++sysmos_mp730 MACH_SYSMOS_MP730 SYSMOS_MP730 985
++snapper_cl15 MACH_SNAPPER_CL15 SNAPPER_CL15 986
++pgigim MACH_PGIGIM PGIGIM 987
++ptx9160p2 MACH_PTX9160P2 PTX9160P2 988
++dcore1 MACH_DCORE1 DCORE1 989
++victorpxa MACH_VICTORPXA VICTORPXA 990
++mx2dtb MACH_MX2DTB MX2DTB 991
++pxa_irex_er0100 MACH_PXA_IREX_ER0100 PXA_IREX_ER0100 992
++omap_palmz71 MACH_OMAP_PALMZ71 OMAP_PALMZ71 993
++bartec_deg MACH_BARTEC_DEG BARTEC_DEG 994
++hw50251 MACH_HW50251 HW50251 995
++ibox MACH_IBOX IBOX 996
++atlaslh7a404 MACH_ATLASLH7A404 ATLASLH7A404 997
++pt2026 MACH_PT2026 PT2026 998
++htcalpine MACH_HTCALPINE HTCALPINE 999
++bartec_vtu MACH_BARTEC_VTU BARTEC_VTU 1000
++vcoreii MACH_VCOREII VCOREII 1001
++pdnb3 MACH_PDNB3 PDNB3 1002
++htcbeetles MACH_HTCBEETLES HTCBEETLES 1003
++s3c6400 MACH_S3C6400 S3C6400 1004
++s3c2443 MACH_S3C2443 S3C2443 1005
++omap_ldk MACH_OMAP_LDK OMAP_LDK 1006
++smdk2460 MACH_SMDK2460 SMDK2460 1007
++smdk2440 MACH_SMDK2440 SMDK2440 1008
++smdk2412 MACH_SMDK2412 SMDK2412 1009
++webbox MACH_WEBBOX WEBBOX 1010
++cwwndp MACH_CWWNDP CWWNDP 1011
++i839 MACH_DRAGON DRAGON 1012
++opendo_cpu_board MACH_OPENDO_CPU_BOARD OPENDO_CPU_BOARD 1013
++ccm2200 MACH_CCM2200 CCM2200 1014
++etwarm MACH_ETWARM ETWARM 1015
++m93030 MACH_M93030 M93030 1016
++cc7u MACH_CC7U CC7U 1017
++mtt_ranger MACH_MTT_RANGER MTT_RANGER 1018
++nexus MACH_NEXUS NEXUS 1019
++desman MACH_DESMAN DESMAN 1020
++bkde303 MACH_BKDE303 BKDE303 1021
++smdk2413 MACH_SMDK2413 SMDK2413 1022
++aml_m7200 MACH_AML_M7200 AML_M7200 1023
++aml_m5900 MACH_AML_M5900 AML_M5900 1024
++sg640 MACH_SG640 SG640 1025
++edg79524 MACH_EDG79524 EDG79524 1026
++ai2410 MACH_AI2410 AI2410 1027
++ixp465 MACH_IXP465 IXP465 1028
++balloon3 MACH_BALLOON3 BALLOON3 1029
++heins MACH_HEINS HEINS 1030
++mpluseva MACH_MPLUSEVA MPLUSEVA 1031
++rt042 MACH_RT042 RT042 1032
++cwiem MACH_CWIEM CWIEM 1033
++cm_x270 MACH_CM_X270 CM_X270 1034
++cm_x255 MACH_CM_X255 CM_X255 1035
++esh_at91 MACH_ESH_AT91 ESH_AT91 1036
++sandgate3 MACH_SANDGATE3 SANDGATE3 1037
++primo MACH_PRIMO PRIMO 1038
++gemstone MACH_GEMSTONE GEMSTONE 1039
++pronghorn_metro MACH_PRONGHORNMETRO PRONGHORNMETRO 1040
++sidewinder MACH_SIDEWINDER SIDEWINDER 1041
++picomod1 MACH_PICOMOD1 PICOMOD1 1042
++sg590 MACH_SG590 SG590 1043
++akai9307 MACH_AKAI9307 AKAI9307 1044
++fontaine MACH_FONTAINE FONTAINE 1045
++wombat MACH_WOMBAT WOMBAT 1046
++acq300 MACH_ACQ300 ACQ300 1047
++mod272 MACH_MOD_270 MOD_270 1048
++vmc_vc0820 MACH_VC0820 VC0820 1049
++ani_aim MACH_ANI_AIM ANI_AIM 1050
++jellyfish MACH_JELLYFISH JELLYFISH 1051
++amanita MACH_AMANITA AMANITA 1052
++vlink MACH_VLINK VLINK 1053
++dexflex MACH_DEXFLEX DEXFLEX 1054
++eigen_ttq MACH_EIGEN_TTQ EIGEN_TTQ 1055
++arcom_titan MACH_ARCOM_TITAN ARCOM_TITAN 1056
++tabla MACH_TABLA TABLA 1057
++mdirac3 MACH_MDIRAC3 MDIRAC3 1058
++mrhfbp2 MACH_MRHFBP2 MRHFBP2 1059
++at91rm9200rb MACH_AT91RM9200RB AT91RM9200RB 1060
++ani_apm MACH_ANI_APM ANI_APM 1061
++ella1 MACH_ELLA1 ELLA1 1062
++inhand_pxa27x MACH_INHAND_PXA27X INHAND_PXA27X 1063
++inhand_pxa25x MACH_INHAND_PXA25X INHAND_PXA25X 1064
++empos_xm MACH_EMPOS_XM EMPOS_XM 1065
++empos MACH_EMPOS EMPOS 1066
++empos_tiny MACH_EMPOS_TINY EMPOS_TINY 1067
++empos_sm MACH_EMPOS_SM EMPOS_SM 1068
++egret MACH_EGRET EGRET 1069
++ostrich MACH_OSTRICH OSTRICH 1070
++n50 MACH_N50 N50 1071
++ecbat91 MACH_ECBAT91 ECBAT91 1072
++stareast MACH_STAREAST STAREAST 1073
++dspg_dw MACH_DSPG_DW DSPG_DW 1074
++onearm MACH_ONEARM ONEARM 1075
++mrg110_6 MACH_MRG110_6 MRG110_6 1076
++wrt300nv2 MACH_WRT300NV2 WRT300NV2 1077
++xm_bulverde MACH_XM_BULVERDE XM_BULVERDE 1078
++msm6100 MACH_MSM6100 MSM6100 1079
++eti_b1 MACH_ETI_B1 ETI_B1 1080
++za9l_series MACH_ZILOG_ZA9L ZILOG_ZA9L 1081
++bit2440 MACH_BIT2440 BIT2440 1082
++nbi MACH_NBI NBI 1083
++smdk2443 MACH_SMDK2443 SMDK2443 1084
++vdavinci MACH_VDAVINCI VDAVINCI 1085
++atc6 MACH_ATC6 ATC6 1086
++multmdw MACH_MULTMDW MULTMDW 1087
++mba2440 MACH_MBA2440 MBA2440 1088
++ecsd MACH_ECSD ECSD 1089
++palmz31 MACH_PALMZ31 PALMZ31 1090
++fsg MACH_FSG FSG 1091
++razor101 MACH_RAZOR101 RAZOR101 1092
++opera_tdm MACH_OPERA_TDM OPERA_TDM 1093
++comcerto MACH_COMCERTO COMCERTO 1094
++tb0319 MACH_TB0319 TB0319 1095
++kws8000 MACH_KWS8000 KWS8000 1096
++b2 MACH_B2 B2 1097
++lcl54 MACH_LCL54 LCL54 1098
++at91sam9260ek MACH_AT91SAM9260EK AT91SAM9260EK 1099
++glantank MACH_GLANTANK GLANTANK 1100
++n2100 MACH_N2100 N2100 1101
++n4100 MACH_N4100 N4100 1102
++rsc4 MACH_VERTICAL_RSC4 VERTICAL_RSC4 1103
++sg8100 MACH_SG8100 SG8100 1104
++im42xx MACH_IM42XX IM42XX 1105
++ftxx MACH_FTXX FTXX 1106
++lwfusion MACH_LWFUSION LWFUSION 1107
++qt2410 MACH_QT2410 QT2410 1108
++kixrp435 MACH_KIXRP435 KIXRP435 1109
++ccw9c MACH_CCW9C CCW9C 1110
++dabhs MACH_DABHS DABHS 1111
++gzmx MACH_GZMX GZMX 1112
++ipnw100ap MACH_IPNW100AP IPNW100AP 1113
++cc9p9360dev MACH_CC9P9360DEV CC9P9360DEV 1114
++cc9p9750dev MACH_CC9P9750DEV CC9P9750DEV 1115
++cc9p9360val MACH_CC9P9360VAL CC9P9360VAL 1116
++cc9p9750val MACH_CC9P9750VAL CC9P9750VAL 1117
++nx70v MACH_NX70V NX70V 1118
++at91rm9200df MACH_AT91RM9200DF AT91RM9200DF 1119
++se_pilot2 MACH_SE_PILOT2 SE_PILOT2 1120
++mtcn_t800 MACH_MTCN_T800 MTCN_T800 1121
++vcmx212 MACH_VCMX212 VCMX212 1122
++lynx MACH_LYNX LYNX 1123
++at91sam9260id MACH_AT91SAM9260ID AT91SAM9260ID 1124
++hw86052 MACH_HW86052 HW86052 1125
++pilz_pmi3 MACH_PILZ_PMI3 PILZ_PMI3 1126
++edb9302a MACH_EDB9302A EDB9302A 1127
++edb9307a MACH_EDB9307A EDB9307A 1128
++ct_dfs MACH_CT_DFS CT_DFS 1129
++pilz_pmi4 MACH_PILZ_PMI4 PILZ_PMI4 1130
++xceednp_ixp MACH_XCEEDNP_IXP XCEEDNP_IXP 1131
++smdk2442b MACH_SMDK2442B SMDK2442B 1132
++xnode MACH_XNODE XNODE 1133
++aidx270 MACH_AIDX270 AIDX270 1134
++rema MACH_REMA REMA 1135
++bps1000 MACH_BPS1000 BPS1000 1136
++hw90350 MACH_HW90350 HW90350 1137
++omap_3430sdp MACH_OMAP_3430SDP OMAP_3430SDP 1138
++bluetouch MACH_BLUETOUCH BLUETOUCH 1139
++vstms MACH_VSTMS VSTMS 1140
++xsbase270 MACH_XSBASE270 XSBASE270 1141
++at91sam9260ek_cn MACH_AT91SAM9260EK_CN AT91SAM9260EK_CN 1142
++adsturboxb MACH_ADSTURBOXB ADSTURBOXB 1143
++oti4110 MACH_OTI4110 OTI4110 1144
++hme_pxa MACH_HME_PXA HME_PXA 1145
++deisterdca MACH_DEISTERDCA DEISTERDCA 1146
++ces_ssem2 MACH_CES_SSEM2 CES_SSEM2 1147
++ces_mtr MACH_CES_MTR CES_MTR 1148
++tds_avng_sbc MACH_TDS_AVNG_SBC TDS_AVNG_SBC 1149
++everest MACH_EVEREST EVEREST 1150
++pnx4010 MACH_PNX4010 PNX4010 1151
++oxnas MACH_OXNAS OXNAS 1152
++fiori MACH_FIORI FIORI 1153
++ml1200 MACH_ML1200 ML1200 1154
++pecos MACH_PECOS PECOS 1155
++nb2xxx MACH_NB2XXX NB2XXX 1156
++hw6900 MACH_HW6900 HW6900 1157
++cdcs_quoll MACH_CDCS_QUOLL CDCS_QUOLL 1158
++quicksilver MACH_QUICKSILVER QUICKSILVER 1159
++uplat926 MACH_UPLAT926 UPLAT926 1160
++dep2410_dep2410 MACH_DEP2410_THOMAS DEP2410_THOMAS 1161
++dtk2410 MACH_DTK2410 DTK2410 1162
++chili MACH_CHILI CHILI 1163
++demeter MACH_DEMETER DEMETER 1164
++dionysus MACH_DIONYSUS DIONYSUS 1165
++as352x MACH_AS352X AS352X 1166
++service MACH_SERVICE SERVICE 1167
++cs_e9301 MACH_CS_E9301 CS_E9301 1168
++micro9m MACH_MICRO9M MICRO9M 1169
++ia_mospck MACH_IA_MOSPCK IA_MOSPCK 1170
++ql201b MACH_QL201B QL201B 1171
++bbm MACH_BBM BBM 1174
++exxx MACH_EXXX EXXX 1175
++wma11b MACH_WMA11B WMA11B 1176
++pelco_atlas MACH_PELCO_ATLAS PELCO_ATLAS 1177
++g500 MACH_G500 G500 1178
++bug MACH_BUG BUG 1179
++mx33ads MACH_MX33ADS MX33ADS 1180
++chub MACH_CHUB CHUB 1181
++neo1973_gta01 MACH_NEO1973_GTA01 NEO1973_GTA01 1182
++w90n740 MACH_W90N740 W90N740 1183
++medallion_sa2410 MACH_MEDALLION_SA2410 MEDALLION_SA2410 1184
++ia_cpu_9200_2 MACH_IA_CPU_9200_2 IA_CPU_9200_2 1185
++dimmrm9200 MACH_DIMMRM9200 DIMMRM9200 1186
++pm9261 MACH_PM9261 PM9261 1187
++ml7304 MACH_ML7304 ML7304 1189
++ucp250 MACH_UCP250 UCP250 1190
++intboard MACH_INTBOARD INTBOARD 1191
++gulfstream MACH_GULFSTREAM GULFSTREAM 1192
++labquest MACH_LABQUEST LABQUEST 1193
++vcmx313 MACH_VCMX313 VCMX313 1194
++urg200 MACH_URG200 URG200 1195
++cpux255lcdnet MACH_CPUX255LCDNET CPUX255LCDNET 1196
++netdcu9 MACH_NETDCU9 NETDCU9 1197
++netdcu10 MACH_NETDCU10 NETDCU10 1198
++dspg_dga MACH_DSPG_DGA DSPG_DGA 1199
++dspg_dvw MACH_DSPG_DVW DSPG_DVW 1200
++solos MACH_SOLOS SOLOS 1201
++at91sam9263ek MACH_AT91SAM9263EK AT91SAM9263EK 1202
++osstbox MACH_OSSTBOX OSSTBOX 1203
++kbat9261 MACH_KBAT9261 KBAT9261 1204
++ct1100 MACH_CT1100 CT1100 1205
++akcppxa MACH_AKCPPXA AKCPPXA 1206
++ochaya1020 MACH_OCHAYA1020 OCHAYA1020 1207
++hitrack MACH_HITRACK HITRACK 1208
++syme1 MACH_SYME1 SYME1 1209
++syhl1 MACH_SYHL1 SYHL1 1210
++empca400 MACH_EMPCA400 EMPCA400 1211
++em7210 MACH_EM7210 EM7210 1212
++htchermes MACH_HTCHERMES HTCHERMES 1213
++eti_c1 MACH_ETI_C1 ETI_C1 1214
++ac100 MACH_AC100 AC100 1216
++sneetch MACH_SNEETCH SNEETCH 1217
++studentmate MACH_STUDENTMATE STUDENTMATE 1218
++zir2410 MACH_ZIR2410 ZIR2410 1219
++zir2413 MACH_ZIR2413 ZIR2413 1220
++dlonip3 MACH_DLONIP3 DLONIP3 1221
++instream MACH_INSTREAM INSTREAM 1222
++ambarella MACH_AMBARELLA AMBARELLA 1223
++nevis MACH_NEVIS NEVIS 1224
++htc_trinity MACH_HTC_TRINITY HTC_TRINITY 1225
++ql202b MACH_QL202B QL202B 1226
++vpac270 MACH_VPAC270 VPAC270 1227
++rd129 MACH_RD129 RD129 1228
++htcwizard MACH_HTCWIZARD HTCWIZARD 1229
++treo680 MACH_TREO680 TREO680 1230
++tecon_tmezon MACH_TECON_TMEZON TECON_TMEZON 1231
++zylonite MACH_ZYLONITE ZYLONITE 1233
++gene1270 MACH_GENE1270 GENE1270 1234
++zir2412 MACH_ZIR2412 ZIR2412 1235
++mx31lite MACH_MX31LITE MX31LITE 1236
++t700wx MACH_T700WX T700WX 1237
++vf100 MACH_VF100 VF100 1238
++nsb2 MACH_NSB2 NSB2 1239
++nxhmi_bb MACH_NXHMI_BB NXHMI_BB 1240
++nxhmi_re MACH_NXHMI_RE NXHMI_RE 1241
++n4100pro MACH_N4100PRO N4100PRO 1242
++sam9260 MACH_SAM9260 SAM9260 1243
++omap_treo600 MACH_OMAP_TREO600 OMAP_TREO600 1244
++indy2410 MACH_INDY2410 INDY2410 1245
++nelt_a MACH_NELT_A NELT_A 1246
++n311 MACH_N311 N311 1248
++at91sam9260vgk MACH_AT91SAM9260VGK AT91SAM9260VGK 1249
++at91leppe MACH_AT91LEPPE AT91LEPPE 1250
++at91lepccn MACH_AT91LEPCCN AT91LEPCCN 1251
++apc7100 MACH_APC7100 APC7100 1252
++stargazer MACH_STARGAZER STARGAZER 1253
++sonata MACH_SONATA SONATA 1254
++schmoogie MACH_SCHMOOGIE SCHMOOGIE 1255
++aztool MACH_AZTOOL AZTOOL 1256
++mioa701 MACH_MIOA701 MIOA701 1257
++sxni9260 MACH_SXNI9260 SXNI9260 1258
++mxc27520evb MACH_MXC27520EVB MXC27520EVB 1259
++armadillo5x0 MACH_ARMADILLO5X0 ARMADILLO5X0 1260
++mb9260 MACH_MB9260 MB9260 1261
++mb9263 MACH_MB9263 MB9263 1262
++ipac9302 MACH_IPAC9302 IPAC9302 1263
++cc9p9360js MACH_CC9P9360JS CC9P9360JS 1264
++gallium MACH_GALLIUM GALLIUM 1265
++msc2410 MACH_MSC2410 MSC2410 1266
++ghi270 MACH_GHI270 GHI270 1267
++davinci_leonardo MACH_DAVINCI_LEONARDO DAVINCI_LEONARDO 1268
++oiab MACH_OIAB OIAB 1269
++smdk6400 MACH_SMDK6400 SMDK6400 1270
++nokia_n800 MACH_NOKIA_N800 NOKIA_N800 1271
++greenphone MACH_GREENPHONE GREENPHONE 1272
++compex42x MACH_COMPEXWP18 COMPEXWP18 1273
++xmate MACH_XMATE XMATE 1274
++energizer MACH_ENERGIZER ENERGIZER 1275
++ime1 MACH_IME1 IME1 1276
++sweda_tms MACH_SWEDATMS SWEDATMS 1277
++ntnp435c MACH_NTNP435C NTNP435C 1278
++spectro2 MACH_SPECTRO2 SPECTRO2 1279
++h6039 MACH_H6039 H6039 1280
++ep80219 MACH_EP80219 EP80219 1281
++samoa_ii MACH_SAMOA_II SAMOA_II 1282
++cwmxl MACH_CWMXL CWMXL 1283
++as9200 MACH_AS9200 AS9200 1284
++sfx1149 MACH_SFX1149 SFX1149 1285
++navi010 MACH_NAVI010 NAVI010 1286
++multmdp MACH_MULTMDP MULTMDP 1287
++scb9520 MACH_SCB9520 SCB9520 1288
++htcathena MACH_HTCATHENA HTCATHENA 1289
++xp179 MACH_XP179 XP179 1290
++h4300 MACH_H4300 H4300 1291
++goramo_mlr MACH_GORAMO_MLR GORAMO_MLR 1292
++mxc30020evb MACH_MXC30020EVB MXC30020EVB 1293
++adsbitsyg5 MACH_ADSBITSYG5 ADSBITSYG5 1294
++adsportalplus MACH_ADSPORTALPLUS ADSPORTALPLUS 1295
++mmsp2plus MACH_MMSP2PLUS MMSP2PLUS 1296
++em_x270 MACH_EM_X270 EM_X270 1297
++tpp302 MACH_TPP302 TPP302 1298
++tpp104 MACH_TPM104 TPM104 1299
++tpm102 MACH_TPM102 TPM102 1300
++tpm109 MACH_TPM109 TPM109 1301
++fbxo1 MACH_FBXO1 FBXO1 1302
++hxd8 MACH_HXD8 HXD8 1303
++neo1973_gta02 MACH_NEO1973_GTA02 NEO1973_GTA02 1304
++emtest MACH_EMTEST EMTEST 1305
++ad6900 MACH_AD6900 AD6900 1306
++europa MACH_EUROPA EUROPA 1307
++metroconnect MACH_METROCONNECT METROCONNECT 1308
++ez_s2410 MACH_EZ_S2410 EZ_S2410 1309
++ez_s2440 MACH_EZ_S2440 EZ_S2440 1310
++ez_ep9312 MACH_EZ_EP9312 EZ_EP9312 1311
++ez_ep9315 MACH_EZ_EP9315 EZ_EP9315 1312
++ez_x7 MACH_EZ_X7 EZ_X7 1313
++godotdb MACH_GODOTDB GODOTDB 1314
++mistral MACH_MISTRAL MISTRAL 1315
++msm MACH_MSM MSM 1316
++ct5910 MACH_CT5910 CT5910 1317
++ct5912 MACH_CT5912 CT5912 1318
++hynet_ine MACH_HYNET_INE HYNET_INE 1319
++hynet_app MACH_HYNET_APP HYNET_APP 1320
++msm7200 MACH_MSM7200 MSM7200 1321
++msm7600 MACH_MSM7600 MSM7600 1322
++ceb255 MACH_CEB255 CEB255 1323
++ciel MACH_CIEL CIEL 1324
++slm5650 MACH_SLM5650 SLM5650 1325
++at91sam9rlek MACH_AT91SAM9RLEK AT91SAM9RLEK 1326
++comtech_router MACH_COMTECH_ROUTER COMTECH_ROUTER 1327
++sbc2410x MACH_SBC2410X SBC2410X 1328
++at4x0bd MACH_AT4X0BD AT4X0BD 1329
++cbifr MACH_CBIFR CBIFR 1330
++arcom_quantum MACH_ARCOM_QUANTUM ARCOM_QUANTUM 1331
++matrix520 MACH_MATRIX520 MATRIX520 1332
++matrix510 MACH_MATRIX510 MATRIX510 1333
++matrix500 MACH_MATRIX500 MATRIX500 1334
++m501 MACH_M501 M501 1335
++aaeon1270 MACH_AAEON1270 AAEON1270 1336
++matrix500ev MACH_MATRIX500EV MATRIX500EV 1337
++pac500 MACH_PAC500 PAC500 1338
++pnx8181 MACH_PNX8181 PNX8181 1339
++colibri320 MACH_COLIBRI320 COLIBRI320 1340
++aztoolbb MACH_AZTOOLBB AZTOOLBB 1341
++aztoolg2 MACH_AZTOOLG2 AZTOOLG2 1342
++dvlhost MACH_DVLHOST DVLHOST 1343
++zir9200 MACH_ZIR9200 ZIR9200 1344
++zir9260 MACH_ZIR9260 ZIR9260 1345
++cocopah MACH_COCOPAH COCOPAH 1346
++nds MACH_NDS NDS 1347
++rosencrantz MACH_ROSENCRANTZ ROSENCRANTZ 1348
++fttx_odsc MACH_FTTX_ODSC FTTX_ODSC 1349
++classe_r6904 MACH_CLASSE_R6904 CLASSE_R6904 1350
++cam60 MACH_CAM60 CAM60 1351
++mxc30031ads MACH_MXC30031ADS MXC30031ADS 1352
++datacall MACH_DATACALL DATACALL 1353
++at91eb01 MACH_AT91EB01 AT91EB01 1354
++rty MACH_RTY RTY 1355
++dwl2100 MACH_DWL2100 DWL2100 1356
++vinsi MACH_VINSI VINSI 1357
++db88f5281 MACH_DB88F5281 DB88F5281 1358
++csb726 MACH_CSB726 CSB726 1359
++tik27 MACH_TIK27 TIK27 1360
++mx_uc7420 MACH_MX_UC7420 MX_UC7420 1361
++rirm3 MACH_RIRM3 RIRM3 1362
++pelco_odyssey MACH_PELCO_ODYSSEY PELCO_ODYSSEY 1363
++adx_abox MACH_ADX_ABOX ADX_ABOX 1365
++adx_tpid MACH_ADX_TPID ADX_TPID 1366
++minicheck MACH_MINICHECK MINICHECK 1367
++idam MACH_IDAM IDAM 1368
++mario_mx MACH_MARIO_MX MARIO_MX 1369
++vi1888 MACH_VI1888 VI1888 1370
++zr4230 MACH_ZR4230 ZR4230 1371
++t1_ix_blue MACH_T1_IX_BLUE T1_IX_BLUE 1372
++syhq2 MACH_SYHQ2 SYHQ2 1373
++computime_r3 MACH_COMPUTIME_R3 COMPUTIME_R3 1374
++oratis MACH_ORATIS ORATIS 1375
++mikko MACH_MIKKO MIKKO 1376
++holon MACH_HOLON HOLON 1377
++olip8 MACH_OLIP8 OLIP8 1378
++ghi270hg MACH_GHI270HG GHI270HG 1379
++davinci_dm6467_evm MACH_DAVINCI_DM6467_EVM DAVINCI_DM6467_EVM 1380
++davinci_dm355_evm MACH_DAVINCI_DM355_EVM DAVINCI_DM355_EVM 1381
++blackriver MACH_BLACKRIVER BLACKRIVER 1383
++sandgate_wp MACH_SANDGATEWP SANDGATEWP 1384
++cdotbwsg MACH_CDOTBWSG CDOTBWSG 1385
++quark963 MACH_QUARK963 QUARK963 1386
++csb735 MACH_CSB735 CSB735 1387
++littleton MACH_LITTLETON LITTLETON 1388
++mio_p550 MACH_MIO_P550 MIO_P550 1389
++motion2440 MACH_MOTION2440 MOTION2440 1390
++imm500 MACH_IMM500 IMM500 1391
++homematic MACH_HOMEMATIC HOMEMATIC 1392
++ermine MACH_ERMINE ERMINE 1393
++kb9202b MACH_KB9202B KB9202B 1394
++hs1xx MACH_HS1XX HS1XX 1395
++studentmate2440 MACH_STUDENTMATE2440 STUDENTMATE2440 1396
++arvoo_l1_z1 MACH_ARVOO_L1_Z1 ARVOO_L1_Z1 1397
++dep2410k MACH_DEP2410K DEP2410K 1398
++xxsvideo MACH_XXSVIDEO XXSVIDEO 1399
++im4004 MACH_IM4004 IM4004 1400
++ochaya1050 MACH_OCHAYA1050 OCHAYA1050 1401
++lep9261 MACH_LEP9261 LEP9261 1402
++svenmeb MACH_SVENMEB SVENMEB 1403
++fortunet2ne MACH_FORTUNET2NE FORTUNET2NE 1404
++nxhx MACH_NXHX NXHX 1406
++realview_pb11mp MACH_REALVIEW_PB11MP REALVIEW_PB11MP 1407
++ids500 MACH_IDS500 IDS500 1408
++ors_n725 MACH_ORS_N725 ORS_N725 1409
++hsdarm MACH_HSDARM HSDARM 1410
++sha_pon003 MACH_SHA_PON003 SHA_PON003 1411
++sha_pon004 MACH_SHA_PON004 SHA_PON004 1412
++sha_pon007 MACH_SHA_PON007 SHA_PON007 1413
++sha_pon011 MACH_SHA_PON011 SHA_PON011 1414
++h6042 MACH_H6042 H6042 1415
++h6043 MACH_H6043 H6043 1416
++looxc550 MACH_LOOXC550 LOOXC550 1417
++cnty_titan MACH_CNTY_TITAN CNTY_TITAN 1418
++app3xx MACH_APP3XX APP3XX 1419
++sideoatsgrama MACH_SIDEOATSGRAMA SIDEOATSGRAMA 1420
++treo700p MACH_TREO700P TREO700P 1421
++treo700w MACH_TREO700W TREO700W 1422
++treo750 MACH_TREO750 TREO750 1423
++treo755p MACH_TREO755P TREO755P 1424
++ezreganut9200 MACH_EZREGANUT9200 EZREGANUT9200 1425
++sarge MACH_SARGE SARGE 1426
++a696 MACH_A696 A696 1427
++turtle1916 MACH_TURTLE TURTLE 1428
++mx27_3ds MACH_MX27_3DS MX27_3DS 1430
++bishop MACH_BISHOP BISHOP 1431
++pxx MACH_PXX PXX 1432
++redwood MACH_REDWOOD REDWOOD 1433
++omap_2430dlp MACH_OMAP_2430DLP OMAP_2430DLP 1436
++omap_2430osk MACH_OMAP_2430OSK OMAP_2430OSK 1437
++sardine MACH_SARDINE SARDINE 1438
++halibut MACH_HALIBUT HALIBUT 1439
++trout MACH_TROUT TROUT 1440
++goldfish MACH_GOLDFISH GOLDFISH 1441
++gesbc2440 MACH_GESBC2440 GESBC2440 1442
++nomad MACH_NOMAD NOMAD 1443
++rosalind MACH_ROSALIND ROSALIND 1444
++cc9p9215 MACH_CC9P9215 CC9P9215 1445
++cc9p9210 MACH_CC9P9210 CC9P9210 1446
++cc9p9215js MACH_CC9P9215JS CC9P9215JS 1447
++cc9p9210js MACH_CC9P9210JS CC9P9210JS 1448
++nasffe MACH_NASFFE NASFFE 1449
++tn2x0bd MACH_TN2X0BD TN2X0BD 1450
++gwmpxa MACH_GWMPXA GWMPXA 1451
++exyplus MACH_EXYPLUS EXYPLUS 1452
++jadoo21 MACH_JADOO21 JADOO21 1453
++looxn560 MACH_LOOXN560 LOOXN560 1454
++bonsai MACH_BONSAI BONSAI 1455
++adsmilgato MACH_ADSMILGATO ADSMILGATO 1456
++gba MACH_GBA GBA 1457
++h6044 MACH_H6044 H6044 1458
++app MACH_APP APP 1459
++tct_hammer MACH_TCT_HAMMER TCT_HAMMER 1460
++herald MACH_HERALD HERALD 1461
++artemis MACH_ARTEMIS ARTEMIS 1462
++htctitan MACH_HTCTITAN HTCTITAN 1463
++qranium MACH_QRANIUM QRANIUM 1464
++adx_wsc2 MACH_ADX_WSC2 ADX_WSC2 1465
++adx_medcom MACH_ADX_MEDCOM ADX_MEDCOM 1466
++bboard MACH_BBOARD BBOARD 1467
++cambria MACH_CAMBRIA CAMBRIA 1468
++mt7xxx MACH_MT7XXX MT7XXX 1469
++matrix512 MACH_MATRIX512 MATRIX512 1470
++matrix522 MACH_MATRIX522 MATRIX522 1471
++ipac5010 MACH_IPAC5010 IPAC5010 1472
++sakura MACH_SAKURA SAKURA 1473
++grocx MACH_GROCX GROCX 1474
++pm9263 MACH_PM9263 PM9263 1475
++sim_one MACH_SIM_ONE SIM_ONE 1476
++acq132 MACH_ACQ132 ACQ132 1477
++datr MACH_DATR DATR 1478
++actux1 MACH_ACTUX1 ACTUX1 1479
++actux2 MACH_ACTUX2 ACTUX2 1480
++actux3 MACH_ACTUX3 ACTUX3 1481
++flexit MACH_FLEXIT FLEXIT 1482
++bh2x0bd MACH_BH2X0BD BH2X0BD 1483
++atb2002 MACH_ATB2002 ATB2002 1484
++xenon MACH_XENON XENON 1485
++fm607 MACH_FM607 FM607 1486
++matrix514 MACH_MATRIX514 MATRIX514 1487
++matrix524 MACH_MATRIX524 MATRIX524 1488
++inpod MACH_INPOD INPOD 1489
++jive MACH_JIVE JIVE 1490
++tll_mx21 MACH_TLL_MX21 TLL_MX21 1491
++sbc2800 MACH_SBC2800 SBC2800 1492
++cc7ucamry MACH_CC7UCAMRY CC7UCAMRY 1493
++ubisys_p9_sc15 MACH_UBISYS_P9_SC15 UBISYS_P9_SC15 1494
++ubisys_p9_ssc2d10 MACH_UBISYS_P9_SSC2D10 UBISYS_P9_SSC2D10 1495
++ubisys_p9_rcu3 MACH_UBISYS_P9_RCU3 UBISYS_P9_RCU3 1496
++aml_m8000 MACH_AML_M8000 AML_M8000 1497
++snapper_270 MACH_SNAPPER_270 SNAPPER_270 1498
++omap_bbx MACH_OMAP_BBX OMAP_BBX 1499
++ucn2410 MACH_UCN2410 UCN2410 1500
++sam9_l9260 MACH_SAM9_L9260 SAM9_L9260 1501
++eti_c2 MACH_ETI_C2 ETI_C2 1502
++avalanche MACH_AVALANCHE AVALANCHE 1503
++realview_pb1176 MACH_REALVIEW_PB1176 REALVIEW_PB1176 1504
++dp1500 MACH_DP1500 DP1500 1505
++apple_iphone MACH_APPLE_IPHONE APPLE_IPHONE 1506
++yl9200 MACH_YL9200 YL9200 1507
++rd88f5182 MACH_RD88F5182 RD88F5182 1508
++kurobox_pro MACH_KUROBOX_PRO KUROBOX_PRO 1509
++se_poet MACH_SE_POET SE_POET 1510
++mx31_3ds MACH_MX31_3DS MX31_3DS 1511
++r270 MACH_R270 R270 1512
++armour21 MACH_ARMOUR21 ARMOUR21 1513
++dt2 MACH_DT2 DT2 1514
++vt4 MACH_VT4 VT4 1515
++tyco320 MACH_TYCO320 TYCO320 1516
++adma MACH_ADMA ADMA 1517
++wp188 MACH_WP188 WP188 1518
++corsica MACH_CORSICA CORSICA 1519
++bigeye MACH_BIGEYE BIGEYE 1520
++tll5000 MACH_TLL5000 TLL5000 1522
++bebot MACH_BEBOT BEBOT 1523
++qong MACH_QONG QONG 1524
++tcompact MACH_TCOMPACT TCOMPACT 1525
++puma5 MACH_PUMA5 PUMA5 1526
++elara MACH_ELARA ELARA 1527
++ellington MACH_ELLINGTON ELLINGTON 1528
++xda_atom MACH_XDA_ATOM XDA_ATOM 1529
++energizer2 MACH_ENERGIZER2 ENERGIZER2 1530
++odin MACH_ODIN ODIN 1531
++actux4 MACH_ACTUX4 ACTUX4 1532
++esl_omap MACH_ESL_OMAP ESL_OMAP 1533
++omap2evm MACH_OMAP2EVM OMAP2EVM 1534
++omap3evm MACH_OMAP3EVM OMAP3EVM 1535
++adx_pcu57 MACH_ADX_PCU57 ADX_PCU57 1536
++monaco MACH_MONACO MONACO 1537
++levante MACH_LEVANTE LEVANTE 1538
++tmxipx425 MACH_TMXIPX425 TMXIPX425 1539
++leep MACH_LEEP LEEP 1540
++raad MACH_RAAD RAAD 1541
++dns323 MACH_DNS323 DNS323 1542
++ap1000 MACH_AP1000 AP1000 1543
++a9sam6432 MACH_A9SAM6432 A9SAM6432 1544
++shiny MACH_SHINY SHINY 1545
++omap3_beagle MACH_OMAP3_BEAGLE OMAP3_BEAGLE 1546
++csr_bdb2 MACH_CSR_BDB2 CSR_BDB2 1547
++nokia_n810 MACH_NOKIA_N810 NOKIA_N810 1548
++c270 MACH_C270 C270 1549
++sentry MACH_SENTRY SENTRY 1550
++pcm038 MACH_PCM038 PCM038 1551
++anc300 MACH_ANC300 ANC300 1552
++htckaiser MACH_HTCKAISER HTCKAISER 1553
++sbat100 MACH_SBAT100 SBAT100 1554
++modunorm MACH_MODUNORM MODUNORM 1555
++pelos_twarm MACH_PELOS_TWARM PELOS_TWARM 1556
++flank MACH_FLANK FLANK 1557
++sirloin MACH_SIRLOIN SIRLOIN 1558
++brisket MACH_BRISKET BRISKET 1559
++chuck MACH_CHUCK CHUCK 1560
++otter MACH_OTTER OTTER 1561
++davinci_ldk MACH_DAVINCI_LDK DAVINCI_LDK 1562
++phreedom MACH_PHREEDOM PHREEDOM 1563
++sg310 MACH_SG310 SG310 1564
++ts_x09 MACH_TS209 TS209 1565
++at91cap9adk MACH_AT91CAP9ADK AT91CAP9ADK 1566
++tion9315 MACH_TION9315 TION9315 1567
++mast MACH_MAST MAST 1568
++pfw MACH_PFW PFW 1569
++yl_p2440 MACH_YL_P2440 YL_P2440 1570
++zsbc32 MACH_ZSBC32 ZSBC32 1571
++omap_pace2 MACH_OMAP_PACE2 OMAP_PACE2 1572
++imx_pace2 MACH_IMX_PACE2 IMX_PACE2 1573
++mx31moboard MACH_MX31MOBOARD MX31MOBOARD 1574
++mx37_3ds MACH_MX37_3DS MX37_3DS 1575
++rcc MACH_RCC RCC 1576
++dmp MACH_ARM9 ARM9 1577
++vision_ep9307 MACH_VISION_EP9307 VISION_EP9307 1578
++scly1000 MACH_SCLY1000 SCLY1000 1579
++fontel_ep MACH_FONTEL_EP FONTEL_EP 1580
++voiceblue3g MACH_VOICEBLUE3G VOICEBLUE3G 1581
++tt9200 MACH_TT9200 TT9200 1582
++digi2410 MACH_DIGI2410 DIGI2410 1583
++terastation_pro2 MACH_TERASTATION_PRO2 TERASTATION_PRO2 1584
++linkstation_pro MACH_LINKSTATION_PRO LINKSTATION_PRO 1585
++motorola_a780 MACH_MOTOROLA_A780 MOTOROLA_A780 1587
++motorola_e6 MACH_MOTOROLA_E6 MOTOROLA_E6 1588
++motorola_e2 MACH_MOTOROLA_E2 MOTOROLA_E2 1589
++motorola_e680 MACH_MOTOROLA_E680 MOTOROLA_E680 1590
++ur2410 MACH_UR2410 UR2410 1591
++tas9261 MACH_TAS9261 TAS9261 1592
++davinci_hermes_hd MACH_HERMES_HD HERMES_HD 1593
++davinci_perseo_hd MACH_PERSEO_HD PERSEO_HD 1594
++stargazer2 MACH_STARGAZER2 STARGAZER2 1595
++e350 MACH_E350 E350 1596
++wpcm450 MACH_WPCM450 WPCM450 1597
++cartesio MACH_CARTESIO CARTESIO 1598
++toybox MACH_TOYBOX TOYBOX 1599
++tx27 MACH_TX27 TX27 1600
++ts409 MACH_TS409 TS409 1601
++p300 MACH_P300 P300 1602
++xdacomet MACH_XDACOMET XDACOMET 1603
++dexflex2 MACH_DEXFLEX2 DEXFLEX2 1604
++ow MACH_OW OW 1605
++armebs3 MACH_ARMEBS3 ARMEBS3 1606
++u3 MACH_U3 U3 1607
++smdk2450 MACH_SMDK2450 SMDK2450 1608
++rsi_ews MACH_RSI_EWS RSI_EWS 1609
++tnb MACH_TNB TNB 1610
++toepath MACH_TOEPATH TOEPATH 1611
++kb9263 MACH_KB9263 KB9263 1612
++mt7108 MACH_MT7108 MT7108 1613
++smtr2440 MACH_SMTR2440 SMTR2440 1614
++manao MACH_MANAO MANAO 1615
++cm_x300 MACH_CM_X300 CM_X300 1616
++gulfstream_kp MACH_GULFSTREAM_KP GULFSTREAM_KP 1617
++lanreadyfn522 MACH_LANREADYFN522 LANREADYFN522 1618
++arma37 MACH_ARMA37 ARMA37 1619
++mendel MACH_MENDEL MENDEL 1620
++pelco_iliad MACH_PELCO_ILIAD PELCO_ILIAD 1621
++unit2p MACH_UNIT2P UNIT2P 1622
++inc20otter MACH_INC20OTTER INC20OTTER 1623
++at91sam9g20ek MACH_AT91SAM9G20EK AT91SAM9G20EK 1624
++sc_ge2 MACH_STORCENTER STORCENTER 1625
++smdk6410 MACH_SMDK6410 SMDK6410 1626
++u300 MACH_U300 U300 1627
++u500 MACH_U500 U500 1628
++ds9260 MACH_DS9260 DS9260 1629
++riverrock MACH_RIVERROCK RIVERROCK 1630
++scibath MACH_SCIBATH SCIBATH 1631
++at91sam7se MACH_AT91SAM7SE512EK AT91SAM7SE512EK 1632
++wrt350n_v2 MACH_WRT350N_V2 WRT350N_V2 1633
++multimedia MACH_MULTIMEDIA MULTIMEDIA 1634
++marvin MACH_MARVIN MARVIN 1635
++x500 MACH_X500 X500 1636
++awlug4lcu MACH_AWLUG4LCU AWLUG4LCU 1637
++palermoc MACH_PALERMOC PALERMOC 1638
++omap_ldp MACH_OMAP_LDP OMAP_LDP 1639
++ip500 MACH_IP500 IP500 1640
++ase2 MACH_ASE2 ASE2 1642
++mx35evb MACH_MX35EVB MX35EVB 1643
++aml_m8050 MACH_AML_M8050 AML_M8050 1644
++mx35_3ds MACH_MX35_3DS MX35_3DS 1645
++mars MACH_MARS MARS 1646
++neuros_osd2 MACH_NEUROS_OSD2 NEUROS_OSD2 1647
++badger MACH_BADGER BADGER 1648
++trizeps4wl MACH_TRIZEPS4WL TRIZEPS4WL 1649
++trizeps5 MACH_TRIZEPS5 TRIZEPS5 1650
++marlin MACH_MARLIN MARLIN 1651
++ts78xx MACH_TS78XX TS78XX 1652
++hpipaq214 MACH_HPIPAQ214 HPIPAQ214 1653
++at572d940dcm MACH_AT572D940DCM AT572D940DCM 1654
++ne1board MACH_NE1BOARD NE1BOARD 1655
++zante MACH_ZANTE ZANTE 1656
++sffsdr MACH_SFFSDR SFFSDR 1657
++tw2662 MACH_TW2662 TW2662 1658
++vf10xx MACH_VF10XX VF10XX 1659
++zoran43xx MACH_ZORAN43XX ZORAN43XX 1660
++sonix926 MACH_SONIX926 SONIX926 1661
++celestialsemi MACH_CELESTIALSEMI CELESTIALSEMI 1662
++cc9m2443js MACH_CC9M2443JS CC9M2443JS 1663
++tw5334 MACH_TW5334 TW5334 1664
++omap_htcartemis MACH_HTCARTEMIS HTCARTEMIS 1665
++nal_hlite MACH_NAL_HLITE NAL_HLITE 1666
++htcvogue MACH_HTCVOGUE HTCVOGUE 1667
++smartweb MACH_SMARTWEB SMARTWEB 1668
++mv86xx MACH_MV86XX MV86XX 1669
++mv87xx MACH_MV87XX MV87XX 1670
++songyoungho MACH_SONGYOUNGHO SONGYOUNGHO 1671
++younghotema MACH_YOUNGHOTEMA YOUNGHOTEMA 1672
++pcm037 MACH_PCM037 PCM037 1673
++mmvp MACH_MMVP MMVP 1674
++mmap MACH_MMAP MMAP 1675
++ptid2410 MACH_PTID2410 PTID2410 1676
++james_926 MACH_JAMES_926 JAMES_926 1677
++fm6000 MACH_FM6000 FM6000 1678
++db88f6281_bp MACH_DB88F6281_BP DB88F6281_BP 1680
++rd88f6192_nas MACH_RD88F6192_NAS RD88F6192_NAS 1681
++rd88f6281 MACH_RD88F6281 RD88F6281 1682
++db78x00_bp MACH_DB78X00_BP DB78X00_BP 1683
++smdk2416 MACH_SMDK2416 SMDK2416 1685
++oce_spider_si MACH_OCE_SPIDER_SI OCE_SPIDER_SI 1686
++oce_spider_sk MACH_OCE_SPIDER_SK OCE_SPIDER_SK 1687
++rovern6 MACH_ROVERN6 ROVERN6 1688
++pelco_evolution MACH_PELCO_EVOLUTION PELCO_EVOLUTION 1689
++wbd111 MACH_WBD111 WBD111 1690
++elaracpe MACH_ELARACPE ELARACPE 1691
++mabv3 MACH_MABV3 MABV3 1692
++mv2120 MACH_MV2120 MV2120 1693
++csb737 MACH_CSB737 CSB737 1695
++mx51_3ds MACH_MX51_3DS MX51_3DS 1696
++g900 MACH_G900 G900 1697
++apf27 MACH_APF27 APF27 1698
++ggus2000 MACH_GGUS2000 GGUS2000 1699
++omap_2430_mimic MACH_OMAP_2430_MIMIC OMAP_2430_MIMIC 1700
++imx27lite MACH_IMX27LITE IMX27LITE 1701
++almex MACH_ALMEX ALMEX 1702
++control MACH_CONTROL CONTROL 1703
++mba2410 MACH_MBA2410 MBA2410 1704
++volcano MACH_VOLCANO VOLCANO 1705
++zenith MACH_ZENITH ZENITH 1706
++muchip MACH_MUCHIP MUCHIP 1707
++magellan MACH_MAGELLAN MAGELLAN 1708
++usb_a9260 MACH_USB_A9260 USB_A9260 1709
++usb_a9263 MACH_USB_A9263 USB_A9263 1710
++qil_a9260 MACH_QIL_A9260 QIL_A9260 1711
++cme9210 MACH_CME9210 CME9210 1712
++hczh4 MACH_HCZH4 HCZH4 1713
++spearbasic MACH_SPEARBASIC SPEARBASIC 1714
++dep2440 MACH_DEP2440 DEP2440 1715
++hdl_gxr MACH_HDL_GXR HDL_GXR 1716
++hdl_gt MACH_HDL_GT HDL_GT 1717
++hdl_4g MACH_HDL_4G HDL_4G 1718
++s3c6000 MACH_S3C6000 S3C6000 1719
++mmsp2_mdk MACH_MMSP2_MDK MMSP2_MDK 1720
++mpx220 MACH_MPX220 MPX220 1721
++kzm_arm11_01 MACH_KZM_ARM11_01 KZM_ARM11_01 1722
++htc_polaris MACH_HTC_POLARIS HTC_POLARIS 1723
++htc_kaiser MACH_HTC_KAISER HTC_KAISER 1724
++lg_ks20 MACH_LG_KS20 LG_KS20 1725
++hhgps MACH_HHGPS HHGPS 1726
++nokia_n810_wimax MACH_NOKIA_N810_WIMAX NOKIA_N810_WIMAX 1727
++insight MACH_INSIGHT INSIGHT 1728
++sapphire MACH_SAPPHIRE SAPPHIRE 1729
++csb637xo MACH_CSB637XO CSB637XO 1730
++evisiong MACH_EVISIONG EVISIONG 1731
++stmp37xx MACH_STMP37XX STMP37XX 1732
++stmp378x MACH_STMP378X STMP378X 1733
++tnt MACH_TNT TNT 1734
++tbxt MACH_TBXT TBXT 1735
++playmate MACH_PLAYMATE PLAYMATE 1736
++pns10 MACH_PNS10 PNS10 1737
++eznavi MACH_EZNAVI EZNAVI 1738
++ps4000 MACH_PS4000 PS4000 1739
++ezx_a780 MACH_EZX_A780 EZX_A780 1740
++ezx_e680 MACH_EZX_E680 EZX_E680 1741
++ezx_a1200 MACH_EZX_A1200 EZX_A1200 1742
++ezx_e6 MACH_EZX_E6 EZX_E6 1743
++ezx_e2 MACH_EZX_E2 EZX_E2 1744
++ezx_a910 MACH_EZX_A910 EZX_A910 1745
++cwmx31 MACH_CWMX31 CWMX31 1746
++sl2312 MACH_SL2312 SL2312 1747
++blenny MACH_BLENNY BLENNY 1748
++ds107 MACH_DS107 DS107 1749
++dsx07 MACH_DSX07 DSX07 1750
++picocom1 MACH_PICOCOM1 PICOCOM1 1751
++lynx_wolverine MACH_LYNX_WOLVERINE LYNX_WOLVERINE 1752
++ubisys_p9_sc19 MACH_UBISYS_P9_SC19 UBISYS_P9_SC19 1753
++kratos_low MACH_KRATOS_LOW KRATOS_LOW 1754
++m700 MACH_M700 M700 1755
++edmini_v2 MACH_EDMINI_V2 EDMINI_V2 1756
++zipit2 MACH_ZIPIT2 ZIPIT2 1757
++hslfemtocell MACH_HSLFEMTOCELL HSLFEMTOCELL 1758
++daintree_at91 MACH_DAINTREE_AT91 DAINTREE_AT91 1759
++sg560usb MACH_SG560USB SG560USB 1760
++omap3_pandora MACH_OMAP3_PANDORA OMAP3_PANDORA 1761
++usr8200 MACH_USR8200 USR8200 1762
++s1s65k MACH_S1S65K S1S65K 1763
++s2s65a MACH_S2S65A S2S65A 1764
++icore MACH_ICORE ICORE 1765
++mss2 MACH_MSS2 MSS2 1766
++belmont MACH_BELMONT BELMONT 1767
++asusp525 MACH_ASUSP525 ASUSP525 1768
++lb88rc8480 MACH_LB88RC8480 LB88RC8480 1769
++hipxa MACH_HIPXA HIPXA 1770
++mx25_3ds MACH_MX25_3DS MX25_3DS 1771
++m800 MACH_M800 M800 1772
++omap3530_lv_som MACH_OMAP3530_LV_SOM OMAP3530_LV_SOM 1773
++prima_evb MACH_PRIMA_EVB PRIMA_EVB 1774
++mx31bt1 MACH_MX31BT1 MX31BT1 1775
++atlas4_evb MACH_ATLAS4_EVB ATLAS4_EVB 1776
++mx31cicada MACH_MX31CICADA MX31CICADA 1777
++mi424wr MACH_MI424WR MI424WR 1778
++axs_ultrax MACH_AXS_ULTRAX AXS_ULTRAX 1779
++at572d940deb MACH_AT572D940DEB AT572D940DEB 1780
++davinci_da830_evm MACH_DAVINCI_DA830_EVM DAVINCI_DA830_EVM 1781
++ep9302 MACH_EP9302 EP9302 1782
++at572d940hfek MACH_AT572D940HFEB AT572D940HFEB 1783
++cybook3 MACH_CYBOOK3 CYBOOK3 1784
++wdg002 MACH_WDG002 WDG002 1785
++sg560adsl MACH_SG560ADSL SG560ADSL 1786
++nextio_n2800_ica MACH_NEXTIO_N2800_ICA NEXTIO_N2800_ICA 1787
++dove_db MACH_DOVE_DB DOVE_DB 1788
++marvell_newdb MACH_MARVELL_NEWDB MARVELL_NEWDB 1789
++vandihud MACH_VANDIHUD VANDIHUD 1790
++magx_e8 MACH_MAGX_E8 MAGX_E8 1791
++magx_z6 MACH_MAGX_Z6 MAGX_Z6 1792
++magx_v8 MACH_MAGX_V8 MAGX_V8 1793
++magx_u9 MACH_MAGX_U9 MAGX_U9 1794
++toughcf08 MACH_TOUGHCF08 TOUGHCF08 1795
++zw4400 MACH_ZW4400 ZW4400 1796
++marat91 MACH_MARAT91 MARAT91 1797
++overo MACH_OVERO OVERO 1798
++at2440evb MACH_AT2440EVB AT2440EVB 1799
++neocore926 MACH_NEOCORE926 NEOCORE926 1800
++wnr854t MACH_WNR854T WNR854T 1801
++imx27 MACH_IMX27 IMX27 1802
++moose_db MACH_MOOSE_DB MOOSE_DB 1803
++fab4 MACH_FAB4 FAB4 1804
++htcdiamond MACH_HTCDIAMOND HTCDIAMOND 1805
++fiona MACH_FIONA FIONA 1806
++mxc30030_x MACH_MXC30030_X MXC30030_X 1807
++bmp1000 MACH_BMP1000 BMP1000 1808
++logi9200 MACH_LOGI9200 LOGI9200 1809
++tqma31 MACH_TQMA31 TQMA31 1810
++ccw9p9215js MACH_CCW9P9215JS CCW9P9215JS 1811
++rd88f5181l_ge MACH_RD88F5181L_GE RD88F5181L_GE 1812
++sifmain MACH_SIFMAIN SIFMAIN 1813
++sam9_l9261 MACH_SAM9_L9261 SAM9_L9261 1814
++cc9m2443 MACH_CC9M2443 CC9M2443 1815
++xaria300 MACH_XARIA300 XARIA300 1816
++it9200 MACH_IT9200 IT9200 1817
++rd88f5181l_fxo MACH_RD88F5181L_FXO RD88F5181L_FXO 1818
++kriss_sensor MACH_KRISS_SENSOR KRISS_SENSOR 1819
++pilz_pmi5 MACH_PILZ_PMI5 PILZ_PMI5 1820
++jade MACH_JADE JADE 1821
++ks8695_softplc MACH_KS8695_SOFTPLC KS8695_SOFTPLC 1822
++gprisc3 MACH_GPRISC3 GPRISC3 1823
++stamp9g20 MACH_STAMP9G20 STAMP9G20 1824
++smdk6430 MACH_SMDK6430 SMDK6430 1825
++smdkc100 MACH_SMDKC100 SMDKC100 1826
++tavorevb MACH_TAVOREVB TAVOREVB 1827
++saar MACH_SAAR SAAR 1828
++deister_eyecam MACH_DEISTER_EYECAM DEISTER_EYECAM 1829
++at91sam9m10g45ek MACH_AT91SAM9M10G45EK AT91SAM9M10G45EK 1830
++linkstation_produo MACH_LINKSTATION_PRODUO LINKSTATION_PRODUO 1831
++hit_b0 MACH_HIT_B0 HIT_B0 1832
++adx_rmu MACH_ADX_RMU ADX_RMU 1833
++xg_cpe_main MACH_XG_CPE_MAIN XG_CPE_MAIN 1834
++edb9407a MACH_EDB9407A EDB9407A 1835
++dtb9608 MACH_DTB9608 DTB9608 1836
++em104v1 MACH_EM104V1 EM104V1 1837
++demo MACH_DEMO DEMO 1838
++logi9260 MACH_LOGI9260 LOGI9260 1839
++mx31_exm32 MACH_MX31_EXM32 MX31_EXM32 1840
++usb_a9g20 MACH_USB_A9G20 USB_A9G20 1841
++picproje2008 MACH_PICPROJE2008 PICPROJE2008 1842
++cs_e9315 MACH_CS_E9315 CS_E9315 1843
++qil_a9g20 MACH_QIL_A9G20 QIL_A9G20 1844
++sha_pon020 MACH_SHA_PON020 SHA_PON020 1845
++nad MACH_NAD NAD 1846
++sbc35_a9260 MACH_SBC35_A9260 SBC35_A9260 1847
++sbc35_a9g20 MACH_SBC35_A9G20 SBC35_A9G20 1848
++davinci_beginning MACH_DAVINCI_BEGINNING DAVINCI_BEGINNING 1849
++uwc MACH_UWC UWC 1850
++mxlads MACH_MXLADS MXLADS 1851
++htcnike MACH_HTCNIKE HTCNIKE 1852
++deister_pxa270 MACH_DEISTER_PXA270 DEISTER_PXA270 1853
++cme9210js MACH_CME9210JS CME9210JS 1854
++cc9p9360 MACH_CC9P9360 CC9P9360 1855
++mocha MACH_MOCHA MOCHA 1856
++wapd170ag MACH_WAPD170AG WAPD170AG 1857
++linkstation_mini MACH_LINKSTATION_MINI LINKSTATION_MINI 1858
++afeb9260 MACH_AFEB9260 AFEB9260 1859
++w90x900 MACH_W90X900 W90X900 1860
++w90x700 MACH_W90X700 W90X700 1861
++kt300ip MACH_KT300IP KT300IP 1862
++kt300ip_g20 MACH_KT300IP_G20 KT300IP_G20 1863
++srcm MACH_SRCM SRCM 1864
++wlnx_9260 MACH_WLNX_9260 WLNX_9260 1865
++openmoko_gta03 MACH_OPENMOKO_GTA03 OPENMOKO_GTA03 1866
++osprey2 MACH_OSPREY2 OSPREY2 1867
++kbio9260 MACH_KBIO9260 KBIO9260 1868
++ginza MACH_GINZA GINZA 1869
++a636n MACH_A636N A636N 1870
++imx27ipcam MACH_IMX27IPCAM IMX27IPCAM 1871
++nemoc MACH_NEMOC NEMOC 1872
++geneva MACH_GENEVA GENEVA 1873
++htcpharos MACH_HTCPHAROS HTCPHAROS 1874
++neonc MACH_NEONC NEONC 1875
++nas7100 MACH_NAS7100 NAS7100 1876
++teuphone MACH_TEUPHONE TEUPHONE 1877
++annax_eth2 MACH_ANNAX_ETH2 ANNAX_ETH2 1878
++csb733 MACH_CSB733 CSB733 1879
++bk3 MACH_BK3 BK3 1880
++omap_em32 MACH_OMAP_EM32 OMAP_EM32 1881
++et9261cp MACH_ET9261CP ET9261CP 1882
++jasperc MACH_JASPERC JASPERC 1883
++issi_arm9 MACH_ISSI_ARM9 ISSI_ARM9 1884
++ued MACH_UED UED 1885
++esiblade MACH_ESIBLADE ESIBLADE 1886
++eye02 MACH_EYE02 EYE02 1887
++imx27kbd MACH_IMX27KBD IMX27KBD 1888
++sst61vc010_fpga MACH_SST61VC010_FPGA SST61VC010_FPGA 1889
++kixvp435 MACH_KIXVP435 KIXVP435 1890
++kixnp435 MACH_KIXNP435 KIXNP435 1891
++africa MACH_AFRICA AFRICA 1892
++nh233 MACH_NH233 NH233 1893
++rd88f6183ap_ge MACH_RD88F6183AP_GE RD88F6183AP_GE 1894
++bcm4760 MACH_BCM4760 BCM4760 1895
++eddy_v2 MACH_EDDY_V2 EDDY_V2 1896
++realview_pba8 MACH_REALVIEW_PBA8 REALVIEW_PBA8 1897
++hid_a7 MACH_HID_A7 HID_A7 1898
++hero MACH_HERO HERO 1899
++omap_poseidon MACH_OMAP_POSEIDON OMAP_POSEIDON 1900
++realview_pbx MACH_REALVIEW_PBX REALVIEW_PBX 1901
++micro9s MACH_MICRO9S MICRO9S 1902
++mako MACH_MAKO MAKO 1903
++xdaflame MACH_XDAFLAME XDAFLAME 1904
++phidget_sbc2 MACH_PHIDGET_SBC2 PHIDGET_SBC2 1905
++limestone MACH_LIMESTONE LIMESTONE 1906
++iprobe_c32 MACH_IPROBE_C32 IPROBE_C32 1907
++rut100 MACH_RUT100 RUT100 1908
++asusp535 MACH_ASUSP535 ASUSP535 1909
++htcraphael MACH_HTCRAPHAEL HTCRAPHAEL 1910
++sygdg1 MACH_SYGDG1 SYGDG1 1911
++sygdg2 MACH_SYGDG2 SYGDG2 1912
++seoul MACH_SEOUL SEOUL 1913
++salerno MACH_SALERNO SALERNO 1914
++ucn_s3c64xx MACH_UCN_S3C64XX UCN_S3C64XX 1915
++msm7201a MACH_MSM7201A MSM7201A 1916
++lpr1 MACH_LPR1 LPR1 1917
++armadillo500fx MACH_ARMADILLO500FX ARMADILLO500FX 1918
++g3evm MACH_G3EVM G3EVM 1919
++z3_dm355 MACH_Z3_DM355 Z3_DM355 1920
++w90p910evb MACH_W90P910EVB W90P910EVB 1921
++w90p920evb MACH_W90P920EVB W90P920EVB 1922
++w90p950evb MACH_W90P950EVB W90P950EVB 1923
++w90n960evb MACH_W90N960EVB W90N960EVB 1924
++camhd MACH_CAMHD CAMHD 1925
++mvc100 MACH_MVC100 MVC100 1926
++electrum_200 MACH_ELECTRUM_200 ELECTRUM_200 1927
++htcjade MACH_HTCJADE HTCJADE 1928
++memphis MACH_MEMPHIS MEMPHIS 1929
++imx27sbc MACH_IMX27SBC IMX27SBC 1930
++lextar MACH_LEXTAR LEXTAR 1931
++mv88f6281gtw_ge MACH_MV88F6281GTW_GE MV88F6281GTW_GE 1932
++ncp MACH_NCP NCP 1933
++z32an_series MACH_Z32AN Z32AN 1934
++tmq_capd MACH_TMQ_CAPD TMQ_CAPD 1935
++omap3_wl MACH_OMAP3_WL OMAP3_WL 1936
++chumby MACH_CHUMBY CHUMBY 1937
++atsarm9 MACH_ATSARM9 ATSARM9 1938
++davinci_dm365_evm MACH_DAVINCI_DM365_EVM DAVINCI_DM365_EVM 1939
++bahamas MACH_BAHAMAS BAHAMAS 1940
++das MACH_DAS DAS 1941
++minidas MACH_MINIDAS MINIDAS 1942
++vk1000 MACH_VK1000 VK1000 1943
++centro MACH_CENTRO CENTRO 1944
++ctera_2bay MACH_CTERA_2BAY CTERA_2BAY 1945
++edgeconnect MACH_EDGECONNECT EDGECONNECT 1946
++nd27000 MACH_ND27000 ND27000 1947
++cobra MACH_GEMALTO_COBRA GEMALTO_COBRA 1948
++ingelabs_comet MACH_INGELABS_COMET INGELABS_COMET 1949
++pollux_wiz MACH_POLLUX_WIZ POLLUX_WIZ 1950
++blackstone MACH_BLACKSTONE BLACKSTONE 1951
++topaz MACH_TOPAZ TOPAZ 1952
++aixle MACH_AIXLE AIXLE 1953
++mw998 MACH_MW998 MW998 1954
++nokia_rx51 MACH_NOKIA_RX51 NOKIA_RX51 1955
++vsc5605ev MACH_VSC5605EV VSC5605EV 1956
++nt98700dk MACH_NT98700DK NT98700DK 1957
++icontact MACH_ICONTACT ICONTACT 1958
++swarco_frcpu MACH_SWARCO_FRCPU SWARCO_FRCPU 1959
++swarco_scpu MACH_SWARCO_SCPU SWARCO_SCPU 1960
++bbox_p16 MACH_BBOX_P16 BBOX_P16 1961
++bstd MACH_BSTD BSTD 1962
++sbc2440ii MACH_SBC2440II SBC2440II 1963
++pcm034 MACH_PCM034 PCM034 1964
++neso MACH_NESO NESO 1965
++wlnx_9g20 MACH_WLNX_9G20 WLNX_9G20 1966
++omap_zoom2 MACH_OMAP_ZOOM2 OMAP_ZOOM2 1967
++totemnova MACH_TOTEMNOVA TOTEMNOVA 1968
++c5000 MACH_C5000 C5000 1969
++unipo_at91sam9263 MACH_UNIPO_AT91SAM9263 UNIPO_AT91SAM9263 1970
++ethernut5 MACH_ETHERNUT5 ETHERNUT5 1971
++arm11 MACH_ARM11 ARM11 1972
++cpuat9260 MACH_CPUAT9260 CPUAT9260 1973
++cpupxa255 MACH_CPUPXA255 CPUPXA255 1974
++eukrea_cpuimx27 MACH_CPUIMX27 CPUIMX27 1975
++cheflux MACH_CHEFLUX CHEFLUX 1976
++eb_cpux9k2 MACH_EB_CPUX9K2 EB_CPUX9K2 1977
++opcotec MACH_OPCOTEC OPCOTEC 1978
++yt MACH_YT YT 1979
++motoq MACH_MOTOQ MOTOQ 1980
++bsb1 MACH_BSB1 BSB1 1981
++acs5k MACH_ACS5K ACS5K 1982
++milan MACH_MILAN MILAN 1983
++quartzv2 MACH_QUARTZV2 QUARTZV2 1984
++rsvp MACH_RSVP RSVP 1985
++rmp200 MACH_RMP200 RMP200 1986
++snapper_9260 MACH_SNAPPER_9260 SNAPPER_9260 1987
++dsm320 MACH_DSM320 DSM320 1988
++adsgcm MACH_ADSGCM ADSGCM 1989
++ase2_400 MACH_ASE2_400 ASE2_400 1990
++pizza MACH_PIZZA PIZZA 1991
++spot_ngpl MACH_SPOT_NGPL SPOT_NGPL 1992
++armata MACH_ARMATA ARMATA 1993
++exeda MACH_EXEDA EXEDA 1994
++mx31sf005 MACH_MX31SF005 MX31SF005 1995
++f5d8231_4_v2 MACH_F5D8231_4_V2 F5D8231_4_V2 1996
++q2440 MACH_Q2440 Q2440 1997
++qq2440 MACH_QQ2440 QQ2440 1998
++mini2440 MACH_MINI2440 MINI2440 1999
++colibri300 MACH_COLIBRI300 COLIBRI300 2000
++jades MACH_JADES JADES 2001
++spark MACH_SPARK SPARK 2002
++benzina MACH_BENZINA BENZINA 2003
++blaze MACH_BLAZE BLAZE 2004
++linkstation_ls_hgl MACH_LINKSTATION_LS_HGL LINKSTATION_LS_HGL 2005
++htckovsky MACH_HTCKOVSKY HTCKOVSKY 2006
++sony_prs505 MACH_SONY_PRS505 SONY_PRS505 2007
++hanlin_v3 MACH_HANLIN_V3 HANLIN_V3 2008
++sapphira MACH_SAPPHIRA SAPPHIRA 2009
++dack_sda_01 MACH_DACK_SDA_01 DACK_SDA_01 2010
++armbox MACH_ARMBOX ARMBOX 2011
++harris_rvp MACH_HARRIS_RVP HARRIS_RVP 2012
++ribaldo MACH_RIBALDO RIBALDO 2013
++agora MACH_AGORA AGORA 2014
++omap3_mini MACH_OMAP3_MINI OMAP3_MINI 2015
++a9sam6432_b MACH_A9SAM6432_B A9SAM6432_B 2016
++usg2410 MACH_USG2410 USG2410 2017
++pc72052_i10_revb MACH_PC72052_I10_REVB PC72052_I10_REVB 2018
++mx35_exm32 MACH_MX35_EXM32 MX35_EXM32 2019
++topas910 MACH_TOPAS910 TOPAS910 2020
++hyena MACH_HYENA HYENA 2021
++pospax MACH_POSPAX POSPAX 2022
++hdl_gx MACH_HDL_GX HDL_GX 2023
++ctera_4bay MACH_CTERA_4BAY CTERA_4BAY 2024
++ctera_plug_c MACH_CTERA_PLUG_C CTERA_PLUG_C 2025
++crwea_plug_i MACH_CRWEA_PLUG_I CRWEA_PLUG_I 2026
++egauge2 MACH_EGAUGE2 EGAUGE2 2027
++didj MACH_DIDJ DIDJ 2028
++m_s3c2443 MACH_MEISTER MEISTER 2029
++htcblackstone MACH_HTCBLACKSTONE HTCBLACKSTONE 2030
++cpuat9g20 MACH_CPUAT9G20 CPUAT9G20 2031
++smdk6440 MACH_SMDK6440 SMDK6440 2032
++omap_35xx_mvp MACH_OMAP_35XX_MVP OMAP_35XX_MVP 2033
++ctera_plug_i MACH_CTERA_PLUG_I CTERA_PLUG_I 2034
++pvg610_100 MACH_PVG610 PVG610 2035
++hprw6815 MACH_HPRW6815 HPRW6815 2036
++omap3_oswald MACH_OMAP3_OSWALD OMAP3_OSWALD 2037
++nas4220b MACH_NAS4220B NAS4220B 2038
++htcraphael_cdma MACH_HTCRAPHAEL_CDMA HTCRAPHAEL_CDMA 2039
++htcdiamond_cdma MACH_HTCDIAMOND_CDMA HTCDIAMOND_CDMA 2040
++scaler MACH_SCALER SCALER 2041
++zylonite2 MACH_ZYLONITE2 ZYLONITE2 2042
++aspenite MACH_ASPENITE ASPENITE 2043
++teton MACH_TETON TETON 2044
++ttc_dkb MACH_TTC_DKB TTC_DKB 2045
++bishop2 MACH_BISHOP2 BISHOP2 2046
++ippv5 MACH_IPPV5 IPPV5 2047
++farm926 MACH_FARM926 FARM926 2048
++mmccpu MACH_MMCCPU MMCCPU 2049
++sgmsfl MACH_SGMSFL SGMSFL 2050
++tt8000 MACH_TT8000 TT8000 2051
++zrn4300lp MACH_ZRN4300LP ZRN4300LP 2052
++mptc MACH_MPTC MPTC 2053
++h6051 MACH_H6051 H6051 2054
++pvg610_101 MACH_PVG610_101 PVG610_101 2055
++stamp9261_pc_evb MACH_STAMP9261_PC_EVB STAMP9261_PC_EVB 2056
++pelco_odysseus MACH_PELCO_ODYSSEUS PELCO_ODYSSEUS 2057
++tny_a9260 MACH_TNY_A9260 TNY_A9260 2058
++tny_a9g20 MACH_TNY_A9G20 TNY_A9G20 2059
++aesop_mp2530f MACH_AESOP_MP2530F AESOP_MP2530F 2060
++dx900 MACH_DX900 DX900 2061
++cpodc2 MACH_CPODC2 CPODC2 2062
++tilt_8925 MACH_TILT_8925 TILT_8925 2063
++davinci_dm357_evm MACH_DAVINCI_DM357_EVM DAVINCI_DM357_EVM 2064
++swordfish MACH_SWORDFISH SWORDFISH 2065
++corvus MACH_CORVUS CORVUS 2066
++taurus MACH_TAURUS TAURUS 2067
++axm MACH_AXM AXM 2068
++axc MACH_AXC AXC 2069
++baby MACH_BABY BABY 2070
++mp200 MACH_MP200 MP200 2071
++pcm043 MACH_PCM043 PCM043 2072
++hanlin_v3c MACH_HANLIN_V3C HANLIN_V3C 2073
++kbk9g20 MACH_KBK9G20 KBK9G20 2074
++adsturbog5 MACH_ADSTURBOG5 ADSTURBOG5 2075
++avenger_lite1 MACH_AVENGER_LITE1 AVENGER_LITE1 2076
++suc82x MACH_SUC SUC 2077
++at91sam7s256 MACH_AT91SAM7S256 AT91SAM7S256 2078
++mendoza MACH_MENDOZA MENDOZA 2079
++kira MACH_KIRA KIRA 2080
++mx1hbm MACH_MX1HBM MX1HBM 2081
++quatro43xx MACH_QUATRO43XX QUATRO43XX 2082
++quatro4230 MACH_QUATRO4230 QUATRO4230 2083
++nsb400 MACH_NSB400 NSB400 2084
++drp255 MACH_DRP255 DRP255 2085
++thoth MACH_THOTH THOTH 2086
++firestone MACH_FIRESTONE FIRESTONE 2087
++asusp750 MACH_ASUSP750 ASUSP750 2088
++ctera_dl MACH_CTERA_DL CTERA_DL 2089
++socr MACH_SOCR SOCR 2090
++htcoxygen MACH_HTCOXYGEN HTCOXYGEN 2091
++heroc MACH_HEROC HEROC 2092
++zeno6800 MACH_ZENO6800 ZENO6800 2093
++sc2mcs MACH_SC2MCS SC2MCS 2094
++gene100 MACH_GENE100 GENE100 2095
++as353x MACH_AS353X AS353X 2096
++sheevaplug MACH_SHEEVAPLUG SHEEVAPLUG 2097
++at91sam9g20 MACH_AT91SAM9G20 AT91SAM9G20 2098
++mv88f6192gtw_fe MACH_MV88F6192GTW_FE MV88F6192GTW_FE 2099
++cc9200 MACH_CC9200 CC9200 2100
++sm9200 MACH_SM9200 SM9200 2101
++tp9200 MACH_TP9200 TP9200 2102
++snapperdv MACH_SNAPPERDV SNAPPERDV 2103
++avengers_lite MACH_AVENGERS_LITE AVENGERS_LITE 2104
++avengers_lite1 MACH_AVENGERS_LITE1 AVENGERS_LITE1 2105
++omap3axon MACH_OMAP3AXON OMAP3AXON 2106
++ma8xx MACH_MA8XX MA8XX 2107
++mp201ek MACH_MP201EK MP201EK 2108
++davinci_tux MACH_DAVINCI_TUX DAVINCI_TUX 2109
++mpa1600 MACH_MPA1600 MPA1600 2110
++pelco_troy MACH_PELCO_TROY PELCO_TROY 2111
++nsb667 MACH_NSB667 NSB667 2112
++rovers5_4mpix MACH_ROVERS5_4MPIX ROVERS5_4MPIX 2113
++twocom MACH_TWOCOM TWOCOM 2114
++ubisys_p9_rcu3r2 MACH_UBISYS_P9_RCU3R2 UBISYS_P9_RCU3R2 2115
++hero_espresso MACH_HERO_ESPRESSO HERO_ESPRESSO 2116
++afeusb MACH_AFEUSB AFEUSB 2117
++t830 MACH_T830 T830 2118
++spd8020_cc MACH_SPD8020_CC SPD8020_CC 2119
++om_3d7k MACH_OM_3D7K OM_3D7K 2120
++picocom2 MACH_PICOCOM2 PICOCOM2 2121
++uwg4mx27 MACH_UWG4MX27 UWG4MX27 2122
++uwg4mx31 MACH_UWG4MX31 UWG4MX31 2123
++cherry MACH_CHERRY CHERRY 2124
++mx51_babbage MACH_MX51_BABBAGE MX51_BABBAGE 2125
++s3c2440turkiye MACH_S3C2440TURKIYE S3C2440TURKIYE 2126
++tx37 MACH_TX37 TX37 2127
++sbc2800_9g20 MACH_SBC2800_9G20 SBC2800_9G20 2128
++benzglb MACH_BENZGLB BENZGLB 2129
++benztd MACH_BENZTD BENZTD 2130
++cartesio_plus MACH_CARTESIO_PLUS CARTESIO_PLUS 2131
++solrad_g20 MACH_SOLRAD_G20 SOLRAD_G20 2132
++mx27wallace MACH_MX27WALLACE MX27WALLACE 2133
++fmzwebmodul MACH_FMZWEBMODUL FMZWEBMODUL 2134
++rd78x00_masa MACH_RD78X00_MASA RD78X00_MASA 2135
++smallogger MACH_SMALLOGGER SMALLOGGER 2136
++ccw9p9215 MACH_CCW9P9215 CCW9P9215 2137
++dm355_leopard MACH_DM355_LEOPARD DM355_LEOPARD 2138
++ts219 MACH_TS219 TS219 2139
++tny_a9263 MACH_TNY_A9263 TNY_A9263 2140
++apollo MACH_APOLLO APOLLO 2141
++at91cap9stk MACH_AT91CAP9STK AT91CAP9STK 2142
++spc300 MACH_SPC300 SPC300 2143
++eko MACH_EKO EKO 2144
++ccw9m2443 MACH_CCW9M2443 CCW9M2443 2145
++ccw9m2443js MACH_CCW9M2443JS CCW9M2443JS 2146
++m2m_router_device MACH_M2M_ROUTER_DEVICE M2M_ROUTER_DEVICE 2147
++str9104nas MACH_STAR9104NAS STAR9104NAS 2148
++pca100 MACH_PCA100 PCA100 2149
++z3_dm365_mod_01 MACH_Z3_DM365_MOD_01 Z3_DM365_MOD_01 2150
++hipox MACH_HIPOX HIPOX 2151
++omap3_piteds MACH_OMAP3_PITEDS OMAP3_PITEDS 2152
++bm150r MACH_BM150R BM150R 2153
++tbone MACH_TBONE TBONE 2154
++merlin MACH_MERLIN MERLIN 2155
++falcon MACH_FALCON FALCON 2156
++davinci_da850_evm MACH_DAVINCI_DA850_EVM DAVINCI_DA850_EVM 2157
++s5p6440 MACH_S5P6440 S5P6440 2158
++at91sam9g10ek MACH_AT91SAM9G10EK AT91SAM9G10EK 2159
++omap_4430sdp MACH_OMAP_4430SDP OMAP_4430SDP 2160
++lpc313x MACH_LPC313X LPC313X 2161
++magx_zn5 MACH_MAGX_ZN5 MAGX_ZN5 2162
++magx_em30 MACH_MAGX_EM30 MAGX_EM30 2163
++magx_ve66 MACH_MAGX_VE66 MAGX_VE66 2164
++meesc MACH_MEESC MEESC 2165
++otc570 MACH_OTC570 OTC570 2166
++bcu2412 MACH_BCU2412 BCU2412 2167
++beacon MACH_BEACON BEACON 2168
++actia_tgw MACH_ACTIA_TGW ACTIA_TGW 2169
++e4430 MACH_E4430 E4430 2170
++ql300 MACH_QL300 QL300 2171
++btmavb101 MACH_BTMAVB101 BTMAVB101 2172
++btmawb101 MACH_BTMAWB101 BTMAWB101 2173
++sq201 MACH_SQ201 SQ201 2174
++quatro45xx MACH_QUATRO45XX QUATRO45XX 2175
++openpad MACH_OPENPAD OPENPAD 2176
++tx25 MACH_TX25 TX25 2177
++omap3_torpedo MACH_OMAP3_TORPEDO OMAP3_TORPEDO 2178
++htcraphael_k MACH_HTCRAPHAEL_K HTCRAPHAEL_K 2179
++lal43 MACH_LAL43 LAL43 2181
++htcraphael_cdma500 MACH_HTCRAPHAEL_CDMA500 HTCRAPHAEL_CDMA500 2182
++anw6410 MACH_ANW6410 ANW6410 2183
++htcprophet MACH_HTCPROPHET HTCPROPHET 2185
++cfa_10022 MACH_CFA_10022 CFA_10022 2186
++imx27_visstrim_m10 MACH_IMX27_VISSTRIM_M10 IMX27_VISSTRIM_M10 2187
++px2imx27 MACH_PX2IMX27 PX2IMX27 2188
++stm3210e_eval MACH_STM3210E_EVAL STM3210E_EVAL 2189
++dvs10 MACH_DVS10 DVS10 2190
++portuxg20 MACH_PORTUXG20 PORTUXG20 2191
++arm_spv MACH_ARM_SPV ARM_SPV 2192
++smdkc110 MACH_SMDKC110 SMDKC110 2193
++cabespresso MACH_CABESPRESSO CABESPRESSO 2194
++hmc800 MACH_HMC800 HMC800 2195
++sholes MACH_SHOLES SHOLES 2196
++btmxc31 MACH_BTMXC31 BTMXC31 2197
++dt501 MACH_DT501 DT501 2198
++ktx MACH_KTX KTX 2199
++omap3517evm MACH_OMAP3517EVM OMAP3517EVM 2200
++netspace_v2 MACH_NETSPACE_V2 NETSPACE_V2 2201
++netspace_max_v2 MACH_NETSPACE_MAX_V2 NETSPACE_MAX_V2 2202
++d2net_v2 MACH_D2NET_V2 D2NET_V2 2203
++net2big_v2 MACH_NET2BIG_V2 NET2BIG_V2 2204
++net4big_v2 MACH_NET4BIG_V2 NET4BIG_V2 2205
++net5big_v2 MACH_NET5BIG_V2 NET5BIG_V2 2206
++endb2443 MACH_ENDB2443 ENDB2443 2207
++inetspace_v2 MACH_INETSPACE_V2 INETSPACE_V2 2208
++tros MACH_TROS TROS 2209
++pelco_homer MACH_PELCO_HOMER PELCO_HOMER 2210
++ofsp8 MACH_OFSP8 OFSP8 2211
++at91sam9g45ekes MACH_AT91SAM9G45EKES AT91SAM9G45EKES 2212
++guf_cupid MACH_GUF_CUPID GUF_CUPID 2213
++eab1r MACH_EAB1R EAB1R 2214
++desirec MACH_DESIREC DESIREC 2215
++cordoba MACH_CORDOBA CORDOBA 2216
++irvine MACH_IRVINE IRVINE 2217
++sff772 MACH_SFF772 SFF772 2218
++pelco_milano MACH_PELCO_MILANO PELCO_MILANO 2219
++pc7302 MACH_PC7302 PC7302 2220
++bip6000 MACH_BIP6000 BIP6000 2221
++silvermoon MACH_SILVERMOON SILVERMOON 2222
++vc0830 MACH_VC0830 VC0830 2223
++dt430 MACH_DT430 DT430 2224
++ji42pf MACH_JI42PF JI42PF 2225
++gnet_ksm MACH_GNET_KSM GNET_KSM 2226
++gnet_sgm MACH_GNET_SGM GNET_SGM 2227
++gnet_sgr MACH_GNET_SGR GNET_SGR 2228
++omap3_icetekevm MACH_OMAP3_ICETEKEVM OMAP3_ICETEKEVM 2229
++pnp MACH_PNP PNP 2230
++ctera_2bay_k MACH_CTERA_2BAY_K CTERA_2BAY_K 2231
++ctera_2bay_u MACH_CTERA_2BAY_U CTERA_2BAY_U 2232
++sas_c MACH_SAS_C SAS_C 2233
++vma2315 MACH_VMA2315 VMA2315 2234
++vcs MACH_VCS VCS 2235
++spear600 MACH_SPEAR600 SPEAR600 2236
++spear300 MACH_SPEAR300 SPEAR300 2237
++spear1300 MACH_SPEAR1300 SPEAR1300 2238
++lilly1131 MACH_LILLY1131 LILLY1131 2239
++arvoo_ax301 MACH_ARVOO_AX301 ARVOO_AX301 2240
++mapphone MACH_MAPPHONE MAPPHONE 2241
++legend MACH_LEGEND LEGEND 2242
++salsa MACH_SALSA SALSA 2243
++lounge MACH_LOUNGE LOUNGE 2244
++vision MACH_VISION VISION 2245
++vmb20 MACH_VMB20 VMB20 2246
++hy2410 MACH_HY2410 HY2410 2247
++hy9315 MACH_HY9315 HY9315 2248
++bullwinkle MACH_BULLWINKLE BULLWINKLE 2249
++arm_ultimator2 MACH_ARM_ULTIMATOR2 ARM_ULTIMATOR2 2250
++vs_v210 MACH_VS_V210 VS_V210 2252
++vs_v212 MACH_VS_V212 VS_V212 2253
++hmt MACH_HMT HMT 2254
++suen3 MACH_SUEN3 SUEN3 2255
++vesper MACH_VESPER VESPER 2256
++str9 MACH_STR9 STR9 2257
++omap3_wl_ff MACH_OMAP3_WL_FF OMAP3_WL_FF 2258
++simcom MACH_SIMCOM SIMCOM 2259
++mcwebio MACH_MCWEBIO MCWEBIO 2260
++omap3_phrazer MACH_OMAP3_PHRAZER OMAP3_PHRAZER 2261
++darwin MACH_DARWIN DARWIN 2262
++oratiscomu MACH_ORATISCOMU ORATISCOMU 2263
++rtsbc20 MACH_RTSBC20 RTSBC20 2264
++sgh_i780 MACH_I780 I780 2265
++gemini324 MACH_GEMINI324 GEMINI324 2266
++oratislan MACH_ORATISLAN ORATISLAN 2267
++oratisalog MACH_ORATISALOG ORATISALOG 2268
++oratismadi MACH_ORATISMADI ORATISMADI 2269
++oratisot16 MACH_ORATISOT16 ORATISOT16 2270
++oratisdesk MACH_ORATISDESK ORATISDESK 2271
++vexpress MACH_VEXPRESS VEXPRESS 2272
++sintexo MACH_SINTEXO SINTEXO 2273
++cm3389 MACH_CM3389 CM3389 2274
++omap3_cio MACH_OMAP3_CIO OMAP3_CIO 2275
++sgh_i900 MACH_SGH_I900 SGH_I900 2276
++bst100 MACH_BST100 BST100 2277
++passion MACH_PASSION PASSION 2278
++indesign_at91sam MACH_INDESIGN_AT91SAM INDESIGN_AT91SAM 2279
++c4_badger MACH_C4_BADGER C4_BADGER 2280
++c4_viper MACH_C4_VIPER C4_VIPER 2281
++d2net MACH_D2NET D2NET 2282
++bigdisk MACH_BIGDISK BIGDISK 2283
++notalvision MACH_NOTALVISION NOTALVISION 2284
++omap3_kboc MACH_OMAP3_KBOC OMAP3_KBOC 2285
++cyclone MACH_CYCLONE CYCLONE 2286
++ninja MACH_NINJA NINJA 2287
++at91sam9g20ek_2mmc MACH_AT91SAM9G20EK_2MMC AT91SAM9G20EK_2MMC 2288
++bcmring MACH_BCMRING BCMRING 2289
++resol_dl2 MACH_RESOL_DL2 RESOL_DL2 2290
++ifosw MACH_IFOSW IFOSW 2291
++htcrhodium MACH_HTCRHODIUM HTCRHODIUM 2292
++htctopaz MACH_HTCTOPAZ HTCTOPAZ 2293
++matrix504 MACH_MATRIX504 MATRIX504 2294
++mrfsa MACH_MRFSA MRFSA 2295
++sc_p270 MACH_SC_P270 SC_P270 2296
++atlas5_evb MACH_ATLAS5_EVB ATLAS5_EVB 2297
++pelco_lobox MACH_PELCO_LOBOX PELCO_LOBOX 2298
++dilax_pcu200 MACH_DILAX_PCU200 DILAX_PCU200 2299
++leonardo MACH_LEONARDO LEONARDO 2300
++zoran_approach7 MACH_ZORAN_APPROACH7 ZORAN_APPROACH7 2301
++dp6xx MACH_DP6XX DP6XX 2302
++bcm2153_vesper MACH_BCM2153_VESPER BCM2153_VESPER 2303
++mahimahi MACH_MAHIMAHI MAHIMAHI 2304
++clickc MACH_CLICKC CLICKC 2305
++zb_gateway MACH_ZB_GATEWAY ZB_GATEWAY 2306
++tazcard MACH_TAZCARD TAZCARD 2307
++tazdev MACH_TAZDEV TAZDEV 2308
++annax_cb_arm MACH_ANNAX_CB_ARM ANNAX_CB_ARM 2309
++annax_dm3 MACH_ANNAX_DM3 ANNAX_DM3 2310
++cerebric MACH_CEREBRIC CEREBRIC 2311
++orca MACH_ORCA ORCA 2312
++pc9260 MACH_PC9260 PC9260 2313
++ems285a MACH_EMS285A EMS285A 2314
++gec2410 MACH_GEC2410 GEC2410 2315
++gec2440 MACH_GEC2440 GEC2440 2316
++mw903 MACH_ARCH_MW903 ARCH_MW903 2317
++mw2440 MACH_MW2440 MW2440 2318
++ecac2378 MACH_ECAC2378 ECAC2378 2319
++tazkiosk MACH_TAZKIOSK TAZKIOSK 2320
++whiterabbit_mch MACH_WHITERABBIT_MCH WHITERABBIT_MCH 2321
++sbox9263 MACH_SBOX9263 SBOX9263 2322
++oreo MACH_OREO OREO 2323
++smdk6442 MACH_SMDK6442 SMDK6442 2324
++openrd_base MACH_OPENRD_BASE OPENRD_BASE 2325
++incredible MACH_INCREDIBLE INCREDIBLE 2326
++incrediblec MACH_INCREDIBLEC INCREDIBLEC 2327
++heroct MACH_HEROCT HEROCT 2328
++mmnet1000 MACH_MMNET1000 MMNET1000 2329
++devkit8000 MACH_DEVKIT8000 DEVKIT8000 2330
++devkit9000 MACH_DEVKIT9000 DEVKIT9000 2331
++mx31txtr MACH_MX31TXTR MX31TXTR 2332
++u380 MACH_U380 U380 2333
++oamp3_hualu MACH_HUALU_BOARD HUALU_BOARD 2334
++npcmx50 MACH_NPCMX50 NPCMX50 2335
++mx51_lange51 MACH_MX51_LANGE51 MX51_LANGE51 2336
++mx51_lange52 MACH_MX51_LANGE52 MX51_LANGE52 2337
++riom MACH_RIOM RIOM 2338
++comcas MACH_COMCAS COMCAS 2339
++wsi_mx27 MACH_WSI_MX27 WSI_MX27 2340
++cm_t35 MACH_CM_T35 CM_T35 2341
++net2big MACH_NET2BIG NET2BIG 2342
++motorola_a1600 MACH_MOTOROLA_A1600 MOTOROLA_A1600 2343
++igep0020 MACH_IGEP0020 IGEP0020 2344
++igep0010 MACH_IGEP0010 IGEP0010 2345
++mv6281gtwge2 MACH_MV6281GTWGE2 MV6281GTWGE2 2346
++scat100 MACH_SCAT100 SCAT100 2347
++sanmina MACH_SANMINA SANMINA 2348
++momento MACH_MOMENTO MOMENTO 2349
++nuc9xx MACH_NUC9XX NUC9XX 2350
++nuc910evb MACH_NUC910EVB NUC910EVB 2351
++nuc920evb MACH_NUC920EVB NUC920EVB 2352
++nuc950evb MACH_NUC950EVB NUC950EVB 2353
++nuc945evb MACH_NUC945EVB NUC945EVB 2354
++nuc960evb MACH_NUC960EVB NUC960EVB 2355
++nuc932evb MACH_NUC932EVB NUC932EVB 2356
++nuc900 MACH_NUC900 NUC900 2357
++sd1soc MACH_SD1SOC SD1SOC 2358
++ln2440bc MACH_LN2440BC LN2440BC 2359
++rsbc MACH_RSBC RSBC 2360
++openrd_client MACH_OPENRD_CLIENT OPENRD_CLIENT 2361
++hpipaq11x MACH_HPIPAQ11X HPIPAQ11X 2362
++wayland MACH_WAYLAND WAYLAND 2363
++acnbsx102 MACH_ACNBSX102 ACNBSX102 2364
++hwat91 MACH_HWAT91 HWAT91 2365
++at91sam9263cs MACH_AT91SAM9263CS AT91SAM9263CS 2366
++csb732 MACH_CSB732 CSB732 2367
++u8500 MACH_U8500 U8500 2368
++huqiu MACH_HUQIU HUQIU 2369
++mx51_kunlun MACH_MX51_KUNLUN MX51_KUNLUN 2370
++pmt1g MACH_PMT1G PMT1G 2371
++htcelf MACH_HTCELF HTCELF 2372
++armadillo420 MACH_ARMADILLO420 ARMADILLO420 2373
++armadillo440 MACH_ARMADILLO440 ARMADILLO440 2374
++u_chip_dual_arm MACH_U_CHIP_DUAL_ARM U_CHIP_DUAL_ARM 2375
++csr_bdb3 MACH_CSR_BDB3 CSR_BDB3 2376
++dolby_cat1018 MACH_DOLBY_CAT1018 DOLBY_CAT1018 2377
++hy9307 MACH_HY9307 HY9307 2378
++aspire_easystore MACH_A_ES A_ES 2379
++davinci_irif MACH_DAVINCI_IRIF DAVINCI_IRIF 2380
++agama9263 MACH_AGAMA9263 AGAMA9263 2381
++marvell_jasper MACH_MARVELL_JASPER MARVELL_JASPER 2382
++flint MACH_FLINT FLINT 2383
++tavorevb3 MACH_TAVOREVB3 TAVOREVB3 2384
++sch_m490 MACH_SCH_M490 SCH_M490 2386
++rbl01 MACH_RBL01 RBL01 2387
++omnifi MACH_OMNIFI OMNIFI 2388
++otavalo MACH_OTAVALO OTAVALO 2389
++sienna MACH_SIENNA SIENNA 2390
++htc_excalibur_s620 MACH_HTC_EXCALIBUR_S620 HTC_EXCALIBUR_S620 2391
++htc_opal MACH_HTC_OPAL HTC_OPAL 2392
++touchbook MACH_TOUCHBOOK TOUCHBOOK 2393
++latte MACH_LATTE LATTE 2394
++xa200 MACH_XA200 XA200 2395
++nimrod MACH_NIMROD NIMROD 2396
++cc9p9215_3g MACH_CC9P9215_3G CC9P9215_3G 2397
++cc9p9215_3gjs MACH_CC9P9215_3GJS CC9P9215_3GJS 2398
++tk71 MACH_TK71 TK71 2399
++comham3525 MACH_COMHAM3525 COMHAM3525 2400
++mx31erebus MACH_MX31EREBUS MX31EREBUS 2401
++mcardmx27 MACH_MCARDMX27 MCARDMX27 2402
++paradise MACH_PARADISE PARADISE 2403
++tide MACH_TIDE TIDE 2404
++wzl2440 MACH_WZL2440 WZL2440 2405
++sdrdemo MACH_SDRDEMO SDRDEMO 2406
++ethercan2 MACH_ETHERCAN2 ETHERCAN2 2407
++ecmimg20 MACH_ECMIMG20 ECMIMG20 2408
++omap_dragon MACH_OMAP_DRAGON OMAP_DRAGON 2409
++halo MACH_HALO HALO 2410
++huangshan MACH_HUANGSHAN HUANGSHAN 2411
++vl_ma2sc MACH_VL_MA2SC VL_MA2SC 2412
++raumfeld_rc MACH_RAUMFELD_RC RAUMFELD_RC 2413
++raumfeld_connector MACH_RAUMFELD_CONNECTOR RAUMFELD_CONNECTOR 2414
++raumfeld_speaker MACH_RAUMFELD_SPEAKER RAUMFELD_SPEAKER 2415
++multibus_master MACH_MULTIBUS_MASTER MULTIBUS_MASTER 2416
++multibus_pbk MACH_MULTIBUS_PBK MULTIBUS_PBK 2417
++tnetv107x MACH_TNETV107X TNETV107X 2418
++snake MACH_SNAKE SNAKE 2419
++cwmx27 MACH_CWMX27 CWMX27 2420
++sch_m480 MACH_SCH_M480 SCH_M480 2421
++platypus MACH_PLATYPUS PLATYPUS 2422
++pss2 MACH_PSS2 PSS2 2423
++davinci_apm150 MACH_DAVINCI_APM150 DAVINCI_APM150 2424
++str9100 MACH_STR9100 STR9100 2425
++net5big MACH_NET5BIG NET5BIG 2426
++seabed9263 MACH_SEABED9263 SEABED9263 2427
++mx51_m2id MACH_MX51_M2ID MX51_M2ID 2428
++octvocplus_eb MACH_OCTVOCPLUS_EB OCTVOCPLUS_EB 2429
++klk_firefox MACH_KLK_FIREFOX KLK_FIREFOX 2430
++klk_wirma_module MACH_KLK_WIRMA_MODULE KLK_WIRMA_MODULE 2431
++klk_wirma_mmi MACH_KLK_WIRMA_MMI KLK_WIRMA_MMI 2432
++supersonic MACH_SUPERSONIC SUPERSONIC 2433
++liberty MACH_LIBERTY LIBERTY 2434
++mh355 MACH_MH355 MH355 2435
++pc7802 MACH_PC7802 PC7802 2436
++gnet_sgc MACH_GNET_SGC GNET_SGC 2437
++einstein15 MACH_EINSTEIN15 EINSTEIN15 2438
++cmpd MACH_CMPD CMPD 2439
++davinci_hase1 MACH_DAVINCI_HASE1 DAVINCI_HASE1 2440
++lgeincitephone MACH_LGEINCITEPHONE LGEINCITEPHONE 2441
++ea313x MACH_EA313X EA313X 2442
++fwbd_39064 MACH_FWBD_39064 FWBD_39064 2443
++fwbd_390128 MACH_FWBD_390128 FWBD_390128 2444
++pelco_moe MACH_PELCO_MOE PELCO_MOE 2445
++minimix27 MACH_MINIMIX27 MINIMIX27 2446
++omap3_thunder MACH_OMAP3_THUNDER OMAP3_THUNDER 2447
++passionc MACH_PASSIONC PASSIONC 2448
++mx27amata MACH_MX27AMATA MX27AMATA 2449
++bgat1 MACH_BGAT1 BGAT1 2450
++buzz MACH_BUZZ BUZZ 2451
++mb9g20 MACH_MB9G20 MB9G20 2452
++yushan MACH_YUSHAN YUSHAN 2453
++lizard MACH_LIZARD LIZARD 2454
++omap3polycom MACH_OMAP3POLYCOM OMAP3POLYCOM 2455
++smdkv210 MACH_SMDKV210 SMDKV210 2456
++bravo MACH_BRAVO BRAVO 2457
++siogentoo1 MACH_SIOGENTOO1 SIOGENTOO1 2458
++siogentoo2 MACH_SIOGENTOO2 SIOGENTOO2 2459
++sm3k MACH_SM3K SM3K 2460
++acer_tempo_f900 MACH_ACER_TEMPO_F900 ACER_TEMPO_F900 2461
++sst61vc010_dev MACH_SST61VC010_DEV SST61VC010_DEV 2462
++glittertind MACH_GLITTERTIND GLITTERTIND 2463
++omap_zoom3 MACH_OMAP_ZOOM3 OMAP_ZOOM3 2464
++omap_3630sdp MACH_OMAP_3630SDP OMAP_3630SDP 2465
++cybook2440 MACH_CYBOOK2440 CYBOOK2440 2466
++torino_s MACH_TORINO_S TORINO_S 2467
++havana MACH_HAVANA HAVANA 2468
++beaumont_11 MACH_BEAUMONT_11 BEAUMONT_11 2469
++vanguard MACH_VANGUARD VANGUARD 2470
++s5pc110_draco MACH_S5PC110_DRACO S5PC110_DRACO 2471
++cartesio_two MACH_CARTESIO_TWO CARTESIO_TWO 2472
++aster MACH_ASTER ASTER 2473
++voguesv210 MACH_VOGUESV210 VOGUESV210 2474
++acm500x MACH_ACM500X ACM500X 2475
++km9260 MACH_KM9260 KM9260 2476
++nideflexg1 MACH_NIDEFLEXG1 NIDEFLEXG1 2477
++ctera_plug_io MACH_CTERA_PLUG_IO CTERA_PLUG_IO 2478
++smartq7 MACH_SMARTQ7 SMARTQ7 2479
++at91sam9g10ek2 MACH_AT91SAM9G10EK2 AT91SAM9G10EK2 2480
++asusp527 MACH_ASUSP527 ASUSP527 2481
++at91sam9g20mpm2 MACH_AT91SAM9G20MPM2 AT91SAM9G20MPM2 2482
++topasa900 MACH_TOPASA900 TOPASA900 2483
++electrum_100 MACH_ELECTRUM_100 ELECTRUM_100 2484
++mx51grb MACH_MX51GRB MX51GRB 2485
++xea300 MACH_XEA300 XEA300 2486
++htcstartrek MACH_HTCSTARTREK HTCSTARTREK 2487
++lima MACH_LIMA LIMA 2488
++csb740 MACH_CSB740 CSB740 2489
++usb_s8815 MACH_USB_S8815 USB_S8815 2490
++watson_efm_plugin MACH_WATSON_EFM_PLUGIN WATSON_EFM_PLUGIN 2491
++milkyway MACH_MILKYWAY MILKYWAY 2492
++g4evm MACH_G4EVM G4EVM 2493
++picomod6 MACH_PICOMOD6 PICOMOD6 2494
++omapl138_hawkboard MACH_OMAPL138_HAWKBOARD OMAPL138_HAWKBOARD 2495
++ip6000 MACH_IP6000 IP6000 2496
++ip6010 MACH_IP6010 IP6010 2497
++utm400 MACH_UTM400 UTM400 2498
++omap3_zybex MACH_OMAP3_ZYBEX OMAP3_ZYBEX 2499
++wireless_space MACH_WIRELESS_SPACE WIRELESS_SPACE 2500
++sx560 MACH_SX560 SX560 2501
++ts41x MACH_TS41X TS41X 2502
++elphel10373 MACH_ELPHEL10373 ELPHEL10373 2503
++rhobot MACH_RHOBOT RHOBOT 2504
++mx51_refresh MACH_MX51_REFRESH MX51_REFRESH 2505
++ls9260 MACH_LS9260 LS9260 2506
++shank MACH_SHANK SHANK 2507
++qsd8x50_st1 MACH_QSD8X50_ST1 QSD8X50_ST1 2508
++at91sam9m10ekes MACH_AT91SAM9M10EKES AT91SAM9M10EKES 2509
++hiram MACH_HIRAM HIRAM 2510
++phy3250 MACH_PHY3250 PHY3250 2511
++ea3250 MACH_EA3250 EA3250 2512
++fdi3250 MACH_FDI3250 FDI3250 2513
++whitestone MACH_WHITESTONE WHITESTONE 2514
++at91sam9263nit MACH_AT91SAM9263NIT AT91SAM9263NIT 2515
++ccmx51 MACH_CCMX51 CCMX51 2516
++ccmx51js MACH_CCMX51JS CCMX51JS 2517
++ccwmx51 MACH_CCWMX51 CCWMX51 2518
++ccwmx51js MACH_CCWMX51JS CCWMX51JS 2519
++mini6410 MACH_MINI6410 MINI6410 2520
++tiny6410 MACH_TINY6410 TINY6410 2521
++nano6410 MACH_NANO6410 NANO6410 2522
++at572d940hfnldb MACH_AT572D940HFNLDB AT572D940HFNLDB 2523
++htcleo MACH_HTCLEO HTCLEO 2524
++avp13 MACH_AVP13 AVP13 2525
++xxsvideod MACH_XXSVIDEOD XXSVIDEOD 2526
++vpnext MACH_VPNEXT VPNEXT 2527
++swarco_itc3 MACH_SWARCO_ITC3 SWARCO_ITC3 2528
++tx51 MACH_TX51 TX51 2529
++dolby_cat1021 MACH_DOLBY_CAT1021 DOLBY_CAT1021 2530
++mx28evk MACH_MX28EVK MX28EVK 2531
++phoenix260 MACH_PHOENIX260 PHOENIX260 2532
++uvaca_stork MACH_UVACA_STORK UVACA_STORK 2533
++smartq5 MACH_SMARTQ5 SMARTQ5 2534
++all3078 MACH_ALL3078 ALL3078 2535
++ctera_2bay_ds MACH_CTERA_2BAY_DS CTERA_2BAY_DS 2536
++siogentoo3 MACH_SIOGENTOO3 SIOGENTOO3 2537
++epb5000 MACH_EPB5000 EPB5000 2538
++hy9263 MACH_HY9263 HY9263 2539
++acer_tempo_m900 MACH_ACER_TEMPO_M900 ACER_TEMPO_M900 2540
++acer_tempo_dx650 MACH_ACER_TEMPO_DX900 ACER_TEMPO_DX900 2541
++acer_tempo_x960 MACH_ACER_TEMPO_X960 ACER_TEMPO_X960 2542
++acer_eten_v900 MACH_ACER_ETEN_V900 ACER_ETEN_V900 2543
++acer_eten_x900 MACH_ACER_ETEN_X900 ACER_ETEN_X900 2544
++bonnell MACH_BONNELL BONNELL 2545
++oht_mx27 MACH_OHT_MX27 OHT_MX27 2546
++htcquartz MACH_HTCQUARTZ HTCQUARTZ 2547
++davinci_dm6467tevm MACH_DAVINCI_DM6467TEVM DAVINCI_DM6467TEVM 2548
++c3ax03 MACH_C3AX03 C3AX03 2549
++mxt_td60 MACH_MXT_TD60 MXT_TD60 2550
++esyx MACH_ESYX ESYX 2551
++dove_db2 MACH_DOVE_DB2 DOVE_DB2 2552
++bulldog MACH_BULLDOG BULLDOG 2553
++derell_me2000 MACH_DERELL_ME2000 DERELL_ME2000 2554
++bcmring_base MACH_BCMRING_BASE BCMRING_BASE 2555
++bcmring_evm MACH_BCMRING_EVM BCMRING_EVM 2556
++bcmring_evm_jazz MACH_BCMRING_EVM_JAZZ BCMRING_EVM_JAZZ 2557
++bcmring_sp MACH_BCMRING_SP BCMRING_SP 2558
++bcmring_sv MACH_BCMRING_SV BCMRING_SV 2559
++bcmring_sv_jazz MACH_BCMRING_SV_JAZZ BCMRING_SV_JAZZ 2560
++bcmring_tablet MACH_BCMRING_TABLET BCMRING_TABLET 2561
++bcmring_vp MACH_BCMRING_VP BCMRING_VP 2562
++bcmring_evm_seikor MACH_BCMRING_EVM_SEIKOR BCMRING_EVM_SEIKOR 2563
++bcmring_sp_wqvga MACH_BCMRING_SP_WQVGA BCMRING_SP_WQVGA 2564
++bcmring_custom MACH_BCMRING_CUSTOM BCMRING_CUSTOM 2565
++acer_s200 MACH_ACER_S200 ACER_S200 2566
++bt270 MACH_BT270 BT270 2567
++iseo MACH_ISEO ISEO 2568
++cezanne MACH_CEZANNE CEZANNE 2569
++lucca MACH_LUCCA LUCCA 2570
++supersmart MACH_SUPERSMART SUPERSMART 2571
++arm11_board MACH_CS_MISANO CS_MISANO 2572
++magnolia2 MACH_MAGNOLIA2 MAGNOLIA2 2573
++emxx MACH_EMXX EMXX 2574
++outlaw MACH_OUTLAW OUTLAW 2575
++riot_bei2 MACH_RIOT_BEI2 RIOT_BEI2 2576
++riot_vox MACH_RIOT_VOX RIOT_VOX 2577
++riot_x37 MACH_RIOT_X37 RIOT_X37 2578
++mega25mx MACH_MEGA25MX MEGA25MX 2579
++benzina2 MACH_BENZINA2 BENZINA2 2580
++ignite MACH_IGNITE IGNITE 2581
++foggia MACH_FOGGIA FOGGIA 2582
++arezzo MACH_AREZZO AREZZO 2583
++leica_skywalker MACH_LEICA_SKYWALKER LEICA_SKYWALKER 2584
++jacinto2_jamr MACH_JACINTO2_JAMR JACINTO2_JAMR 2585
++gts_nova MACH_GTS_NOVA GTS_NOVA 2586
++p3600 MACH_P3600 P3600 2587
++dlt2 MACH_DLT2 DLT2 2588
++df3120 MACH_DF3120 DF3120 2589
++ecucore_9g20 MACH_ECUCORE_9G20 ECUCORE_9G20 2590
++nautel_lpc3240 MACH_NAUTEL_LPC3240 NAUTEL_LPC3240 2591
++glacier MACH_GLACIER GLACIER 2592
++phrazer_bulldog MACH_PHRAZER_BULLDOG PHRAZER_BULLDOG 2593
++omap3_bulldog MACH_OMAP3_BULLDOG OMAP3_BULLDOG 2594
++pca101 MACH_PCA101 PCA101 2595
++buzzc MACH_BUZZC BUZZC 2596
++sasie2 MACH_SASIE2 SASIE2 2597
++davinci_cio MACH_DAVINCI_CIO DAVINCI_CIO 2598
++smartmeter_dl MACH_SMARTMETER_DL SMARTMETER_DL 2599
++wzl6410 MACH_WZL6410 WZL6410 2600
++wzl6410m MACH_WZL6410M WZL6410M 2601
++wzl6410f MACH_WZL6410F WZL6410F 2602
++wzl6410i MACH_WZL6410I WZL6410I 2603
++spacecom1 MACH_SPACECOM1 SPACECOM1 2604
++pingu920 MACH_PINGU920 PINGU920 2605
++bravoc MACH_BRAVOC BRAVOC 2606
++cybo2440 MACH_CYBO2440 CYBO2440 2607
++vdssw MACH_VDSSW VDSSW 2608
++romulus MACH_ROMULUS ROMULUS 2609
++omap_magic MACH_OMAP_MAGIC OMAP_MAGIC 2610
++eltd100 MACH_ELTD100 ELTD100 2611
++capc7117 MACH_CAPC7117 CAPC7117 2612
++swan MACH_SWAN SWAN 2613
++veu MACH_VEU VEU 2614
++rm2 MACH_RM2 RM2 2615
++tt2100 MACH_TT2100 TT2100 2616
++venice MACH_VENICE VENICE 2617
++pc7323 MACH_PC7323 PC7323 2618
++masp MACH_MASP MASP 2619
++fujitsu_tvstbsoc0 MACH_FUJITSU_TVSTBSOC FUJITSU_TVSTBSOC 2620
++fujitsu_tvstbsoc1 MACH_FUJITSU_TVSTBSOC1 FUJITSU_TVSTBSOC1 2621
++lexikon MACH_LEXIKON LEXIKON 2622
++mini2440v2 MACH_MINI2440V2 MINI2440V2 2623
++icontrol MACH_ICONTROL ICONTROL 2624
++gplugd MACH_SHEEVAD SHEEVAD 2625
++qsd8x50a_st1_1 MACH_QSD8X50A_ST1_1 QSD8X50A_ST1_1 2626
++qsd8x50a_st1_5 MACH_QSD8X50A_ST1_5 QSD8X50A_ST1_5 2627
++bee MACH_BEE BEE 2628
++mx23evk MACH_MX23EVK MX23EVK 2629
++ap4evb MACH_AP4EVB AP4EVB 2630
++stockholm MACH_STOCKHOLM STOCKHOLM 2631
++lpc_h3131 MACH_LPC_H3131 LPC_H3131 2632
++stingray MACH_STINGRAY STINGRAY 2633
++kraken MACH_KRAKEN KRAKEN 2634
++gw2388 MACH_GW2388 GW2388 2635
++jadecpu MACH_JADECPU JADECPU 2636
++carlisle MACH_CARLISLE CARLISLE 2637
++lux_sf9 MACH_LUX_SFT9 LUX_SFT9 2638
++nemid_tb MACH_NEMID_TB NEMID_TB 2639
++terrier MACH_TERRIER TERRIER 2640
++turbot MACH_TURBOT TURBOT 2641
++sanddab MACH_SANDDAB SANDDAB 2642
++mx35_cicada MACH_MX35_CICADA MX35_CICADA 2643
++ghi2703d MACH_GHI2703D GHI2703D 2644
++lux_sfx9 MACH_LUX_SFX9 LUX_SFX9 2645
++lux_sf9g MACH_LUX_SF9G LUX_SF9G 2646
++lux_edk9 MACH_LUX_EDK9 LUX_EDK9 2647
++hw90240 MACH_HW90240 HW90240 2648
++dm365_leopard MACH_DM365_LEOPARD DM365_LEOPARD 2649
++mityomapl138 MACH_MITYOMAPL138 MITYOMAPL138 2650
++scat110 MACH_SCAT110 SCAT110 2651
++acer_a1 MACH_ACER_A1 ACER_A1 2652
++cmcontrol MACH_CMCONTROL CMCONTROL 2653
++pelco_lamar MACH_PELCO_LAMAR PELCO_LAMAR 2654
++rfp43 MACH_RFP43 RFP43 2655
++sk86r0301 MACH_SK86R0301 SK86R0301 2656
++ctpxa MACH_CTPXA CTPXA 2657
++epb_arm9_a MACH_EPB_ARM9_A EPB_ARM9_A 2658
++guruplug MACH_GURUPLUG GURUPLUG 2659
++spear310 MACH_SPEAR310 SPEAR310 2660
++spear320 MACH_SPEAR320 SPEAR320 2661
++robotx MACH_ROBOTX ROBOTX 2662
++lsxhl MACH_LSXHL LSXHL 2663
++smartlite MACH_SMARTLITE SMARTLITE 2664
++cws2 MACH_CWS2 CWS2 2665
++m619 MACH_M619 M619 2666
++smartview MACH_SMARTVIEW SMARTVIEW 2667
++lsa_salsa MACH_LSA_SALSA LSA_SALSA 2668
++kizbox MACH_KIZBOX KIZBOX 2669
++htccharmer MACH_HTCCHARMER HTCCHARMER 2670
++guf_neso_lt MACH_GUF_NESO_LT GUF_NESO_LT 2671
++pm9g45 MACH_PM9G45 PM9G45 2672
++htcpanther MACH_HTCPANTHER HTCPANTHER 2673
++htcpanther_cdma MACH_HTCPANTHER_CDMA HTCPANTHER_CDMA 2674
++reb01 MACH_REB01 REB01 2675
++aquila MACH_AQUILA AQUILA 2676
++spark_sls_hw2 MACH_SPARK_SLS_HW2 SPARK_SLS_HW2 2677
++sheeva_esata MACH_ESATA_SHEEVAPLUG ESATA_SHEEVAPLUG 2678
++msm7x30_surf MACH_MSM7X30_SURF MSM7X30_SURF 2679
++micro2440 MACH_MICRO2440 MICRO2440 2680
++am2440 MACH_AM2440 AM2440 2681
++tq2440 MACH_TQ2440 TQ2440 2682
++lpc2478oem MACH_LPC2478OEM LPC2478OEM 2683
++ak880x MACH_AK880X AK880X 2684
++cobra3530 MACH_COBRA3530 COBRA3530 2685
++pmppb MACH_PMPPB PMPPB 2686
++u6715 MACH_U6715 U6715 2687
++axar1500_sender MACH_AXAR1500_SENDER AXAR1500_SENDER 2688
++g30_dvb MACH_G30_DVB G30_DVB 2689
++vc088x MACH_VC088X VC088X 2690
++mioa702 MACH_MIOA702 MIOA702 2691
++hpmin MACH_HPMIN HPMIN 2692
++ak880xak MACH_AK880XAK AK880XAK 2693
++arm926tomap850 MACH_ARM926TOMAP850 ARM926TOMAP850 2694
++lkevm MACH_LKEVM LKEVM 2695
++mw6410 MACH_MW6410 MW6410 2696
++terastation_wxl MACH_TERASTATION_WXL TERASTATION_WXL 2697
++cpu8000e MACH_CPU8000E CPU8000E 2698
++catania MACH_CATANIA CATANIA 2699
++tokyo MACH_TOKYO TOKYO 2700
++msm7201a_surf MACH_MSM7201A_SURF MSM7201A_SURF 2701
++msm7201a_ffa MACH_MSM7201A_FFA MSM7201A_FFA 2702
++msm7x25_surf MACH_MSM7X25_SURF MSM7X25_SURF 2703
++msm7x25_ffa MACH_MSM7X25_FFA MSM7X25_FFA 2704
++msm7x27_surf MACH_MSM7X27_SURF MSM7X27_SURF 2705
++msm7x27_ffa MACH_MSM7X27_FFA MSM7X27_FFA 2706
++msm7x30_ffa MACH_MSM7X30_FFA MSM7X30_FFA 2707
++qsd8x50_surf MACH_QSD8X50_SURF QSD8X50_SURF 2708
++qsd8x50_comet MACH_QSD8X50_COMET QSD8X50_COMET 2709
++qsd8x50_ffa MACH_QSD8X50_FFA QSD8X50_FFA 2710
++qsd8x50a_surf MACH_QSD8X50A_SURF QSD8X50A_SURF 2711
++qsd8x50a_ffa MACH_QSD8X50A_FFA QSD8X50A_FFA 2712
++adx_xgcp10 MACH_ADX_XGCP10 ADX_XGCP10 2713
++mcgwumts2a MACH_MCGWUMTS2A MCGWUMTS2A 2714
++mobikt MACH_MOBIKT MOBIKT 2715
++mx53_evk MACH_MX53_EVK MX53_EVK 2716
++igep0030 MACH_IGEP0030 IGEP0030 2717
++axell_h40_h50_ctrl MACH_AXELL_H40_H50_CTRL AXELL_H40_H50_CTRL 2718
++dtcommod MACH_DTCOMMOD DTCOMMOD 2719
++gould MACH_GOULD GOULD 2720
++siberia MACH_SIBERIA SIBERIA 2721
++sbc3530 MACH_SBC3530 SBC3530 2722
++qarm MACH_QARM QARM 2723
++mips MACH_MIPS MIPS 2724
++mx27grb MACH_MX27GRB MX27GRB 2725
++sbc8100 MACH_SBC8100 SBC8100 2726
++saarb MACH_SAARB SAARB 2727
++omap3mini MACH_OMAP3MINI OMAP3MINI 2728
++cnmbook7se MACH_CNMBOOK7SE CNMBOOK7SE 2729
++catan MACH_CATAN CATAN 2730
++harmony MACH_HARMONY HARMONY 2731
++tonga MACH_TONGA TONGA 2732
++cybook_orizon MACH_CYBOOK_ORIZON CYBOOK_ORIZON 2733
++htcrhodiumcdma MACH_HTCRHODIUMCDMA HTCRHODIUMCDMA 2734
++epc_g45 MACH_EPC_G45 EPC_G45 2735
++epc_lpc3250 MACH_EPC_LPC3250 EPC_LPC3250 2736
++mxc91341evb MACH_MXC91341EVB MXC91341EVB 2737
++rtw1000 MACH_RTW1000 RTW1000 2738
++bobcat MACH_BOBCAT BOBCAT 2739
++trizeps6 MACH_TRIZEPS6 TRIZEPS6 2740
++msm7x30_fluid MACH_MSM7X30_FLUID MSM7X30_FLUID 2741
++nedap9263 MACH_NEDAP9263 NEDAP9263 2742
++netgear_ms2110 MACH_NETGEAR_MS2110 NETGEAR_MS2110 2743
++bmx MACH_BMX BMX 2744
++netstream MACH_NETSTREAM NETSTREAM 2745
++vpnext_rcu MACH_VPNEXT_RCU VPNEXT_RCU 2746
++vpnext_mpu MACH_VPNEXT_MPU VPNEXT_MPU 2747
++bcmring_tablet_v1 MACH_BCMRING_TABLET_V1 BCMRING_TABLET_V1 2748
++sgarm10 MACH_SGARM10 SGARM10 2749
++cm_t3517 MACH_CM_T3517 CM_T3517 2750
++omap3_cps MACH_OMAP3_CPS OMAP3_CPS 2751
++axar1500_receiver MACH_AXAR1500_RECEIVER AXAR1500_RECEIVER 2752
++wbd222 MACH_WBD222 WBD222 2753
++mt65xx MACH_MT65XX MT65XX 2754
++msm8x60_surf MACH_MSM8X60_SURF MSM8X60_SURF 2755
++msm8x60_sim MACH_MSM8X60_SIM MSM8X60_SIM 2756
++vmc300 MACH_VMC300 VMC300 2757
++tcc8000_sdk MACH_TCC8000_SDK TCC8000_SDK 2758
++nanos MACH_NANOS NANOS 2759
++stamp9g10 MACH_STAMP9G10 STAMP9G10 2760
++stamp9g45 MACH_STAMP9G45 STAMP9G45 2761
++h6053 MACH_H6053 H6053 2762
++smint01 MACH_SMINT01 SMINT01 2763
++prtlvt2 MACH_PRTLVT2 PRTLVT2 2764
++ap420 MACH_AP420 AP420 2765
++htcshift MACH_HTCSHIFT HTCSHIFT 2766
++davinci_dm365_fc MACH_DAVINCI_DM365_FC DAVINCI_DM365_FC 2767
++msm8x55_surf MACH_MSM8X55_SURF MSM8X55_SURF 2768
++msm8x55_ffa MACH_MSM8X55_FFA MSM8X55_FFA 2769
++esl_vamana MACH_ESL_VAMANA ESL_VAMANA 2770
++sbc35 MACH_SBC35 SBC35 2771
++mpx6446 MACH_MPX6446 MPX6446 2772
++oreo_controller MACH_OREO_CONTROLLER OREO_CONTROLLER 2773
++kopin_models MACH_KOPIN_MODELS KOPIN_MODELS 2774
++ttc_vision2 MACH_TTC_VISION2 TTC_VISION2 2775
++cns3420vb MACH_CNS3420VB CNS3420VB 2776
++lpc2 MACH_LPC2 LPC2 2777
++olympus MACH_OLYMPUS OLYMPUS 2778
++vortex MACH_VORTEX VORTEX 2779
++s5pc200 MACH_S5PC200 S5PC200 2780
++ecucore_9263 MACH_ECUCORE_9263 ECUCORE_9263 2781
++smdkc200 MACH_SMDKC200 SMDKC200 2782
++emsiso_sx27 MACH_EMSISO_SX27 EMSISO_SX27 2783
++apx_som9g45_ek MACH_APX_SOM9G45_EK APX_SOM9G45_EK 2784
++songshan MACH_SONGSHAN SONGSHAN 2785
++tianshan MACH_TIANSHAN TIANSHAN 2786
++vpx500 MACH_VPX500 VPX500 2787
++am3517sam MACH_AM3517SAM AM3517SAM 2788
++skat91_sim508 MACH_SKAT91_SIM508 SKAT91_SIM508 2789
++skat91_s3e MACH_SKAT91_S3E SKAT91_S3E 2790
++omap4_panda MACH_OMAP4_PANDA OMAP4_PANDA 2791
++df7220 MACH_DF7220 DF7220 2792
++nemini MACH_NEMINI NEMINI 2793
++t8200 MACH_T8200 T8200 2794
++apf51 MACH_APF51 APF51 2795
++dr_rc_unit MACH_DR_RC_UNIT DR_RC_UNIT 2796
++bordeaux MACH_BORDEAUX BORDEAUX 2797
++catania_b MACH_CATANIA_B CATANIA_B 2798
++mx51_ocean MACH_MX51_OCEAN MX51_OCEAN 2799
++ti8168evm MACH_TI8168EVM TI8168EVM 2800
++neocoreomap MACH_NEOCOREOMAP NEOCOREOMAP 2801
++withings_wbp MACH_WITHINGS_WBP WITHINGS_WBP 2802
++dbps MACH_DBPS DBPS 2803
++sbc9261 MACH_SBC9261 SBC9261 2804
++pcbfp0001 MACH_PCBFP0001 PCBFP0001 2805
++speedy MACH_SPEEDY SPEEDY 2806
++chrysaor MACH_CHRYSAOR CHRYSAOR 2807
++tango MACH_TANGO TANGO 2808
++synology_dsx11 MACH_SYNOLOGY_DSX11 SYNOLOGY_DSX11 2809
++hanlin_v3ext MACH_HANLIN_V3EXT HANLIN_V3EXT 2810
++hanlin_v5 MACH_HANLIN_V5 HANLIN_V5 2811
++hanlin_v3plus MACH_HANLIN_V3PLUS HANLIN_V3PLUS 2812
++iriver_story MACH_IRIVER_STORY IRIVER_STORY 2813
++irex_iliad MACH_IREX_ILIAD IREX_ILIAD 2814
++irex_dr1000 MACH_IREX_DR1000 IREX_DR1000 2815
++teton_bga MACH_TETON_BGA TETON_BGA 2816
++snapper9g45 MACH_SNAPPER9G45 SNAPPER9G45 2817
++tam3517 MACH_TAM3517 TAM3517 2818
++pdc100 MACH_PDC100 PDC100 2819
++eukrea_cpuimx25sd MACH_EUKREA_CPUIMX25 EUKREA_CPUIMX25 2820
++eukrea_cpuimx35sd MACH_EUKREA_CPUIMX35 EUKREA_CPUIMX35 2821
++eukrea_cpuimx51sd MACH_EUKREA_CPUIMX51SD EUKREA_CPUIMX51SD 2822
++eukrea_cpuimx51 MACH_EUKREA_CPUIMX51 EUKREA_CPUIMX51 2823
++p565 MACH_P565 P565 2824
++acer_a4 MACH_ACER_A4 ACER_A4 2825
++davinci_dm368_bip MACH_DAVINCI_DM368_BIP DAVINCI_DM368_BIP 2826
++eshare MACH_ESHARE ESHARE 2827
++hw_omapl138_europa MACH_HW_OMAPL138_EUROPA HW_OMAPL138_EUROPA 2828
++wlbargn MACH_WLBARGN WLBARGN 2829
++bm170 MACH_BM170 BM170 2830
++netspace_mini_v2 MACH_NETSPACE_MINI_V2 NETSPACE_MINI_V2 2831
++netspace_plug_v2 MACH_NETSPACE_PLUG_V2 NETSPACE_PLUG_V2 2832
++siemens_l1 MACH_SIEMENS_L1 SIEMENS_L1 2833
++elv_lcu1 MACH_ELV_LCU1 ELV_LCU1 2834
++mcu1 MACH_MCU1 MCU1 2835
++omap3_tao3530 MACH_OMAP3_TAO3530 OMAP3_TAO3530 2836
++omap3_pcutouch MACH_OMAP3_PCUTOUCH OMAP3_PCUTOUCH 2837
++smdkc210 MACH_SMDKC210 SMDKC210 2838
++omap3_braillo MACH_OMAP3_BRAILLO OMAP3_BRAILLO 2839
++spyplug MACH_SPYPLUG SPYPLUG 2840
++ginger MACH_GINGER GINGER 2841
++tny_t3530 MACH_TNY_T3530 TNY_T3530 2842
++pca102 MACH_PCA102 PCA102 2843
++spade MACH_SPADE SPADE 2844
++mxc25_topaz MACH_MXC25_TOPAZ MXC25_TOPAZ 2845
++t5325 MACH_T5325 T5325 2846
++gw2361 MACH_GW2361 GW2361 2847
++elog MACH_ELOG ELOG 2848
++income MACH_INCOME INCOME 2849
++bcm589x MACH_BCM589X BCM589X 2850
++etna MACH_ETNA ETNA 2851
++hawks MACH_HAWKS HAWKS 2852
++meson MACH_MESON MESON 2853
++xsbase255 MACH_XSBASE255 XSBASE255 2854
++pvm2030 MACH_PVM2030 PVM2030 2855
++mioa502 MACH_MIOA502 MIOA502 2856
++vvbox_sdorig2 MACH_VVBOX_SDORIG2 VVBOX_SDORIG2 2857
++vvbox_sdlite2 MACH_VVBOX_SDLITE2 VVBOX_SDLITE2 2858
++vvbox_sdpro4 MACH_VVBOX_SDPRO4 VVBOX_SDPRO4 2859
++htc_spv_m700 MACH_HTC_SPV_M700 HTC_SPV_M700 2860
++mx257sx MACH_MX257SX MX257SX 2861
++goni MACH_GONI GONI 2862
++msm8x55_svlte_ffa MACH_MSM8X55_SVLTE_FFA MSM8X55_SVLTE_FFA 2863
++msm8x55_svlte_surf MACH_MSM8X55_SVLTE_SURF MSM8X55_SVLTE_SURF 2864
++quickstep MACH_QUICKSTEP QUICKSTEP 2865
++dmw96 MACH_DMW96 DMW96 2866
++hammerhead MACH_HAMMERHEAD HAMMERHEAD 2867
++trident MACH_TRIDENT TRIDENT 2868
++lightning MACH_LIGHTNING LIGHTNING 2869
++iconnect MACH_ICONNECT ICONNECT 2870
++autobot MACH_AUTOBOT AUTOBOT 2871
++coconut MACH_COCONUT COCONUT 2872
++durian MACH_DURIAN DURIAN 2873
++cayenne MACH_CAYENNE CAYENNE 2874
++fuji MACH_FUJI FUJI 2875
++synology_6282 MACH_SYNOLOGY_6282 SYNOLOGY_6282 2876
++em1sy MACH_EM1SY EM1SY 2877
++m502 MACH_M502 M502 2878
++matrix518 MACH_MATRIX518 MATRIX518 2879
++tiny_gurnard MACH_TINY_GURNARD TINY_GURNARD 2880
++spear1310 MACH_SPEAR1310 SPEAR1310 2881
++bv07 MACH_BV07 BV07 2882
++mxt_td61 MACH_MXT_TD61 MXT_TD61 2883
++openrd_ultimate MACH_OPENRD_ULTIMATE OPENRD_ULTIMATE 2884
++devixp MACH_DEVIXP DEVIXP 2885
++miccpt MACH_MICCPT MICCPT 2886
++mic256 MACH_MIC256 MIC256 2887
++as1167 MACH_AS1167 AS1167 2888
++omap3_ibiza MACH_OMAP3_IBIZA OMAP3_IBIZA 2889
++u5500 MACH_U5500 U5500 2890
++davinci_picto MACH_DAVINCI_PICTO DAVINCI_PICTO 2891
++mecha MACH_MECHA MECHA 2892
++bubba3 MACH_BUBBA3 BUBBA3 2893
++pupitre MACH_PUPITRE PUPITRE 2894
++tegra_harmony MACH_TEGRA_HARMONY TEGRA_HARMONY 2895
++tegra_vogue MACH_TEGRA_VOGUE TEGRA_VOGUE 2896
++tegra_e1165 MACH_TEGRA_E1165 TEGRA_E1165 2897
++simplenet MACH_SIMPLENET SIMPLENET 2898
++ec4350tbm MACH_EC4350TBM EC4350TBM 2899
++pec_tc MACH_PEC_TC PEC_TC 2900
++pec_hc2 MACH_PEC_HC2 PEC_HC2 2901
++esl_mobilis_a MACH_ESL_MOBILIS_A ESL_MOBILIS_A 2902
++esl_mobilis_b MACH_ESL_MOBILIS_B ESL_MOBILIS_B 2903
++esl_wave_a MACH_ESL_WAVE_A ESL_WAVE_A 2904
++esl_wave_b MACH_ESL_WAVE_B ESL_WAVE_B 2905
++unisense_mmm MACH_UNISENSE_MMM UNISENSE_MMM 2906
++blueshark MACH_BLUESHARK BLUESHARK 2907
++e10 MACH_E10 E10 2908
++app3k_robin MACH_APP3K_ROBIN APP3K_ROBIN 2909
++pov15hd MACH_POV15HD POV15HD 2910
++stella MACH_STELLA STELLA 2911
++linkstation_lschl MACH_LINKSTATION_LSCHL LINKSTATION_LSCHL 2913
++netwalker MACH_NETWALKER NETWALKER 2914
++acsx106 MACH_ACSX106 ACSX106 2915
++atlas5_c1 MACH_ATLAS5_C1 ATLAS5_C1 2916
++nsb3ast MACH_NSB3AST NSB3AST 2917
++gnet_slc MACH_GNET_SLC GNET_SLC 2918
++af4000 MACH_AF4000 AF4000 2919
++ark9431 MACH_ARK9431 ARK9431 2920
++fs_s5pc100 MACH_FS_S5PC100 FS_S5PC100 2921
++omap3505nova8 MACH_OMAP3505NOVA8 OMAP3505NOVA8 2922
++omap3621_edp1 MACH_OMAP3621_EDP1 OMAP3621_EDP1 2923
++oratisaes MACH_ORATISAES ORATISAES 2924
++smdkv310 MACH_SMDKV310 SMDKV310 2925
++siemens_l0 MACH_SIEMENS_L0 SIEMENS_L0 2926
++ventana MACH_VENTANA VENTANA 2927
++wm8505_7in_netbook MACH_WM8505_7IN_NETBOOK WM8505_7IN_NETBOOK 2928
++ec4350sdb MACH_EC4350SDB EC4350SDB 2929
++mimas MACH_MIMAS MIMAS 2930
++titan MACH_TITAN TITAN 2931
++craneboard MACH_CRANEBOARD CRANEBOARD 2932
++es2440 MACH_ES2440 ES2440 2933
++najay_a9263 MACH_NAJAY_A9263 NAJAY_A9263 2934
++htctornado MACH_HTCTORNADO HTCTORNADO 2935
++dimm_mx257 MACH_DIMM_MX257 DIMM_MX257 2936
++jigen301 MACH_JIGEN JIGEN 2937
++smdk6450 MACH_SMDK6450 SMDK6450 2938
++meno_qng MACH_MENO_QNG MENO_QNG 2939
++ns2416 MACH_NS2416 NS2416 2940
++rpc353 MACH_RPC353 RPC353 2941
++tq6410 MACH_TQ6410 TQ6410 2942
++sky6410 MACH_SKY6410 SKY6410 2943
++dynasty MACH_DYNASTY DYNASTY 2944
++vivo MACH_VIVO VIVO 2945
++bury_bl7582 MACH_BURY_BL7582 BURY_BL7582 2946
++bury_bps5270 MACH_BURY_BPS5270 BURY_BPS5270 2947
++basi MACH_BASI BASI 2948
++tn200 MACH_TN200 TN200 2949
++c2mmi MACH_C2MMI C2MMI 2950
++meson_6236m MACH_MESON_6236M MESON_6236M 2951
++meson_8626m MACH_MESON_8626M MESON_8626M 2952
++tube MACH_TUBE TUBE 2953
++messina MACH_MESSINA MESSINA 2954
++mx50_arm2 MACH_MX50_ARM2 MX50_ARM2 2955
++cetus9263 MACH_CETUS9263 CETUS9263 2956
++brownstone MACH_BROWNSTONE BROWNSTONE 2957
++vmx25 MACH_VMX25 VMX25 2958
++vmx51 MACH_VMX51 VMX51 2959
++abacus MACH_ABACUS ABACUS 2960
++cm4745 MACH_CM4745 CM4745 2961
++oratislink MACH_ORATISLINK ORATISLINK 2962
++davinci_dm365_dvr MACH_DAVINCI_DM365_DVR DAVINCI_DM365_DVR 2963
++netviz MACH_NETVIZ NETVIZ 2964
++flexibity MACH_FLEXIBITY FLEXIBITY 2965
++wlan_computer MACH_WLAN_COMPUTER WLAN_COMPUTER 2966
+diff -rupN linux-2.6.35.11/arch/arm/tools/mach-types.orig linux-2.6.35.11-ts7500/arch/arm/tools/mach-types.orig
+--- linux-2.6.35.11/arch/arm/tools/mach-types.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/arch/arm/tools/mach-types.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,2952 @@
++# Database of machine macros and numbers
++#
++# This file is linux/arch/arm/tools/mach-types
++#
++# Up to date versions of this file can be obtained from:
++#
++# http://www.arm.linux.org.uk/developer/machines/download.php
++#
++# Please do not send patches to this file; it is automatically generated!
++# To add an entry into this database, please see Documentation/arm/README,
++# or visit:
++#
++# http://www.arm.linux.org.uk/developer/machines/?action=new
++#
++# Last update: Mon Jul 12 21:10:14 2010
++#
++# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
++#
++ebsa110 ARCH_EBSA110 EBSA110 0
++riscpc ARCH_RPC RISCPC 1
++nexuspci ARCH_NEXUSPCI NEXUSPCI 3
++ebsa285 ARCH_EBSA285 EBSA285 4
++netwinder ARCH_NETWINDER NETWINDER 5
++cats ARCH_CATS CATS 6
++tbox ARCH_TBOX TBOX 7
++co285 ARCH_CO285 CO285 8
++clps7110 ARCH_CLPS7110 CLPS7110 9
++archimedes ARCH_ARC ARCHIMEDES 10
++a5k ARCH_A5K A5K 11
++etoile ARCH_ETOILE ETOILE 12
++lacie_nas ARCH_LACIE_NAS LACIE_NAS 13
++clps7500 ARCH_CLPS7500 CLPS7500 14
++shark ARCH_SHARK SHARK 15
++brutus SA1100_BRUTUS BRUTUS 16
++personal_server ARCH_PERSONAL_SERVER PERSONAL_SERVER 17
++itsy SA1100_ITSY ITSY 18
++l7200 ARCH_L7200 L7200 19
++pleb SA1100_PLEB PLEB 20
++integrator ARCH_INTEGRATOR INTEGRATOR 21
++h3600 SA1100_H3600 H3600 22
++ixp1200 ARCH_IXP1200 IXP1200 23
++p720t ARCH_P720T P720T 24
++assabet SA1100_ASSABET ASSABET 25
++victor SA1100_VICTOR VICTOR 26
++lart SA1100_LART LART 27
++ranger SA1100_RANGER RANGER 28
++graphicsclient SA1100_GRAPHICSCLIENT GRAPHICSCLIENT 29
++xp860 SA1100_XP860 XP860 30
++cerf SA1100_CERF CERF 31
++nanoengine SA1100_NANOENGINE NANOENGINE 32
++fpic SA1100_FPIC FPIC 33
++extenex1 SA1100_EXTENEX1 EXTENEX1 34
++sherman SA1100_SHERMAN SHERMAN 35
++accelent_sa SA1100_ACCELENT ACCELENT_SA 36
++accelent_l7200 ARCH_L7200_ACCELENT ACCELENT_L7200 37
++netport SA1100_NETPORT NETPORT 38
++pangolin SA1100_PANGOLIN PANGOLIN 39
++yopy SA1100_YOPY YOPY 40
++coolidge SA1100_COOLIDGE COOLIDGE 41
++huw_webpanel SA1100_HUW_WEBPANEL HUW_WEBPANEL 42
++spotme ARCH_SPOTME SPOTME 43
++freebird ARCH_FREEBIRD FREEBIRD 44
++ti925 ARCH_TI925 TI925 45
++riscstation ARCH_RISCSTATION RISCSTATION 46
++cavy SA1100_CAVY CAVY 47
++jornada720 SA1100_JORNADA720 JORNADA720 48
++omnimeter SA1100_OMNIMETER OMNIMETER 49
++edb7211 ARCH_EDB7211 EDB7211 50
++citygo SA1100_CITYGO CITYGO 51
++pfs168 SA1100_PFS168 PFS168 52
++spot SA1100_SPOT SPOT 53
++flexanet SA1100_FLEXANET FLEXANET 54
++webpal ARCH_WEBPAL WEBPAL 55
++linpda SA1100_LINPDA LINPDA 56
++anakin ARCH_ANAKIN ANAKIN 57
++mvi SA1100_MVI MVI 58
++jupiter SA1100_JUPITER JUPITER 59
++psionw ARCH_PSIONW PSIONW 60
++aln SA1100_ALN ALN 61
++epxa ARCH_CAMELOT CAMELOT 62
++gds2200 SA1100_GDS2200 GDS2200 63
++netbook SA1100_PSION_SERIES7 PSION_SERIES7 64
++xfile SA1100_XFILE XFILE 65
++accelent_ep9312 ARCH_ACCELENT_EP9312 ACCELENT_EP9312 66
++ic200 ARCH_IC200 IC200 67
++creditlart SA1100_CREDITLART CREDITLART 68
++htm SA1100_HTM HTM 69
++iq80310 ARCH_IQ80310 IQ80310 70
++freebot SA1100_FREEBOT FREEBOT 71
++entel ARCH_ENTEL ENTEL 72
++enp3510 ARCH_ENP3510 ENP3510 73
++trizeps SA1100_TRIZEPS TRIZEPS 74
++nesa SA1100_NESA NESA 75
++venus ARCH_VENUS VENUS 76
++tardis ARCH_TARDIS TARDIS 77
++mercury ARCH_MERCURY MERCURY 78
++empeg SA1100_EMPEG EMPEG 79
++adi_evb ARCH_I80200FCC I80200FCC 80
++itt_cpb SA1100_ITT_CPB ITT_CPB 81
++svc SA1100_SVC SVC 82
++alpha2 SA1100_ALPHA2 ALPHA2 84
++alpha1 SA1100_ALPHA1 ALPHA1 85
++netarm ARCH_NETARM NETARM 86
++simpad SA1100_SIMPAD SIMPAD 87
++pda1 ARCH_PDA1 PDA1 88
++lubbock ARCH_LUBBOCK LUBBOCK 89
++aniko ARCH_ANIKO ANIKO 90
++clep7212 ARCH_CLEP7212 CLEP7212 91
++cs89712 ARCH_CS89712 CS89712 92
++weararm SA1100_WEARARM WEARARM 93
++possio_px SA1100_POSSIO_PX POSSIO_PX 94
++sidearm SA1100_SIDEARM SIDEARM 95
++stork SA1100_STORK STORK 96
++shannon SA1100_SHANNON SHANNON 97
++ace ARCH_ACE ACE 98
++ballyarm SA1100_BALLYARM BALLYARM 99
++simputer SA1100_SIMPUTER SIMPUTER 100
++nexterm SA1100_NEXTERM NEXTERM 101
++sa1100_elf SA1100_SA1100_ELF SA1100_ELF 102
++gator SA1100_GATOR GATOR 103
++granite ARCH_GRANITE GRANITE 104
++consus SA1100_CONSUS CONSUS 105
++aaed2000 ARCH_AAED2000 AAED2000 106
++cdb89712 ARCH_CDB89712 CDB89712 107
++graphicsmaster SA1100_GRAPHICSMASTER GRAPHICSMASTER 108
++adsbitsy SA1100_ADSBITSY ADSBITSY 109
++pxa_idp ARCH_PXA_IDP PXA_IDP 110
++plce ARCH_PLCE PLCE 111
++pt_system3 SA1100_PT_SYSTEM3 PT_SYSTEM3 112
++murphy ARCH_MEDALB MEDALB 113
++eagle ARCH_EAGLE EAGLE 114
++dsc21 ARCH_DSC21 DSC21 115
++dsc24 ARCH_DSC24 DSC24 116
++ti5472 ARCH_TI5472 TI5472 117
++autcpu12 ARCH_AUTCPU12 AUTCPU12 118
++uengine ARCH_UENGINE UENGINE 119
++bluestem SA1100_BLUESTEM BLUESTEM 120
++xingu8 ARCH_XINGU8 XINGU8 121
++bushstb ARCH_BUSHSTB BUSHSTB 122
++epsilon1 SA1100_EPSILON1 EPSILON1 123
++balloon SA1100_BALLOON BALLOON 124
++puppy ARCH_PUPPY PUPPY 125
++elroy SA1100_ELROY ELROY 126
++gms720 ARCH_GMS720 GMS720 127
++s24x ARCH_S24X S24X 128
++jtel_clep7312 ARCH_JTEL_CLEP7312 JTEL_CLEP7312 129
++cx821xx ARCH_CX821XX CX821XX 130
++edb7312 ARCH_EDB7312 EDB7312 131
++bsa1110 SA1100_BSA1110 BSA1110 132
++powerpin ARCH_POWERPIN POWERPIN 133
++openarm ARCH_OPENARM OPENARM 134
++whitechapel SA1100_WHITECHAPEL WHITECHAPEL 135
++h3100 SA1100_H3100 H3100 136
++h3800 SA1100_H3800 H3800 137
++blue_v1 ARCH_BLUE_V1 BLUE_V1 138
++pxa_cerf ARCH_PXA_CERF PXA_CERF 139
++arm7tevb ARCH_ARM7TEVB ARM7TEVB 140
++d7400 SA1100_D7400 D7400 141
++piranha ARCH_PIRANHA PIRANHA 142
++sbcamelot SA1100_SBCAMELOT SBCAMELOT 143
++kings SA1100_KINGS KINGS 144
++smdk2400 ARCH_SMDK2400 SMDK2400 145
++collie SA1100_COLLIE COLLIE 146
++idr ARCH_IDR IDR 147
++badge4 SA1100_BADGE4 BADGE4 148
++webnet ARCH_WEBNET WEBNET 149
++d7300 SA1100_D7300 D7300 150
++cep SA1100_CEP CEP 151
++fortunet ARCH_FORTUNET FORTUNET 152
++vc547x ARCH_VC547X VC547X 153
++filewalker SA1100_FILEWALKER FILEWALKER 154
++netgateway SA1100_NETGATEWAY NETGATEWAY 155
++symbol2800 SA1100_SYMBOL2800 SYMBOL2800 156
++suns SA1100_SUNS SUNS 157
++frodo SA1100_FRODO FRODO 158
++ms301 SA1100_MACH_TYTE_MS301 MACH_TYTE_MS301 159
++mx1ads ARCH_MX1ADS MX1ADS 160
++h7201 ARCH_H7201 H7201 161
++h7202 ARCH_H7202 H7202 162
++amico ARCH_AMICO AMICO 163
++iam SA1100_IAM IAM 164
++tt530 SA1100_TT530 TT530 165
++sam2400 ARCH_SAM2400 SAM2400 166
++jornada56x SA1100_JORNADA56X JORNADA56X 167
++active SA1100_ACTIVE ACTIVE 168
++iq80321 ARCH_IQ80321 IQ80321 169
++wid SA1100_WID WID 170
++sabinal ARCH_SABINAL SABINAL 171
++ixp425_matacumbe ARCH_IXP425_MATACUMBE IXP425_MATACUMBE 172
++miniprint SA1100_MINIPRINT MINIPRINT 173
++adm510x ARCH_ADM510X ADM510X 174
++svs200 SA1100_SVS200 SVS200 175
++atg_tcu ARCH_ATG_TCU ATG_TCU 176
++jornada820 SA1100_JORNADA820 JORNADA820 177
++s3c44b0 ARCH_S3C44B0 S3C44B0 178
++margis2 ARCH_MARGIS2 MARGIS2 179
++ks8695 ARCH_KS8695 KS8695 180
++brh ARCH_BRH BRH 181
++s3c2410 ARCH_S3C2410 S3C2410 182
++possio_px30 ARCH_POSSIO_PX30 POSSIO_PX30 183
++s3c2800 ARCH_S3C2800 S3C2800 184
++fleetwood SA1100_FLEETWOOD FLEETWOOD 185
++omaha ARCH_OMAHA OMAHA 186
++ta7 ARCH_TA7 TA7 187
++nova SA1100_NOVA NOVA 188
++hmk ARCH_HMK HMK 189
++karo ARCH_KARO KARO 190
++fester SA1100_FESTER FESTER 191
++gpi ARCH_GPI GPI 192
++smdk2410 ARCH_SMDK2410 SMDK2410 193
++i519 ARCH_I519 I519 194
++nexio SA1100_NEXIO NEXIO 195
++bitbox SA1100_BITBOX BITBOX 196
++g200 SA1100_G200 G200 197
++gill SA1100_GILL GILL 198
++pxa_mercury ARCH_PXA_MERCURY PXA_MERCURY 199
++ceiva ARCH_CEIVA CEIVA 200
++fret SA1100_FRET FRET 201
++emailphone SA1100_EMAILPHONE EMAILPHONE 202
++h3900 ARCH_H3900 H3900 203
++pxa1 ARCH_PXA1 PXA1 204
++koan369 SA1100_KOAN369 KOAN369 205
++cogent ARCH_COGENT COGENT 206
++esl_simputer ARCH_ESL_SIMPUTER ESL_SIMPUTER 207
++esl_simputer_clr ARCH_ESL_SIMPUTER_CLR ESL_SIMPUTER_CLR 208
++esl_simputer_bw ARCH_ESL_SIMPUTER_BW ESL_SIMPUTER_BW 209
++hhp_cradle ARCH_HHP_CRADLE HHP_CRADLE 210
++he500 ARCH_HE500 HE500 211
++inhandelf2 SA1100_INHANDELF2 INHANDELF2 212
++inhandftip SA1100_INHANDFTIP INHANDFTIP 213
++dnp1110 SA1100_DNP1110 DNP1110 214
++pnp1110 SA1100_PNP1110 PNP1110 215
++csb226 ARCH_CSB226 CSB226 216
++arnold SA1100_ARNOLD ARNOLD 217
++voiceblue MACH_VOICEBLUE VOICEBLUE 218
++jz8028 ARCH_JZ8028 JZ8028 219
++h5400 ARCH_H5400 H5400 220
++forte SA1100_FORTE FORTE 221
++acam SA1100_ACAM ACAM 222
++abox SA1100_ABOX ABOX 223
++atmel ARCH_ATMEL ATMEL 224
++sitsang ARCH_SITSANG SITSANG 225
++cpu1110lcdnet SA1100_CPU1110LCDNET CPU1110LCDNET 226
++mpl_vcma9 ARCH_MPL_VCMA9 MPL_VCMA9 227
++opus_a1 ARCH_OPUS_A1 OPUS_A1 228
++daytona ARCH_DAYTONA DAYTONA 229
++killbear SA1100_KILLBEAR KILLBEAR 230
++yoho ARCH_YOHO YOHO 231
++jasper ARCH_JASPER JASPER 232
++dsc25 ARCH_DSC25 DSC25 233
++omap_innovator MACH_OMAP_INNOVATOR OMAP_INNOVATOR 234
++mnci ARCH_RAMSES RAMSES 235
++s28x ARCH_S28X S28X 236
++mport3 ARCH_MPORT3 MPORT3 237
++pxa_eagle250 ARCH_PXA_EAGLE250 PXA_EAGLE250 238
++pdb ARCH_PDB PDB 239
++blue_2g SA1100_BLUE_2G BLUE_2G 240
++bluearch SA1100_BLUEARCH BLUEARCH 241
++ixdp2400 ARCH_IXDP2400 IXDP2400 242
++ixdp2800 ARCH_IXDP2800 IXDP2800 243
++explorer SA1100_EXPLORER EXPLORER 244
++ixdp425 ARCH_IXDP425 IXDP425 245
++chimp ARCH_CHIMP CHIMP 246
++stork_nest ARCH_STORK_NEST STORK_NEST 247
++stork_egg ARCH_STORK_EGG STORK_EGG 248
++wismo SA1100_WISMO WISMO 249
++ezlinx ARCH_EZLINX EZLINX 250
++at91rm9200 ARCH_AT91RM9200 AT91RM9200 251
++adtech_orion ARCH_ADTECH_ORION ADTECH_ORION 252
++neptune ARCH_NEPTUNE NEPTUNE 253
++hackkit SA1100_HACKKIT HACKKIT 254
++pxa_wins30 ARCH_PXA_WINS30 PXA_WINS30 255
++lavinna SA1100_LAVINNA LAVINNA 256
++pxa_uengine ARCH_PXA_UENGINE PXA_UENGINE 257
++innokom ARCH_INNOKOM INNOKOM 258
++bms ARCH_BMS BMS 259
++ixcdp1100 ARCH_IXCDP1100 IXCDP1100 260
++prpmc1100 ARCH_PRPMC1100 PRPMC1100 261
++at91rm9200dk ARCH_AT91RM9200DK AT91RM9200DK 262
++armstick ARCH_ARMSTICK ARMSTICK 263
++armonie ARCH_ARMONIE ARMONIE 264
++mport1 ARCH_MPORT1 MPORT1 265
++s3c5410 ARCH_S3C5410 S3C5410 266
++zcp320a ARCH_ZCP320A ZCP320A 267
++i_box ARCH_I_BOX I_BOX 268
++stlc1502 ARCH_STLC1502 STLC1502 269
++siren ARCH_SIREN SIREN 270
++greenlake ARCH_GREENLAKE GREENLAKE 271
++argus ARCH_ARGUS ARGUS 272
++combadge SA1100_COMBADGE COMBADGE 273
++rokepxa ARCH_ROKEPXA ROKEPXA 274
++cintegrator ARCH_CINTEGRATOR CINTEGRATOR 275
++guidea07 ARCH_GUIDEA07 GUIDEA07 276
++tat257 ARCH_TAT257 TAT257 277
++igp2425 ARCH_IGP2425 IGP2425 278
++bluegrama ARCH_BLUEGRAMMA BLUEGRAMMA 279
++ipod ARCH_IPOD IPOD 280
++adsbitsyx ARCH_ADSBITSYX ADSBITSYX 281
++trizeps2 ARCH_TRIZEPS2 TRIZEPS2 282
++viper ARCH_VIPER VIPER 283
++adsbitsyplus SA1100_ADSBITSYPLUS ADSBITSYPLUS 284
++adsagc SA1100_ADSAGC ADSAGC 285
++stp7312 ARCH_STP7312 STP7312 286
++nx_phnx MACH_NX_PHNX NX_PHNX 287
++wep_ep250 ARCH_WEP_EP250 WEP_EP250 288
++inhandelf3 ARCH_INHANDELF3 INHANDELF3 289
++adi_coyote ARCH_ADI_COYOTE ADI_COYOTE 290
++iyonix ARCH_IYONIX IYONIX 291
++damicam1 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292
++meg03 ARCH_MEG03 MEG03 293
++pxa_whitechapel ARCH_PXA_WHITECHAPEL PXA_WHITECHAPEL 294
++nwsc ARCH_NWSC NWSC 295
++nwlarm ARCH_NWLARM NWLARM 296
++ixp425_mguard ARCH_IXP425_MGUARD IXP425_MGUARD 297
++pxa_netdcu4 ARCH_PXA_NETDCU4 PXA_NETDCU4 298
++ixdp2401 ARCH_IXDP2401 IXDP2401 299
++ixdp2801 ARCH_IXDP2801 IXDP2801 300
++zodiac ARCH_ZODIAC ZODIAC 301
++armmodul ARCH_ARMMODUL ARMMODUL 302
++ketop SA1100_KETOP KETOP 303
++av7200 ARCH_AV7200 AV7200 304
++arch_ti925 ARCH_ARCH_TI925 ARCH_TI925 305
++acq200 ARCH_ACQ200 ACQ200 306
++pt_dafit SA1100_PT_DAFIT PT_DAFIT 307
++ihba ARCH_IHBA IHBA 308
++quinque ARCH_QUINQUE QUINQUE 309
++nimbraone ARCH_NIMBRAONE NIMBRAONE 310
++nimbra29x ARCH_NIMBRA29X NIMBRA29X 311
++nimbra210 ARCH_NIMBRA210 NIMBRA210 312
++hhp_d95xx ARCH_HHP_D95XX HHP_D95XX 313
++labarm ARCH_LABARM LABARM 314
++m825xx ARCH_M825XX M825XX 315
++m7100 SA1100_M7100 M7100 316
++nipc2 ARCH_NIPC2 NIPC2 317
++fu7202 ARCH_FU7202 FU7202 318
++adsagx ARCH_ADSAGX ADSAGX 319
++pxa_pooh ARCH_PXA_POOH PXA_POOH 320
++bandon ARCH_BANDON BANDON 321
++pcm7210 ARCH_PCM7210 PCM7210 322
++nms9200 ARCH_NMS9200 NMS9200 323
++logodl ARCH_LOGODL LOGODL 324
++m7140 SA1100_M7140 M7140 325
++korebot ARCH_KOREBOT KOREBOT 326
++iq31244 ARCH_IQ31244 IQ31244 327
++koan393 SA1100_KOAN393 KOAN393 328
++inhandftip3 ARCH_INHANDFTIP3 INHANDFTIP3 329
++gonzo ARCH_GONZO GONZO 330
++bast ARCH_BAST BAST 331
++scanpass ARCH_SCANPASS SCANPASS 332
++ep7312_pooh ARCH_EP7312_POOH EP7312_POOH 333
++ta7s ARCH_TA7S TA7S 334
++ta7v ARCH_TA7V TA7V 335
++icarus SA1100_ICARUS ICARUS 336
++h1900 ARCH_H1900 H1900 337
++gemini SA1100_GEMINI GEMINI 338
++axim ARCH_AXIM AXIM 339
++audiotron ARCH_AUDIOTRON AUDIOTRON 340
++h2200 ARCH_H2200 H2200 341
++loox600 ARCH_LOOX600 LOOX600 342
++niop ARCH_NIOP NIOP 343
++dm310 ARCH_DM310 DM310 344
++seedpxa_c2 ARCH_SEEDPXA_C2 SEEDPXA_C2 345
++ixp4xx_mguardpci ARCH_IXP4XX_MGUARD_PCI IXP4XX_MGUARD_PCI 346
++h1940 ARCH_H1940 H1940 347
++scorpio ARCH_SCORPIO SCORPIO 348
++viva ARCH_VIVA VIVA 349
++pxa_xcard ARCH_PXA_XCARD PXA_XCARD 350
++csb335 ARCH_CSB335 CSB335 351
++ixrd425 ARCH_IXRD425 IXRD425 352
++iq80315 ARCH_IQ80315 IQ80315 353
++nmp7312 ARCH_NMP7312 NMP7312 354
++cx861xx ARCH_CX861XX CX861XX 355
++enp2611 ARCH_ENP2611 ENP2611 356
++xda SA1100_XDA XDA 357
++csir_ims ARCH_CSIR_IMS CSIR_IMS 358
++ixp421_dnaeeth ARCH_IXP421_DNAEETH IXP421_DNAEETH 359
++pocketserv9200 ARCH_POCKETSERV9200 POCKETSERV9200 360
++toto ARCH_TOTO TOTO 361
++s3c2440 ARCH_S3C2440 S3C2440 362
++ks8695p ARCH_KS8695P KS8695P 363
++se4000 ARCH_SE4000 SE4000 364
++quadriceps ARCH_QUADRICEPS QUADRICEPS 365
++bronco ARCH_BRONCO BRONCO 366
++esl_wireless_tab ARCH_ESL_WIRELESS_TAB ESL_WIRELESS_TAB 367
++esl_sofcomp ARCH_ESL_SOFCOMP ESL_SOFCOMP 368
++s5c7375 ARCH_S5C7375 S5C7375 369
++spearhead ARCH_SPEARHEAD SPEARHEAD 370
++pantera ARCH_PANTERA PANTERA 371
++prayoglite ARCH_PRAYOGLITE PRAYOGLITE 372
++gumstix ARCH_GUMSTIX GUMSTIX 373
++rcube ARCH_RCUBE RCUBE 374
++rea_olv ARCH_REA_OLV REA_OLV 375
++pxa_iphone ARCH_PXA_IPHONE PXA_IPHONE 376
++s3c3410 ARCH_S3C3410 S3C3410 377
++espd_4510b ARCH_ESPD_4510B ESPD_4510B 378
++mp1x ARCH_MP1X MP1X 379
++at91rm9200tb ARCH_AT91RM9200TB AT91RM9200TB 380
++adsvgx ARCH_ADSVGX ADSVGX 381
++omap_h2 MACH_OMAP_H2 OMAP_H2 382
++pelee ARCH_PELEE PELEE 383
++e740 MACH_E740 E740 384
++iq80331 ARCH_IQ80331 IQ80331 385
++versatile_pb ARCH_VERSATILE_PB VERSATILE_PB 387
++kev7a400 MACH_KEV7A400 KEV7A400 388
++lpd7a400 MACH_LPD7A400 LPD7A400 389
++lpd7a404 MACH_LPD7A404 LPD7A404 390
++fujitsu_camelot ARCH_FUJITSU_CAMELOT FUJITSU_CAMELOT 391
++janus2m ARCH_JANUS2M JANUS2M 392
++embtf MACH_EMBTF EMBTF 393
++hpm MACH_HPM HPM 394
++smdk2410tk MACH_SMDK2410TK SMDK2410TK 395
++smdk2410aj MACH_SMDK2410AJ SMDK2410AJ 396
++streetracer MACH_STREETRACER STREETRACER 397
++eframe MACH_EFRAME EFRAME 398
++csb337 MACH_CSB337 CSB337 399
++pxa_lark MACH_PXA_LARK PXA_LARK 400
++pxa_pnp2110 MACH_PNP2110 PNP2110 401
++tcc72x MACH_TCC72X TCC72X 402
++altair MACH_ALTAIR ALTAIR 403
++kc3 MACH_KC3 KC3 404
++sinteftd MACH_SINTEFTD SINTEFTD 405
++mainstone MACH_MAINSTONE MAINSTONE 406
++aday4x MACH_ADAY4X ADAY4X 407
++lite300 MACH_LITE300 LITE300 408
++s5c7376 MACH_S5C7376 S5C7376 409
++mt02 MACH_MT02 MT02 410
++mport3s MACH_MPORT3S MPORT3S 411
++ra_alpha MACH_RA_ALPHA RA_ALPHA 412
++xcep MACH_XCEP XCEP 413
++arcom_vulcan MACH_ARCOM_VULCAN ARCOM_VULCAN 414
++stargate MACH_STARGATE STARGATE 415
++armadilloj MACH_ARMADILLOJ ARMADILLOJ 416
++elroy_jack MACH_ELROY_JACK ELROY_JACK 417
++backend MACH_BACKEND BACKEND 418
++s5linbox MACH_S5LINBOX S5LINBOX 419
++nomadik MACH_NOMADIK NOMADIK 420
++ia_cpu_9200 MACH_IA_CPU_9200 IA_CPU_9200 421
++at91_bja1 MACH_AT91_BJA1 AT91_BJA1 422
++corgi MACH_CORGI CORGI 423
++poodle MACH_POODLE POODLE 424
++ten MACH_TEN TEN 425
++roverp5p MACH_ROVERP5P ROVERP5P 426
++sc2700 MACH_SC2700 SC2700 427
++ex_eagle MACH_EX_EAGLE EX_EAGLE 428
++nx_pxa12 MACH_NX_PXA12 NX_PXA12 429
++nx_pxa5 MACH_NX_PXA5 NX_PXA5 430
++blackboard2 MACH_BLACKBOARD2 BLACKBOARD2 431
++i819 MACH_I819 I819 432
++ixmb995e MACH_IXMB995E IXMB995E 433
++skyrider MACH_SKYRIDER SKYRIDER 434
++skyhawk MACH_SKYHAWK SKYHAWK 435
++enterprise MACH_ENTERPRISE ENTERPRISE 436
++dep2410 MACH_DEP2410 DEP2410 437
++armcore MACH_ARMCORE ARMCORE 438
++hobbit MACH_HOBBIT HOBBIT 439
++h7210 MACH_H7210 H7210 440
++pxa_netdcu5 MACH_PXA_NETDCU5 PXA_NETDCU5 441
++acc MACH_ACC ACC 442
++esl_sarva MACH_ESL_SARVA ESL_SARVA 443
++xm250 MACH_XM250 XM250 444
++t6tc1xb MACH_T6TC1XB T6TC1XB 445
++ess710 MACH_ESS710 ESS710 446
++mx31ads MACH_MX31ADS MX31ADS 447
++himalaya MACH_HIMALAYA HIMALAYA 448
++bolfenk MACH_BOLFENK BOLFENK 449
++at91rm9200kr MACH_AT91RM9200KR AT91RM9200KR 450
++edb9312 MACH_EDB9312 EDB9312 451
++omap_generic MACH_OMAP_GENERIC OMAP_GENERIC 452
++aximx3 MACH_AXIMX3 AXIMX3 453
++eb67xdip MACH_EB67XDIP EB67XDIP 454
++webtxs MACH_WEBTXS WEBTXS 455
++hawk MACH_HAWK HAWK 456
++ccat91sbc001 MACH_CCAT91SBC001 CCAT91SBC001 457
++expresso MACH_EXPRESSO EXPRESSO 458
++h4000 MACH_H4000 H4000 459
++dino MACH_DINO DINO 460
++ml675k MACH_ML675K ML675K 461
++edb9301 MACH_EDB9301 EDB9301 462
++edb9315 MACH_EDB9315 EDB9315 463
++reciva_tt MACH_RECIVA_TT RECIVA_TT 464
++cstcb01 MACH_CSTCB01 CSTCB01 465
++cstcb1 MACH_CSTCB1 CSTCB1 466
++shadwell MACH_SHADWELL SHADWELL 467
++goepel263 MACH_GOEPEL263 GOEPEL263 468
++acq100 MACH_ACQ100 ACQ100 469
++mx1fs2 MACH_MX1FS2 MX1FS2 470
++hiptop_g1 MACH_HIPTOP_G1 HIPTOP_G1 471
++sparky MACH_SPARKY SPARKY 472
++ns9750 MACH_NS9750 NS9750 473
++phoenix MACH_PHOENIX PHOENIX 474
++vr1000 MACH_VR1000 VR1000 475
++deisterpxa MACH_DEISTERPXA DEISTERPXA 476
++bcm1160 MACH_BCM1160 BCM1160 477
++pcm022 MACH_PCM022 PCM022 478
++adsgcx MACH_ADSGCX ADSGCX 479
++dreadnaught MACH_DREADNAUGHT DREADNAUGHT 480
++dm320 MACH_DM320 DM320 481
++markov MACH_MARKOV MARKOV 482
++cos7a400 MACH_COS7A400 COS7A400 483
++milano MACH_MILANO MILANO 484
++ue9328 MACH_UE9328 UE9328 485
++uex255 MACH_UEX255 UEX255 486
++ue2410 MACH_UE2410 UE2410 487
++a620 MACH_A620 A620 488
++ocelot MACH_OCELOT OCELOT 489
++cheetah MACH_CHEETAH CHEETAH 490
++omap_perseus2 MACH_OMAP_PERSEUS2 OMAP_PERSEUS2 491
++zvue MACH_ZVUE ZVUE 492
++roverp1 MACH_ROVERP1 ROVERP1 493
++asidial2 MACH_ASIDIAL2 ASIDIAL2 494
++s3c24a0 MACH_S3C24A0 S3C24A0 495
++e800 MACH_E800 E800 496
++e750 MACH_E750 E750 497
++s3c5500 MACH_S3C5500 S3C5500 498
++smdk5500 MACH_SMDK5500 SMDK5500 499
++signalsync MACH_SIGNALSYNC SIGNALSYNC 500
++nbc MACH_NBC NBC 501
++kodiak MACH_KODIAK KODIAK 502
++netbookpro MACH_NETBOOKPRO NETBOOKPRO 503
++hw90200 MACH_HW90200 HW90200 504
++condor MACH_CONDOR CONDOR 505
++cup MACH_CUP CUP 506
++kite MACH_KITE KITE 507
++scb9328 MACH_SCB9328 SCB9328 508
++omap_h3 MACH_OMAP_H3 OMAP_H3 509
++omap_h4 MACH_OMAP_H4 OMAP_H4 510
++n10 MACH_N10 N10 511
++montejade MACH_MONTAJADE MONTAJADE 512
++sg560 MACH_SG560 SG560 513
++dp1000 MACH_DP1000 DP1000 514
++omap_osk MACH_OMAP_OSK OMAP_OSK 515
++rg100v3 MACH_RG100V3 RG100V3 516
++mx2ads MACH_MX2ADS MX2ADS 517
++pxa_kilo MACH_PXA_KILO PXA_KILO 518
++ixp4xx_eagle MACH_IXP4XX_EAGLE IXP4XX_EAGLE 519
++tosa MACH_TOSA TOSA 520
++mb2520f MACH_MB2520F MB2520F 521
++emc1000 MACH_EMC1000 EMC1000 522
++tidsc25 MACH_TIDSC25 TIDSC25 523
++akcpmxl MACH_AKCPMXL AKCPMXL 524
++av3xx MACH_AV3XX AV3XX 525
++avila MACH_AVILA AVILA 526
++pxa_mpm10 MACH_PXA_MPM10 PXA_MPM10 527
++pxa_kyanite MACH_PXA_KYANITE PXA_KYANITE 528
++sgold MACH_SGOLD SGOLD 529
++oscar MACH_OSCAR OSCAR 530
++epxa4usb2 MACH_EPXA4USB2 EPXA4USB2 531
++xsengine MACH_XSENGINE XSENGINE 532
++ip600 MACH_IP600 IP600 533
++mcan2 MACH_MCAN2 MCAN2 534
++ddi_blueridge MACH_DDI_BLUERIDGE DDI_BLUERIDGE 535
++skyminder MACH_SKYMINDER SKYMINDER 536
++lpd79520 MACH_LPD79520 LPD79520 537
++edb9302 MACH_EDB9302 EDB9302 538
++hw90340 MACH_HW90340 HW90340 539
++cip_box MACH_CIP_BOX CIP_BOX 540
++ivpn MACH_IVPN IVPN 541
++rsoc2 MACH_RSOC2 RSOC2 542
++husky MACH_HUSKY HUSKY 543
++boxer MACH_BOXER BOXER 544
++shepherd MACH_SHEPHERD SHEPHERD 545
++aml42800aa MACH_AML42800AA AML42800AA 546
++lpc2294 MACH_LPC2294 LPC2294 548
++switchgrass MACH_SWITCHGRASS SWITCHGRASS 549
++ens_cmu MACH_ENS_CMU ENS_CMU 550
++mm6_sdb MACH_MM6_SDB MM6_SDB 551
++saturn MACH_SATURN SATURN 552
++i30030evb MACH_I30030EVB I30030EVB 553
++mxc27530evb MACH_MXC27530EVB MXC27530EVB 554
++smdk2800 MACH_SMDK2800 SMDK2800 555
++mtwilson MACH_MTWILSON MTWILSON 556
++ziti MACH_ZITI ZITI 557
++grandfather MACH_GRANDFATHER GRANDFATHER 558
++tengine MACH_TENGINE TENGINE 559
++s3c2460 MACH_S3C2460 S3C2460 560
++pdm MACH_PDM PDM 561
++h4700 MACH_H4700 H4700 562
++h6300 MACH_H6300 H6300 563
++rz1700 MACH_RZ1700 RZ1700 564
++a716 MACH_A716 A716 565
++estk2440a MACH_ESTK2440A ESTK2440A 566
++atwixp425 MACH_ATWIXP425 ATWIXP425 567
++csb336 MACH_CSB336 CSB336 568
++rirm2 MACH_RIRM2 RIRM2 569
++cx23518 MACH_CX23518 CX23518 570
++cx2351x MACH_CX2351X CX2351X 571
++computime MACH_COMPUTIME COMPUTIME 572
++izarus MACH_IZARUS IZARUS 573
++pxa_rts MACH_RTS RTS 574
++se5100 MACH_SE5100 SE5100 575
++s3c2510 MACH_S3C2510 S3C2510 576
++csb437tl MACH_CSB437TL CSB437TL 577
++slauson MACH_SLAUSON SLAUSON 578
++pearlriver MACH_PEARLRIVER PEARLRIVER 579
++tdc_p210 MACH_TDC_P210 TDC_P210 580
++sg580 MACH_SG580 SG580 581
++wrsbcarm7 MACH_WRSBCARM7 WRSBCARM7 582
++ipd MACH_IPD IPD 583
++pxa_dnp2110 MACH_PXA_DNP2110 PXA_DNP2110 584
++xaeniax MACH_XAENIAX XAENIAX 585
++somn4250 MACH_SOMN4250 SOMN4250 586
++pleb2 MACH_PLEB2 PLEB2 587
++cornwallis MACH_CORNWALLIS CORNWALLIS 588
++gurney_drv MACH_GURNEY_DRV GURNEY_DRV 589
++chaffee MACH_CHAFFEE CHAFFEE 590
++rms101 MACH_RMS101 RMS101 591
++rx3715 MACH_RX3715 RX3715 592
++swift MACH_SWIFT SWIFT 593
++roverp7 MACH_ROVERP7 ROVERP7 594
++pr818s MACH_PR818S PR818S 595
++trxpro MACH_TRXPRO TRXPRO 596
++nslu2 MACH_NSLU2 NSLU2 597
++e400 MACH_E400 E400 598
++trab MACH_TRAB TRAB 599
++cmc_pu2 MACH_CMC_PU2 CMC_PU2 600
++fulcrum MACH_FULCRUM FULCRUM 601
++netgate42x MACH_NETGATE42X NETGATE42X 602
++str710 MACH_STR710 STR710 603
++ixdpg425 MACH_IXDPG425 IXDPG425 604
++tomtomgo MACH_TOMTOMGO TOMTOMGO 605
++versatile_ab MACH_VERSATILE_AB VERSATILE_AB 606
++edb9307 MACH_EDB9307 EDB9307 607
++sg565 MACH_SG565 SG565 608
++lpd79524 MACH_LPD79524 LPD79524 609
++lpd79525 MACH_LPD79525 LPD79525 610
++rms100 MACH_RMS100 RMS100 611
++kb9200 MACH_KB9200 KB9200 612
++sx1 MACH_SX1 SX1 613
++hms39c7092 MACH_HMS39C7092 HMS39C7092 614
++armadillo MACH_ARMADILLO ARMADILLO 615
++ipcu MACH_IPCU IPCU 616
++loox720 MACH_LOOX720 LOOX720 617
++ixdp465 MACH_IXDP465 IXDP465 618
++ixdp2351 MACH_IXDP2351 IXDP2351 619
++adsvix MACH_ADSVIX ADSVIX 620
++dm270 MACH_DM270 DM270 621
++socltplus MACH_SOCLTPLUS SOCLTPLUS 622
++ecia MACH_ECIA ECIA 623
++cm4008 MACH_CM4008 CM4008 624
++p2001 MACH_P2001 P2001 625
++twister MACH_TWISTER TWISTER 626
++mudshark MACH_MUDSHARK MUDSHARK 627
++hb2 MACH_HB2 HB2 628
++iq80332 MACH_IQ80332 IQ80332 629
++sendt MACH_SENDT SENDT 630
++mx2jazz MACH_MX2JAZZ MX2JAZZ 631
++multiio MACH_MULTIIO MULTIIO 632
++hrdisplay MACH_HRDISPLAY HRDISPLAY 633
++mxc27530ads MACH_MXC27530ADS MXC27530ADS 634
++trizeps3 MACH_TRIZEPS3 TRIZEPS3 635
++zefeerdza MACH_ZEFEERDZA ZEFEERDZA 636
++zefeerdzb MACH_ZEFEERDZB ZEFEERDZB 637
++zefeerdzg MACH_ZEFEERDZG ZEFEERDZG 638
++zefeerdzn MACH_ZEFEERDZN ZEFEERDZN 639
++zefeerdzq MACH_ZEFEERDZQ ZEFEERDZQ 640
++gtwx5715 MACH_GTWX5715 GTWX5715 641
++astro_jack MACH_ASTRO_JACK ASTRO_JACK 643
++tip03 MACH_TIP03 TIP03 644
++a9200ec MACH_A9200EC A9200EC 645
++pnx0105 MACH_PNX0105 PNX0105 646
++adcpoecpu MACH_ADCPOECPU ADCPOECPU 647
++csb637 MACH_CSB637 CSB637 648
++mb9200 MACH_MB9200 MB9200 650
++kulun MACH_KULUN KULUN 651
++snapper MACH_SNAPPER SNAPPER 652
++optima MACH_OPTIMA OPTIMA 653
++dlhsbc MACH_DLHSBC DLHSBC 654
++x30 MACH_X30 X30 655
++n30 MACH_N30 N30 656
++manga_ks8695 MACH_MANGA_KS8695 MANGA_KS8695 657
++ajax MACH_AJAX AJAX 658
++nec_mp900 MACH_NEC_MP900 NEC_MP900 659
++vvtk1000 MACH_VVTK1000 VVTK1000 661
++kafa MACH_KAFA KAFA 662
++vvtk3000 MACH_VVTK3000 VVTK3000 663
++pimx1 MACH_PIMX1 PIMX1 664
++ollie MACH_OLLIE OLLIE 665
++skymax MACH_SKYMAX SKYMAX 666
++jazz MACH_JAZZ JAZZ 667
++tel_t3 MACH_TEL_T3 TEL_T3 668
++aisino_fcr255 MACH_AISINO_FCR255 AISINO_FCR255 669
++btweb MACH_BTWEB BTWEB 670
++dbg_lh79520 MACH_DBG_LH79520 DBG_LH79520 671
++cm41xx MACH_CM41XX CM41XX 672
++ts72xx MACH_TS72XX TS72XX 673
++nggpxa MACH_NGGPXA NGGPXA 674
++csb535 MACH_CSB535 CSB535 675
++csb536 MACH_CSB536 CSB536 676
++pxa_trakpod MACH_PXA_TRAKPOD PXA_TRAKPOD 677
++praxis MACH_PRAXIS PRAXIS 678
++lh75411 MACH_LH75411 LH75411 679
++otom MACH_OTOM OTOM 680
++nexcoder_2440 MACH_NEXCODER_2440 NEXCODER_2440 681
++loox410 MACH_LOOX410 LOOX410 682
++westlake MACH_WESTLAKE WESTLAKE 683
++nsb MACH_NSB NSB 684
++esl_sarva_stn MACH_ESL_SARVA_STN ESL_SARVA_STN 685
++esl_sarva_tft MACH_ESL_SARVA_TFT ESL_SARVA_TFT 686
++esl_sarva_iad MACH_ESL_SARVA_IAD ESL_SARVA_IAD 687
++esl_sarva_acc MACH_ESL_SARVA_ACC ESL_SARVA_ACC 688
++typhoon MACH_TYPHOON TYPHOON 689
++cnav MACH_CNAV CNAV 690
++a730 MACH_A730 A730 691
++netstar MACH_NETSTAR NETSTAR 692
++supercon MACH_PHASEFALE_SUPERCON PHASEFALE_SUPERCON 693
++shiva1100 MACH_SHIVA1100 SHIVA1100 694
++etexsc MACH_ETEXSC ETEXSC 695
++ixdpg465 MACH_IXDPG465 IXDPG465 696
++a9m2410 MACH_A9M2410 A9M2410 697
++a9m2440 MACH_A9M2440 A9M2440 698
++a9m9750 MACH_A9M9750 A9M9750 699
++a9m9360 MACH_A9M9360 A9M9360 700
++unc90 MACH_UNC90 UNC90 701
++eco920 MACH_ECO920 ECO920 702
++satview MACH_SATVIEW SATVIEW 703
++roadrunner MACH_ROADRUNNER ROADRUNNER 704
++at91rm9200ek MACH_AT91RM9200EK AT91RM9200EK 705
++gp32 MACH_GP32 GP32 706
++gem MACH_GEM GEM 707
++i858 MACH_I858 I858 708
++hx2750 MACH_HX2750 HX2750 709
++mxc91131evb MACH_MXC91131EVB MXC91131EVB 710
++p700 MACH_P700 P700 711
++cpe MACH_CPE CPE 712
++spitz MACH_SPITZ SPITZ 713
++nimbra340 MACH_NIMBRA340 NIMBRA340 714
++lpc22xx MACH_LPC22XX LPC22XX 715
++omap_comet3 MACH_COMET3 COMET3 716
++omap_comet4 MACH_COMET4 COMET4 717
++csb625 MACH_CSB625 CSB625 718
++fortunet2 MACH_FORTUNET2 FORTUNET2 719
++s5h2200 MACH_S5H2200 S5H2200 720
++optorm920 MACH_OPTORM920 OPTORM920 721
++adsbitsyxb MACH_ADSBITSYXB ADSBITSYXB 722
++adssphere MACH_ADSSPHERE ADSSPHERE 723
++adsportal MACH_ADSPORTAL ADSPORTAL 724
++ln2410sbc MACH_LN2410SBC LN2410SBC 725
++cb3rufc MACH_CB3RUFC CB3RUFC 726
++mp2usb MACH_MP2USB MP2USB 727
++ntnp425c MACH_NTNP425C NTNP425C 728
++colibri MACH_COLIBRI COLIBRI 729
++pcm7220 MACH_PCM7220 PCM7220 730
++gateway7001 MACH_GATEWAY7001 GATEWAY7001 731
++pcm027 MACH_PCM027 PCM027 732
++cmpxa MACH_CMPXA CMPXA 733
++anubis MACH_ANUBIS ANUBIS 734
++ite8152 MACH_ITE8152 ITE8152 735
++lpc3xxx MACH_LPC3XXX LPC3XXX 736
++puppeteer MACH_PUPPETEER PUPPETEER 737
++e570 MACH_E570 E570 739
++x50 MACH_X50 X50 740
++recon MACH_RECON RECON 741
++xboardgp8 MACH_XBOARDGP8 XBOARDGP8 742
++fpic2 MACH_FPIC2 FPIC2 743
++akita MACH_AKITA AKITA 744
++a81 MACH_A81 A81 745
++svm_sc25x MACH_SVM_SC25X SVM_SC25X 746
++vt020 MACH_VADATECH020 VADATECH020 747
++tli MACH_TLI TLI 748
++edb9315lc MACH_EDB9315LC EDB9315LC 749
++passec MACH_PASSEC PASSEC 750
++ds_tiger MACH_DS_TIGER DS_TIGER 751
++e310 MACH_E310 E310 752
++e330 MACH_E330 E330 753
++rt3000 MACH_RT3000 RT3000 754
++nokia770 MACH_NOKIA770 NOKIA770 755
++pnx0106 MACH_PNX0106 PNX0106 756
++hx21xx MACH_HX21XX HX21XX 757
++faraday MACH_FARADAY FARADAY 758
++sbc9312 MACH_SBC9312 SBC9312 759
++batman MACH_BATMAN BATMAN 760
++jpd201 MACH_JPD201 JPD201 761
++mipsa MACH_MIPSA MIPSA 762
++kacom MACH_KACOM KACOM 763
++swarcocpu MACH_SWARCOCPU SWARCOCPU 764
++swarcodsl MACH_SWARCODSL SWARCODSL 765
++blueangel MACH_BLUEANGEL BLUEANGEL 766
++hairygrama MACH_HAIRYGRAMA HAIRYGRAMA 767
++banff MACH_BANFF BANFF 768
++carmeva MACH_CARMEVA CARMEVA 769
++sam255 MACH_SAM255 SAM255 770
++ppm10 MACH_PPM10 PPM10 771
++edb9315a MACH_EDB9315A EDB9315A 772
++sunset MACH_SUNSET SUNSET 773
++stargate2 MACH_STARGATE2 STARGATE2 774
++intelmote2 MACH_INTELMOTE2 INTELMOTE2 775
++trizeps4 MACH_TRIZEPS4 TRIZEPS4 776
++mainstone2 MACH_MAINSTONE2 MAINSTONE2 777
++ez_ixp42x MACH_EZ_IXP42X EZ_IXP42X 778
++tapwave_zodiac MACH_TAPWAVE_ZODIAC TAPWAVE_ZODIAC 779
++universalmeter MACH_UNIVERSALMETER UNIVERSALMETER 780
++hicoarm9 MACH_HICOARM9 HICOARM9 781
++pnx4008 MACH_PNX4008 PNX4008 782
++kws6000 MACH_KWS6000 KWS6000 783
++portux920t MACH_PORTUX920T PORTUX920T 784
++ez_x5 MACH_EZ_X5 EZ_X5 785
++omap_rudolph MACH_OMAP_RUDOLPH OMAP_RUDOLPH 786
++cpuat91 MACH_CPUAT91 CPUAT91 787
++rea9200 MACH_REA9200 REA9200 788
++acts_pune_sa1110 MACH_ACTS_PUNE_SA1110 ACTS_PUNE_SA1110 789
++ixp425 MACH_IXP425 IXP425 790
++i30030ads MACH_I30030ADS I30030ADS 791
++perch MACH_PERCH PERCH 792
++eis05r1 MACH_EIS05R1 EIS05R1 793
++pepperpad MACH_PEPPERPAD PEPPERPAD 794
++sb3010 MACH_SB3010 SB3010 795
++rm9200 MACH_RM9200 RM9200 796
++dma03 MACH_DMA03 DMA03 797
++road_s101 MACH_ROAD_S101 ROAD_S101 798
++iq81340sc MACH_IQ81340SC IQ81340SC 799
++iq_nextgen_b MACH_IQ_NEXTGEN_B IQ_NEXTGEN_B 800
++iq81340mc MACH_IQ81340MC IQ81340MC 801
++iq_nextgen_d MACH_IQ_NEXTGEN_D IQ_NEXTGEN_D 802
++iq_nextgen_e MACH_IQ_NEXTGEN_E IQ_NEXTGEN_E 803
++mallow_at91 MACH_MALLOW_AT91 MALLOW_AT91 804
++cybertracker_i MACH_CYBERTRACKER_I CYBERTRACKER_I 805
++gesbc931x MACH_GESBC931X GESBC931X 806
++centipad MACH_CENTIPAD CENTIPAD 807
++armsoc MACH_ARMSOC ARMSOC 808
++se4200 MACH_SE4200 SE4200 809
++ems197a MACH_EMS197A EMS197A 810
++micro9 MACH_MICRO9 MICRO9 811
++micro9l MACH_MICRO9L MICRO9L 812
++uc5471dsp MACH_UC5471DSP UC5471DSP 813
++sj5471eng MACH_SJ5471ENG SJ5471ENG 814
++none MACH_CMPXA26X CMPXA26X 815
++nc1 MACH_NC NC 816
++omap_palmte MACH_OMAP_PALMTE OMAP_PALMTE 817
++ajax52x MACH_AJAX52X AJAX52X 818
++siriustar MACH_SIRIUSTAR SIRIUSTAR 819
++iodata_hdlg MACH_IODATA_HDLG IODATA_HDLG 820
++at91rm9200utl MACH_AT91RM9200UTL AT91RM9200UTL 821
++biosafe MACH_BIOSAFE BIOSAFE 822
++mp1000 MACH_MP1000 MP1000 823
++parsy MACH_PARSY PARSY 824
++ccxp270 MACH_CCXP CCXP 825
++omap_gsample MACH_OMAP_GSAMPLE OMAP_GSAMPLE 826
++realview_eb MACH_REALVIEW_EB REALVIEW_EB 827
++samoa MACH_SAMOA SAMOA 828
++palmt3 MACH_PALMT3 PALMT3 829
++i878 MACH_I878 I878 830
++borzoi MACH_BORZOI BORZOI 831
++gecko MACH_GECKO GECKO 832
++ds101 MACH_DS101 DS101 833
++omap_palmtt2 MACH_OMAP_PALMTT2 OMAP_PALMTT2 834
++palmld MACH_PALMLD PALMLD 835
++cc9c MACH_CC9C CC9C 836
++sbc1670 MACH_SBC1670 SBC1670 837
++ixdp28x5 MACH_IXDP28X5 IXDP28X5 838
++omap_palmtt MACH_OMAP_PALMTT OMAP_PALMTT 839
++ml696k MACH_ML696K ML696K 840
++arcom_zeus MACH_ARCOM_ZEUS ARCOM_ZEUS 841
++osiris MACH_OSIRIS OSIRIS 842
++maestro MACH_MAESTRO MAESTRO 843
++palmte2 MACH_PALMTE2 PALMTE2 844
++ixbbm MACH_IXBBM IXBBM 845
++mx27ads MACH_MX27ADS MX27ADS 846
++ax8004 MACH_AX8004 AX8004 847
++at91sam9261ek MACH_AT91SAM9261EK AT91SAM9261EK 848
++loft MACH_LOFT LOFT 849
++magpie MACH_MAGPIE MAGPIE 850
++mx21ads MACH_MX21ADS MX21ADS 851
++mb87m3400 MACH_MB87M3400 MB87M3400 852
++mguard_delta MACH_MGUARD_DELTA MGUARD_DELTA 853
++davinci_dvdp MACH_DAVINCI_DVDP DAVINCI_DVDP 854
++htcuniversal MACH_HTCUNIVERSAL HTCUNIVERSAL 855
++tpad MACH_TPAD TPAD 856
++roverp3 MACH_ROVERP3 ROVERP3 857
++jornada928 MACH_JORNADA928 JORNADA928 858
++mv88fxx81 MACH_MV88FXX81 MV88FXX81 859
++stmp36xx MACH_STMP36XX STMP36XX 860
++sxni79524 MACH_SXNI79524 SXNI79524 861
++ams_delta MACH_AMS_DELTA AMS_DELTA 862
++uranium MACH_URANIUM URANIUM 863
++ucon MACH_UCON UCON 864
++nas100d MACH_NAS100D NAS100D 865
++l083 MACH_L083_1000 L083_1000 866
++ezx MACH_EZX EZX 867
++pnx5220 MACH_PNX5220 PNX5220 868
++butte MACH_BUTTE BUTTE 869
++srm2 MACH_SRM2 SRM2 870
++dsbr MACH_DSBR DSBR 871
++crystalball MACH_CRYSTALBALL CRYSTALBALL 872
++tinypxa27x MACH_TINYPXA27X TINYPXA27X 873
++herbie MACH_HERBIE HERBIE 874
++magician MACH_MAGICIAN MAGICIAN 875
++cm4002 MACH_CM4002 CM4002 876
++b4 MACH_B4 B4 877
++maui MACH_MAUI MAUI 878
++cybertracker_g MACH_CYBERTRACKER_G CYBERTRACKER_G 879
++nxdkn MACH_NXDKN NXDKN 880
++mio8390 MACH_MIO8390 MIO8390 881
++omi_board MACH_OMI_BOARD OMI_BOARD 882
++mx21civ MACH_MX21CIV MX21CIV 883
++mahi_cdac MACH_MAHI_CDAC MAHI_CDAC 884
++palmtx MACH_PALMTX PALMTX 885
++s3c2413 MACH_S3C2413 S3C2413 887
++samsys_ep0 MACH_SAMSYS_EP0 SAMSYS_EP0 888
++wg302v1 MACH_WG302V1 WG302V1 889
++wg302v2 MACH_WG302V2 WG302V2 890
++eb42x MACH_EB42X EB42X 891
++iq331es MACH_IQ331ES IQ331ES 892
++cosydsp MACH_COSYDSP COSYDSP 893
++uplat7d_proto MACH_UPLAT7D UPLAT7D 894
++ptdavinci MACH_PTDAVINCI PTDAVINCI 895
++mbus MACH_MBUS MBUS 896
++nadia2vb MACH_NADIA2VB NADIA2VB 897
++r1000 MACH_R1000 R1000 898
++hw90250 MACH_HW90250 HW90250 899
++omap_2430sdp MACH_OMAP_2430SDP OMAP_2430SDP 900
++davinci_evm MACH_DAVINCI_EVM DAVINCI_EVM 901
++omap_tornado MACH_OMAP_TORNADO OMAP_TORNADO 902
++olocreek MACH_OLOCREEK OLOCREEK 903
++palmz72 MACH_PALMZ72 PALMZ72 904
++nxdb500 MACH_NXDB500 NXDB500 905
++apf9328 MACH_APF9328 APF9328 906
++omap_wipoq MACH_OMAP_WIPOQ OMAP_WIPOQ 907
++omap_twip MACH_OMAP_TWIP OMAP_TWIP 908
++treo650 MACH_TREO650 TREO650 909
++acumen MACH_ACUMEN ACUMEN 910
++xp100 MACH_XP100 XP100 911
++fs2410 MACH_FS2410 FS2410 912
++pxa270_cerf MACH_PXA270_CERF PXA270_CERF 913
++sq2ftlpalm MACH_SQ2FTLPALM SQ2FTLPALM 914
++bsemserver MACH_BSEMSERVER BSEMSERVER 915
++netclient MACH_NETCLIENT NETCLIENT 916
++palmt5 MACH_PALMT5 PALMT5 917
++palmtc MACH_PALMTC PALMTC 918
++omap_apollon MACH_OMAP_APOLLON OMAP_APOLLON 919
++mxc30030evb MACH_MXC30030EVB MXC30030EVB 920
++rea_cpu2 MACH_REA_2D REA_2D 921
++eti3e524 MACH_TI3E524 TI3E524 922
++ateb9200 MACH_ATEB9200 ATEB9200 923
++auckland MACH_AUCKLAND AUCKLAND 924
++ak3220m MACH_AK3320M AK3320M 925
++duramax MACH_DURAMAX DURAMAX 926
++n35 MACH_N35 N35 927
++pronghorn MACH_PRONGHORN PRONGHORN 928
++fundy MACH_FUNDY FUNDY 929
++logicpd_pxa270 MACH_LOGICPD_PXA270 LOGICPD_PXA270 930
++cpu777 MACH_CPU777 CPU777 931
++simicon9201 MACH_SIMICON9201 SIMICON9201 932
++leap2_hpm MACH_LEAP2_HPM LEAP2_HPM 933
++cm922txa10 MACH_CM922TXA10 CM922TXA10 934
++sandgate MACH_PXA PXA 935
++sandgate2 MACH_SANDGATE2 SANDGATE2 936
++sandgate2g MACH_SANDGATE2G SANDGATE2G 937
++sandgate2p MACH_SANDGATE2P SANDGATE2P 938
++fred_jack MACH_FRED_JACK FRED_JACK 939
++ttg_color1 MACH_TTG_COLOR1 TTG_COLOR1 940
++nxeb500hmi MACH_NXEB500HMI NXEB500HMI 941
++netdcu8 MACH_NETDCU8 NETDCU8 942
++ng_fvx538 MACH_NG_FVX538 NG_FVX538 944
++ng_fvs338 MACH_NG_FVS338 NG_FVS338 945
++pnx4103 MACH_PNX4103 PNX4103 946
++hesdb MACH_HESDB HESDB 947
++xsilo MACH_XSILO XSILO 948
++espresso MACH_ESPRESSO ESPRESSO 949
++emlc MACH_EMLC EMLC 950
++sisteron MACH_SISTERON SISTERON 951
++rx1950 MACH_RX1950 RX1950 952
++tsc_venus MACH_TSC_VENUS TSC_VENUS 953
++ds101j MACH_DS101J DS101J 954
++mxc30030ads MACH_MXC30030ADS MXC30030ADS 955
++fujitsu_wimaxsoc MACH_FUJITSU_WIMAXSOC FUJITSU_WIMAXSOC 956
++dualpcmodem MACH_DUALPCMODEM DUALPCMODEM 957
++gesbc9312 MACH_GESBC9312 GESBC9312 958
++htcapache MACH_HTCAPACHE HTCAPACHE 959
++ixdp435 MACH_IXDP435 IXDP435 960
++catprovt100 MACH_CATPROVT100 CATPROVT100 961
++picotux1xx MACH_PICOTUX1XX PICOTUX1XX 962
++picotux2xx MACH_PICOTUX2XX PICOTUX2XX 963
++dsmg600 MACH_DSMG600 DSMG600 964
++empc2 MACH_EMPC2 EMPC2 965
++ventura MACH_VENTURA VENTURA 966
++phidget_sbc MACH_PHIDGET_SBC PHIDGET_SBC 967
++ij3k MACH_IJ3K IJ3K 968
++pisgah MACH_PISGAH PISGAH 969
++omap_fsample MACH_OMAP_FSAMPLE OMAP_FSAMPLE 970
++sg720 MACH_SG720 SG720 971
++redfox MACH_REDFOX REDFOX 972
++mysh_ep9315_1 MACH_MYSH_EP9315_1 MYSH_EP9315_1 973
++tpf106 MACH_TPF106 TPF106 974
++at91rm9200kg MACH_AT91RM9200KG AT91RM9200KG 975
++rcmt2 MACH_SLEDB SLEDB 976
++ontrack MACH_ONTRACK ONTRACK 977
++pm1200 MACH_PM1200 PM1200 978
++ess24562 MACH_ESS24XXX ESS24XXX 979
++coremp7 MACH_COREMP7 COREMP7 980
++nexcoder_6446 MACH_NEXCODER_6446 NEXCODER_6446 981
++stvc8380 MACH_STVC8380 STVC8380 982
++teklynx MACH_TEKLYNX TEKLYNX 983
++carbonado MACH_CARBONADO CARBONADO 984
++sysmos_mp730 MACH_SYSMOS_MP730 SYSMOS_MP730 985
++snapper_cl15 MACH_SNAPPER_CL15 SNAPPER_CL15 986
++pgigim MACH_PGIGIM PGIGIM 987
++ptx9160p2 MACH_PTX9160P2 PTX9160P2 988
++dcore1 MACH_DCORE1 DCORE1 989
++victorpxa MACH_VICTORPXA VICTORPXA 990
++mx2dtb MACH_MX2DTB MX2DTB 991
++pxa_irex_er0100 MACH_PXA_IREX_ER0100 PXA_IREX_ER0100 992
++omap_palmz71 MACH_OMAP_PALMZ71 OMAP_PALMZ71 993
++bartec_deg MACH_BARTEC_DEG BARTEC_DEG 994
++hw50251 MACH_HW50251 HW50251 995
++ibox MACH_IBOX IBOX 996
++atlaslh7a404 MACH_ATLASLH7A404 ATLASLH7A404 997
++pt2026 MACH_PT2026 PT2026 998
++htcalpine MACH_HTCALPINE HTCALPINE 999
++bartec_vtu MACH_BARTEC_VTU BARTEC_VTU 1000
++vcoreii MACH_VCOREII VCOREII 1001
++pdnb3 MACH_PDNB3 PDNB3 1002
++htcbeetles MACH_HTCBEETLES HTCBEETLES 1003
++s3c6400 MACH_S3C6400 S3C6400 1004
++s3c2443 MACH_S3C2443 S3C2443 1005
++omap_ldk MACH_OMAP_LDK OMAP_LDK 1006
++smdk2460 MACH_SMDK2460 SMDK2460 1007
++smdk2440 MACH_SMDK2440 SMDK2440 1008
++smdk2412 MACH_SMDK2412 SMDK2412 1009
++webbox MACH_WEBBOX WEBBOX 1010
++cwwndp MACH_CWWNDP CWWNDP 1011
++i839 MACH_DRAGON DRAGON 1012
++opendo_cpu_board MACH_OPENDO_CPU_BOARD OPENDO_CPU_BOARD 1013
++ccm2200 MACH_CCM2200 CCM2200 1014
++etwarm MACH_ETWARM ETWARM 1015
++m93030 MACH_M93030 M93030 1016
++cc7u MACH_CC7U CC7U 1017
++mtt_ranger MACH_MTT_RANGER MTT_RANGER 1018
++nexus MACH_NEXUS NEXUS 1019
++desman MACH_DESMAN DESMAN 1020
++bkde303 MACH_BKDE303 BKDE303 1021
++smdk2413 MACH_SMDK2413 SMDK2413 1022
++aml_m7200 MACH_AML_M7200 AML_M7200 1023
++aml_m5900 MACH_AML_M5900 AML_M5900 1024
++sg640 MACH_SG640 SG640 1025
++edg79524 MACH_EDG79524 EDG79524 1026
++ai2410 MACH_AI2410 AI2410 1027
++ixp465 MACH_IXP465 IXP465 1028
++balloon3 MACH_BALLOON3 BALLOON3 1029
++heins MACH_HEINS HEINS 1030
++mpluseva MACH_MPLUSEVA MPLUSEVA 1031
++rt042 MACH_RT042 RT042 1032
++cwiem MACH_CWIEM CWIEM 1033
++cm_x270 MACH_CM_X270 CM_X270 1034
++cm_x255 MACH_CM_X255 CM_X255 1035
++esh_at91 MACH_ESH_AT91 ESH_AT91 1036
++sandgate3 MACH_SANDGATE3 SANDGATE3 1037
++primo MACH_PRIMO PRIMO 1038
++gemstone MACH_GEMSTONE GEMSTONE 1039
++pronghorn_metro MACH_PRONGHORNMETRO PRONGHORNMETRO 1040
++sidewinder MACH_SIDEWINDER SIDEWINDER 1041
++picomod1 MACH_PICOMOD1 PICOMOD1 1042
++sg590 MACH_SG590 SG590 1043
++akai9307 MACH_AKAI9307 AKAI9307 1044
++fontaine MACH_FONTAINE FONTAINE 1045
++wombat MACH_WOMBAT WOMBAT 1046
++acq300 MACH_ACQ300 ACQ300 1047
++mod272 MACH_MOD_270 MOD_270 1048
++vmc_vc0820 MACH_VC0820 VC0820 1049
++ani_aim MACH_ANI_AIM ANI_AIM 1050
++jellyfish MACH_JELLYFISH JELLYFISH 1051
++amanita MACH_AMANITA AMANITA 1052
++vlink MACH_VLINK VLINK 1053
++dexflex MACH_DEXFLEX DEXFLEX 1054
++eigen_ttq MACH_EIGEN_TTQ EIGEN_TTQ 1055
++arcom_titan MACH_ARCOM_TITAN ARCOM_TITAN 1056
++tabla MACH_TABLA TABLA 1057
++mdirac3 MACH_MDIRAC3 MDIRAC3 1058
++mrhfbp2 MACH_MRHFBP2 MRHFBP2 1059
++at91rm9200rb MACH_AT91RM9200RB AT91RM9200RB 1060
++ani_apm MACH_ANI_APM ANI_APM 1061
++ella1 MACH_ELLA1 ELLA1 1062
++inhand_pxa27x MACH_INHAND_PXA27X INHAND_PXA27X 1063
++inhand_pxa25x MACH_INHAND_PXA25X INHAND_PXA25X 1064
++empos_xm MACH_EMPOS_XM EMPOS_XM 1065
++empos MACH_EMPOS EMPOS 1066
++empos_tiny MACH_EMPOS_TINY EMPOS_TINY 1067
++empos_sm MACH_EMPOS_SM EMPOS_SM 1068
++egret MACH_EGRET EGRET 1069
++ostrich MACH_OSTRICH OSTRICH 1070
++n50 MACH_N50 N50 1071
++ecbat91 MACH_ECBAT91 ECBAT91 1072
++stareast MACH_STAREAST STAREAST 1073
++dspg_dw MACH_DSPG_DW DSPG_DW 1074
++onearm MACH_ONEARM ONEARM 1075
++mrg110_6 MACH_MRG110_6 MRG110_6 1076
++wrt300nv2 MACH_WRT300NV2 WRT300NV2 1077
++xm_bulverde MACH_XM_BULVERDE XM_BULVERDE 1078
++msm6100 MACH_MSM6100 MSM6100 1079
++eti_b1 MACH_ETI_B1 ETI_B1 1080
++za9l_series MACH_ZILOG_ZA9L ZILOG_ZA9L 1081
++bit2440 MACH_BIT2440 BIT2440 1082
++nbi MACH_NBI NBI 1083
++smdk2443 MACH_SMDK2443 SMDK2443 1084
++vdavinci MACH_VDAVINCI VDAVINCI 1085
++atc6 MACH_ATC6 ATC6 1086
++multmdw MACH_MULTMDW MULTMDW 1087
++mba2440 MACH_MBA2440 MBA2440 1088
++ecsd MACH_ECSD ECSD 1089
++palmz31 MACH_PALMZ31 PALMZ31 1090
++fsg MACH_FSG FSG 1091
++razor101 MACH_RAZOR101 RAZOR101 1092
++opera_tdm MACH_OPERA_TDM OPERA_TDM 1093
++comcerto MACH_COMCERTO COMCERTO 1094
++tb0319 MACH_TB0319 TB0319 1095
++kws8000 MACH_KWS8000 KWS8000 1096
++b2 MACH_B2 B2 1097
++lcl54 MACH_LCL54 LCL54 1098
++at91sam9260ek MACH_AT91SAM9260EK AT91SAM9260EK 1099
++glantank MACH_GLANTANK GLANTANK 1100
++n2100 MACH_N2100 N2100 1101
++n4100 MACH_N4100 N4100 1102
++rsc4 MACH_VERTICAL_RSC4 VERTICAL_RSC4 1103
++sg8100 MACH_SG8100 SG8100 1104
++im42xx MACH_IM42XX IM42XX 1105
++ftxx MACH_FTXX FTXX 1106
++lwfusion MACH_LWFUSION LWFUSION 1107
++qt2410 MACH_QT2410 QT2410 1108
++kixrp435 MACH_KIXRP435 KIXRP435 1109
++ccw9c MACH_CCW9C CCW9C 1110
++dabhs MACH_DABHS DABHS 1111
++gzmx MACH_GZMX GZMX 1112
++ipnw100ap MACH_IPNW100AP IPNW100AP 1113
++cc9p9360dev MACH_CC9P9360DEV CC9P9360DEV 1114
++cc9p9750dev MACH_CC9P9750DEV CC9P9750DEV 1115
++cc9p9360val MACH_CC9P9360VAL CC9P9360VAL 1116
++cc9p9750val MACH_CC9P9750VAL CC9P9750VAL 1117
++nx70v MACH_NX70V NX70V 1118
++at91rm9200df MACH_AT91RM9200DF AT91RM9200DF 1119
++se_pilot2 MACH_SE_PILOT2 SE_PILOT2 1120
++mtcn_t800 MACH_MTCN_T800 MTCN_T800 1121
++vcmx212 MACH_VCMX212 VCMX212 1122
++lynx MACH_LYNX LYNX 1123
++at91sam9260id MACH_AT91SAM9260ID AT91SAM9260ID 1124
++hw86052 MACH_HW86052 HW86052 1125
++pilz_pmi3 MACH_PILZ_PMI3 PILZ_PMI3 1126
++edb9302a MACH_EDB9302A EDB9302A 1127
++edb9307a MACH_EDB9307A EDB9307A 1128
++ct_dfs MACH_CT_DFS CT_DFS 1129
++pilz_pmi4 MACH_PILZ_PMI4 PILZ_PMI4 1130
++xceednp_ixp MACH_XCEEDNP_IXP XCEEDNP_IXP 1131
++smdk2442b MACH_SMDK2442B SMDK2442B 1132
++xnode MACH_XNODE XNODE 1133
++aidx270 MACH_AIDX270 AIDX270 1134
++rema MACH_REMA REMA 1135
++bps1000 MACH_BPS1000 BPS1000 1136
++hw90350 MACH_HW90350 HW90350 1137
++omap_3430sdp MACH_OMAP_3430SDP OMAP_3430SDP 1138
++bluetouch MACH_BLUETOUCH BLUETOUCH 1139
++vstms MACH_VSTMS VSTMS 1140
++xsbase270 MACH_XSBASE270 XSBASE270 1141
++at91sam9260ek_cn MACH_AT91SAM9260EK_CN AT91SAM9260EK_CN 1142
++adsturboxb MACH_ADSTURBOXB ADSTURBOXB 1143
++oti4110 MACH_OTI4110 OTI4110 1144
++hme_pxa MACH_HME_PXA HME_PXA 1145
++deisterdca MACH_DEISTERDCA DEISTERDCA 1146
++ces_ssem2 MACH_CES_SSEM2 CES_SSEM2 1147
++ces_mtr MACH_CES_MTR CES_MTR 1148
++tds_avng_sbc MACH_TDS_AVNG_SBC TDS_AVNG_SBC 1149
++everest MACH_EVEREST EVEREST 1150
++pnx4010 MACH_PNX4010 PNX4010 1151
++oxnas MACH_OXNAS OXNAS 1152
++fiori MACH_FIORI FIORI 1153
++ml1200 MACH_ML1200 ML1200 1154
++pecos MACH_PECOS PECOS 1155
++nb2xxx MACH_NB2XXX NB2XXX 1156
++hw6900 MACH_HW6900 HW6900 1157
++cdcs_quoll MACH_CDCS_QUOLL CDCS_QUOLL 1158
++quicksilver MACH_QUICKSILVER QUICKSILVER 1159
++uplat926 MACH_UPLAT926 UPLAT926 1160
++dep2410_dep2410 MACH_DEP2410_THOMAS DEP2410_THOMAS 1161
++dtk2410 MACH_DTK2410 DTK2410 1162
++chili MACH_CHILI CHILI 1163
++demeter MACH_DEMETER DEMETER 1164
++dionysus MACH_DIONYSUS DIONYSUS 1165
++as352x MACH_AS352X AS352X 1166
++service MACH_SERVICE SERVICE 1167
++cs_e9301 MACH_CS_E9301 CS_E9301 1168
++micro9m MACH_MICRO9M MICRO9M 1169
++ia_mospck MACH_IA_MOSPCK IA_MOSPCK 1170
++ql201b MACH_QL201B QL201B 1171
++bbm MACH_BBM BBM 1174
++exxx MACH_EXXX EXXX 1175
++wma11b MACH_WMA11B WMA11B 1176
++pelco_atlas MACH_PELCO_ATLAS PELCO_ATLAS 1177
++g500 MACH_G500 G500 1178
++bug MACH_BUG BUG 1179
++mx33ads MACH_MX33ADS MX33ADS 1180
++chub MACH_CHUB CHUB 1181
++neo1973_gta01 MACH_NEO1973_GTA01 NEO1973_GTA01 1182
++w90n740 MACH_W90N740 W90N740 1183
++medallion_sa2410 MACH_MEDALLION_SA2410 MEDALLION_SA2410 1184
++ia_cpu_9200_2 MACH_IA_CPU_9200_2 IA_CPU_9200_2 1185
++dimmrm9200 MACH_DIMMRM9200 DIMMRM9200 1186
++pm9261 MACH_PM9261 PM9261 1187
++ml7304 MACH_ML7304 ML7304 1189
++ucp250 MACH_UCP250 UCP250 1190
++intboard MACH_INTBOARD INTBOARD 1191
++gulfstream MACH_GULFSTREAM GULFSTREAM 1192
++labquest MACH_LABQUEST LABQUEST 1193
++vcmx313 MACH_VCMX313 VCMX313 1194
++urg200 MACH_URG200 URG200 1195
++cpux255lcdnet MACH_CPUX255LCDNET CPUX255LCDNET 1196
++netdcu9 MACH_NETDCU9 NETDCU9 1197
++netdcu10 MACH_NETDCU10 NETDCU10 1198
++dspg_dga MACH_DSPG_DGA DSPG_DGA 1199
++dspg_dvw MACH_DSPG_DVW DSPG_DVW 1200
++solos MACH_SOLOS SOLOS 1201
++at91sam9263ek MACH_AT91SAM9263EK AT91SAM9263EK 1202
++osstbox MACH_OSSTBOX OSSTBOX 1203
++kbat9261 MACH_KBAT9261 KBAT9261 1204
++ct1100 MACH_CT1100 CT1100 1205
++akcppxa MACH_AKCPPXA AKCPPXA 1206
++ochaya1020 MACH_OCHAYA1020 OCHAYA1020 1207
++hitrack MACH_HITRACK HITRACK 1208
++syme1 MACH_SYME1 SYME1 1209
++syhl1 MACH_SYHL1 SYHL1 1210
++empca400 MACH_EMPCA400 EMPCA400 1211
++em7210 MACH_EM7210 EM7210 1212
++htchermes MACH_HTCHERMES HTCHERMES 1213
++eti_c1 MACH_ETI_C1 ETI_C1 1214
++ac100 MACH_AC100 AC100 1216
++sneetch MACH_SNEETCH SNEETCH 1217
++studentmate MACH_STUDENTMATE STUDENTMATE 1218
++zir2410 MACH_ZIR2410 ZIR2410 1219
++zir2413 MACH_ZIR2413 ZIR2413 1220
++dlonip3 MACH_DLONIP3 DLONIP3 1221
++instream MACH_INSTREAM INSTREAM 1222
++ambarella MACH_AMBARELLA AMBARELLA 1223
++nevis MACH_NEVIS NEVIS 1224
++htc_trinity MACH_HTC_TRINITY HTC_TRINITY 1225
++ql202b MACH_QL202B QL202B 1226
++vpac270 MACH_VPAC270 VPAC270 1227
++rd129 MACH_RD129 RD129 1228
++htcwizard MACH_HTCWIZARD HTCWIZARD 1229
++treo680 MACH_TREO680 TREO680 1230
++tecon_tmezon MACH_TECON_TMEZON TECON_TMEZON 1231
++zylonite MACH_ZYLONITE ZYLONITE 1233
++gene1270 MACH_GENE1270 GENE1270 1234
++zir2412 MACH_ZIR2412 ZIR2412 1235
++mx31lite MACH_MX31LITE MX31LITE 1236
++t700wx MACH_T700WX T700WX 1237
++vf100 MACH_VF100 VF100 1238
++nsb2 MACH_NSB2 NSB2 1239
++nxhmi_bb MACH_NXHMI_BB NXHMI_BB 1240
++nxhmi_re MACH_NXHMI_RE NXHMI_RE 1241
++n4100pro MACH_N4100PRO N4100PRO 1242
++sam9260 MACH_SAM9260 SAM9260 1243
++omap_treo600 MACH_OMAP_TREO600 OMAP_TREO600 1244
++indy2410 MACH_INDY2410 INDY2410 1245
++nelt_a MACH_NELT_A NELT_A 1246
++n311 MACH_N311 N311 1248
++at91sam9260vgk MACH_AT91SAM9260VGK AT91SAM9260VGK 1249
++at91leppe MACH_AT91LEPPE AT91LEPPE 1250
++at91lepccn MACH_AT91LEPCCN AT91LEPCCN 1251
++apc7100 MACH_APC7100 APC7100 1252
++stargazer MACH_STARGAZER STARGAZER 1253
++sonata MACH_SONATA SONATA 1254
++schmoogie MACH_SCHMOOGIE SCHMOOGIE 1255
++aztool MACH_AZTOOL AZTOOL 1256
++mioa701 MACH_MIOA701 MIOA701 1257
++sxni9260 MACH_SXNI9260 SXNI9260 1258
++mxc27520evb MACH_MXC27520EVB MXC27520EVB 1259
++armadillo5x0 MACH_ARMADILLO5X0 ARMADILLO5X0 1260
++mb9260 MACH_MB9260 MB9260 1261
++mb9263 MACH_MB9263 MB9263 1262
++ipac9302 MACH_IPAC9302 IPAC9302 1263
++cc9p9360js MACH_CC9P9360JS CC9P9360JS 1264
++gallium MACH_GALLIUM GALLIUM 1265
++msc2410 MACH_MSC2410 MSC2410 1266
++ghi270 MACH_GHI270 GHI270 1267
++davinci_leonardo MACH_DAVINCI_LEONARDO DAVINCI_LEONARDO 1268
++oiab MACH_OIAB OIAB 1269
++smdk6400 MACH_SMDK6400 SMDK6400 1270
++nokia_n800 MACH_NOKIA_N800 NOKIA_N800 1271
++greenphone MACH_GREENPHONE GREENPHONE 1272
++compex42x MACH_COMPEXWP18 COMPEXWP18 1273
++xmate MACH_XMATE XMATE 1274
++energizer MACH_ENERGIZER ENERGIZER 1275
++ime1 MACH_IME1 IME1 1276
++sweda_tms MACH_SWEDATMS SWEDATMS 1277
++ntnp435c MACH_NTNP435C NTNP435C 1278
++spectro2 MACH_SPECTRO2 SPECTRO2 1279
++h6039 MACH_H6039 H6039 1280
++ep80219 MACH_EP80219 EP80219 1281
++samoa_ii MACH_SAMOA_II SAMOA_II 1282
++cwmxl MACH_CWMXL CWMXL 1283
++as9200 MACH_AS9200 AS9200 1284
++sfx1149 MACH_SFX1149 SFX1149 1285
++navi010 MACH_NAVI010 NAVI010 1286
++multmdp MACH_MULTMDP MULTMDP 1287
++scb9520 MACH_SCB9520 SCB9520 1288
++htcathena MACH_HTCATHENA HTCATHENA 1289
++xp179 MACH_XP179 XP179 1290
++h4300 MACH_H4300 H4300 1291
++goramo_mlr MACH_GORAMO_MLR GORAMO_MLR 1292
++mxc30020evb MACH_MXC30020EVB MXC30020EVB 1293
++adsbitsyg5 MACH_ADSBITSYG5 ADSBITSYG5 1294
++adsportalplus MACH_ADSPORTALPLUS ADSPORTALPLUS 1295
++mmsp2plus MACH_MMSP2PLUS MMSP2PLUS 1296
++em_x270 MACH_EM_X270 EM_X270 1297
++tpp302 MACH_TPP302 TPP302 1298
++tpp104 MACH_TPM104 TPM104 1299
++tpm102 MACH_TPM102 TPM102 1300
++tpm109 MACH_TPM109 TPM109 1301
++fbxo1 MACH_FBXO1 FBXO1 1302
++hxd8 MACH_HXD8 HXD8 1303
++neo1973_gta02 MACH_NEO1973_GTA02 NEO1973_GTA02 1304
++emtest MACH_EMTEST EMTEST 1305
++ad6900 MACH_AD6900 AD6900 1306
++europa MACH_EUROPA EUROPA 1307
++metroconnect MACH_METROCONNECT METROCONNECT 1308
++ez_s2410 MACH_EZ_S2410 EZ_S2410 1309
++ez_s2440 MACH_EZ_S2440 EZ_S2440 1310
++ez_ep9312 MACH_EZ_EP9312 EZ_EP9312 1311
++ez_ep9315 MACH_EZ_EP9315 EZ_EP9315 1312
++ez_x7 MACH_EZ_X7 EZ_X7 1313
++godotdb MACH_GODOTDB GODOTDB 1314
++mistral MACH_MISTRAL MISTRAL 1315
++msm MACH_MSM MSM 1316
++ct5910 MACH_CT5910 CT5910 1317
++ct5912 MACH_CT5912 CT5912 1318
++hynet_ine MACH_HYNET_INE HYNET_INE 1319
++hynet_app MACH_HYNET_APP HYNET_APP 1320
++msm7200 MACH_MSM7200 MSM7200 1321
++msm7600 MACH_MSM7600 MSM7600 1322
++ceb255 MACH_CEB255 CEB255 1323
++ciel MACH_CIEL CIEL 1324
++slm5650 MACH_SLM5650 SLM5650 1325
++at91sam9rlek MACH_AT91SAM9RLEK AT91SAM9RLEK 1326
++comtech_router MACH_COMTECH_ROUTER COMTECH_ROUTER 1327
++sbc2410x MACH_SBC2410X SBC2410X 1328
++at4x0bd MACH_AT4X0BD AT4X0BD 1329
++cbifr MACH_CBIFR CBIFR 1330
++arcom_quantum MACH_ARCOM_QUANTUM ARCOM_QUANTUM 1331
++matrix520 MACH_MATRIX520 MATRIX520 1332
++matrix510 MACH_MATRIX510 MATRIX510 1333
++matrix500 MACH_MATRIX500 MATRIX500 1334
++m501 MACH_M501 M501 1335
++aaeon1270 MACH_AAEON1270 AAEON1270 1336
++matrix500ev MACH_MATRIX500EV MATRIX500EV 1337
++pac500 MACH_PAC500 PAC500 1338
++pnx8181 MACH_PNX8181 PNX8181 1339
++colibri320 MACH_COLIBRI320 COLIBRI320 1340
++aztoolbb MACH_AZTOOLBB AZTOOLBB 1341
++aztoolg2 MACH_AZTOOLG2 AZTOOLG2 1342
++dvlhost MACH_DVLHOST DVLHOST 1343
++zir9200 MACH_ZIR9200 ZIR9200 1344
++zir9260 MACH_ZIR9260 ZIR9260 1345
++cocopah MACH_COCOPAH COCOPAH 1346
++nds MACH_NDS NDS 1347
++rosencrantz MACH_ROSENCRANTZ ROSENCRANTZ 1348
++fttx_odsc MACH_FTTX_ODSC FTTX_ODSC 1349
++classe_r6904 MACH_CLASSE_R6904 CLASSE_R6904 1350
++cam60 MACH_CAM60 CAM60 1351
++mxc30031ads MACH_MXC30031ADS MXC30031ADS 1352
++datacall MACH_DATACALL DATACALL 1353
++at91eb01 MACH_AT91EB01 AT91EB01 1354
++rty MACH_RTY RTY 1355
++dwl2100 MACH_DWL2100 DWL2100 1356
++vinsi MACH_VINSI VINSI 1357
++db88f5281 MACH_DB88F5281 DB88F5281 1358
++csb726 MACH_CSB726 CSB726 1359
++tik27 MACH_TIK27 TIK27 1360
++mx_uc7420 MACH_MX_UC7420 MX_UC7420 1361
++rirm3 MACH_RIRM3 RIRM3 1362
++pelco_odyssey MACH_PELCO_ODYSSEY PELCO_ODYSSEY 1363
++adx_abox MACH_ADX_ABOX ADX_ABOX 1365
++adx_tpid MACH_ADX_TPID ADX_TPID 1366
++minicheck MACH_MINICHECK MINICHECK 1367
++idam MACH_IDAM IDAM 1368
++mario_mx MACH_MARIO_MX MARIO_MX 1369
++vi1888 MACH_VI1888 VI1888 1370
++zr4230 MACH_ZR4230 ZR4230 1371
++t1_ix_blue MACH_T1_IX_BLUE T1_IX_BLUE 1372
++syhq2 MACH_SYHQ2 SYHQ2 1373
++computime_r3 MACH_COMPUTIME_R3 COMPUTIME_R3 1374
++oratis MACH_ORATIS ORATIS 1375
++mikko MACH_MIKKO MIKKO 1376
++holon MACH_HOLON HOLON 1377
++olip8 MACH_OLIP8 OLIP8 1378
++ghi270hg MACH_GHI270HG GHI270HG 1379
++davinci_dm6467_evm MACH_DAVINCI_DM6467_EVM DAVINCI_DM6467_EVM 1380
++davinci_dm355_evm MACH_DAVINCI_DM355_EVM DAVINCI_DM355_EVM 1381
++blackriver MACH_BLACKRIVER BLACKRIVER 1383
++sandgate_wp MACH_SANDGATEWP SANDGATEWP 1384
++cdotbwsg MACH_CDOTBWSG CDOTBWSG 1385
++quark963 MACH_QUARK963 QUARK963 1386
++csb735 MACH_CSB735 CSB735 1387
++littleton MACH_LITTLETON LITTLETON 1388
++mio_p550 MACH_MIO_P550 MIO_P550 1389
++motion2440 MACH_MOTION2440 MOTION2440 1390
++imm500 MACH_IMM500 IMM500 1391
++homematic MACH_HOMEMATIC HOMEMATIC 1392
++ermine MACH_ERMINE ERMINE 1393
++kb9202b MACH_KB9202B KB9202B 1394
++hs1xx MACH_HS1XX HS1XX 1395
++studentmate2440 MACH_STUDENTMATE2440 STUDENTMATE2440 1396
++arvoo_l1_z1 MACH_ARVOO_L1_Z1 ARVOO_L1_Z1 1397
++dep2410k MACH_DEP2410K DEP2410K 1398
++xxsvideo MACH_XXSVIDEO XXSVIDEO 1399
++im4004 MACH_IM4004 IM4004 1400
++ochaya1050 MACH_OCHAYA1050 OCHAYA1050 1401
++lep9261 MACH_LEP9261 LEP9261 1402
++svenmeb MACH_SVENMEB SVENMEB 1403
++fortunet2ne MACH_FORTUNET2NE FORTUNET2NE 1404
++nxhx MACH_NXHX NXHX 1406
++realview_pb11mp MACH_REALVIEW_PB11MP REALVIEW_PB11MP 1407
++ids500 MACH_IDS500 IDS500 1408
++ors_n725 MACH_ORS_N725 ORS_N725 1409
++hsdarm MACH_HSDARM HSDARM 1410
++sha_pon003 MACH_SHA_PON003 SHA_PON003 1411
++sha_pon004 MACH_SHA_PON004 SHA_PON004 1412
++sha_pon007 MACH_SHA_PON007 SHA_PON007 1413
++sha_pon011 MACH_SHA_PON011 SHA_PON011 1414
++h6042 MACH_H6042 H6042 1415
++h6043 MACH_H6043 H6043 1416
++looxc550 MACH_LOOXC550 LOOXC550 1417
++cnty_titan MACH_CNTY_TITAN CNTY_TITAN 1418
++app3xx MACH_APP3XX APP3XX 1419
++sideoatsgrama MACH_SIDEOATSGRAMA SIDEOATSGRAMA 1420
++treo700p MACH_TREO700P TREO700P 1421
++treo700w MACH_TREO700W TREO700W 1422
++treo750 MACH_TREO750 TREO750 1423
++treo755p MACH_TREO755P TREO755P 1424
++ezreganut9200 MACH_EZREGANUT9200 EZREGANUT9200 1425
++sarge MACH_SARGE SARGE 1426
++a696 MACH_A696 A696 1427
++turtle1916 MACH_TURTLE TURTLE 1428
++mx27_3ds MACH_MX27_3DS MX27_3DS 1430
++bishop MACH_BISHOP BISHOP 1431
++pxx MACH_PXX PXX 1432
++redwood MACH_REDWOOD REDWOOD 1433
++omap_2430dlp MACH_OMAP_2430DLP OMAP_2430DLP 1436
++omap_2430osk MACH_OMAP_2430OSK OMAP_2430OSK 1437
++sardine MACH_SARDINE SARDINE 1438
++halibut MACH_HALIBUT HALIBUT 1439
++trout MACH_TROUT TROUT 1440
++goldfish MACH_GOLDFISH GOLDFISH 1441
++gesbc2440 MACH_GESBC2440 GESBC2440 1442
++nomad MACH_NOMAD NOMAD 1443
++rosalind MACH_ROSALIND ROSALIND 1444
++cc9p9215 MACH_CC9P9215 CC9P9215 1445
++cc9p9210 MACH_CC9P9210 CC9P9210 1446
++cc9p9215js MACH_CC9P9215JS CC9P9215JS 1447
++cc9p9210js MACH_CC9P9210JS CC9P9210JS 1448
++nasffe MACH_NASFFE NASFFE 1449
++tn2x0bd MACH_TN2X0BD TN2X0BD 1450
++gwmpxa MACH_GWMPXA GWMPXA 1451
++exyplus MACH_EXYPLUS EXYPLUS 1452
++jadoo21 MACH_JADOO21 JADOO21 1453
++looxn560 MACH_LOOXN560 LOOXN560 1454
++bonsai MACH_BONSAI BONSAI 1455
++adsmilgato MACH_ADSMILGATO ADSMILGATO 1456
++gba MACH_GBA GBA 1457
++h6044 MACH_H6044 H6044 1458
++app MACH_APP APP 1459
++tct_hammer MACH_TCT_HAMMER TCT_HAMMER 1460
++herald MACH_HERALD HERALD 1461
++artemis MACH_ARTEMIS ARTEMIS 1462
++htctitan MACH_HTCTITAN HTCTITAN 1463
++qranium MACH_QRANIUM QRANIUM 1464
++adx_wsc2 MACH_ADX_WSC2 ADX_WSC2 1465
++adx_medcom MACH_ADX_MEDCOM ADX_MEDCOM 1466
++bboard MACH_BBOARD BBOARD 1467
++cambria MACH_CAMBRIA CAMBRIA 1468
++mt7xxx MACH_MT7XXX MT7XXX 1469
++matrix512 MACH_MATRIX512 MATRIX512 1470
++matrix522 MACH_MATRIX522 MATRIX522 1471
++ipac5010 MACH_IPAC5010 IPAC5010 1472
++sakura MACH_SAKURA SAKURA 1473
++grocx MACH_GROCX GROCX 1474
++pm9263 MACH_PM9263 PM9263 1475
++sim_one MACH_SIM_ONE SIM_ONE 1476
++acq132 MACH_ACQ132 ACQ132 1477
++datr MACH_DATR DATR 1478
++actux1 MACH_ACTUX1 ACTUX1 1479
++actux2 MACH_ACTUX2 ACTUX2 1480
++actux3 MACH_ACTUX3 ACTUX3 1481
++flexit MACH_FLEXIT FLEXIT 1482
++bh2x0bd MACH_BH2X0BD BH2X0BD 1483
++atb2002 MACH_ATB2002 ATB2002 1484
++xenon MACH_XENON XENON 1485
++fm607 MACH_FM607 FM607 1486
++matrix514 MACH_MATRIX514 MATRIX514 1487
++matrix524 MACH_MATRIX524 MATRIX524 1488
++inpod MACH_INPOD INPOD 1489
++jive MACH_JIVE JIVE 1490
++tll_mx21 MACH_TLL_MX21 TLL_MX21 1491
++sbc2800 MACH_SBC2800 SBC2800 1492
++cc7ucamry MACH_CC7UCAMRY CC7UCAMRY 1493
++ubisys_p9_sc15 MACH_UBISYS_P9_SC15 UBISYS_P9_SC15 1494
++ubisys_p9_ssc2d10 MACH_UBISYS_P9_SSC2D10 UBISYS_P9_SSC2D10 1495
++ubisys_p9_rcu3 MACH_UBISYS_P9_RCU3 UBISYS_P9_RCU3 1496
++aml_m8000 MACH_AML_M8000 AML_M8000 1497
++snapper_270 MACH_SNAPPER_270 SNAPPER_270 1498
++omap_bbx MACH_OMAP_BBX OMAP_BBX 1499
++ucn2410 MACH_UCN2410 UCN2410 1500
++sam9_l9260 MACH_SAM9_L9260 SAM9_L9260 1501
++eti_c2 MACH_ETI_C2 ETI_C2 1502
++avalanche MACH_AVALANCHE AVALANCHE 1503
++realview_pb1176 MACH_REALVIEW_PB1176 REALVIEW_PB1176 1504
++dp1500 MACH_DP1500 DP1500 1505
++apple_iphone MACH_APPLE_IPHONE APPLE_IPHONE 1506
++yl9200 MACH_YL9200 YL9200 1507
++rd88f5182 MACH_RD88F5182 RD88F5182 1508
++kurobox_pro MACH_KUROBOX_PRO KUROBOX_PRO 1509
++se_poet MACH_SE_POET SE_POET 1510
++mx31_3ds MACH_MX31_3DS MX31_3DS 1511
++r270 MACH_R270 R270 1512
++armour21 MACH_ARMOUR21 ARMOUR21 1513
++dt2 MACH_DT2 DT2 1514
++vt4 MACH_VT4 VT4 1515
++tyco320 MACH_TYCO320 TYCO320 1516
++adma MACH_ADMA ADMA 1517
++wp188 MACH_WP188 WP188 1518
++corsica MACH_CORSICA CORSICA 1519
++bigeye MACH_BIGEYE BIGEYE 1520
++tll5000 MACH_TLL5000 TLL5000 1522
++bebot MACH_BEBOT BEBOT 1523
++qong MACH_QONG QONG 1524
++tcompact MACH_TCOMPACT TCOMPACT 1525
++puma5 MACH_PUMA5 PUMA5 1526
++elara MACH_ELARA ELARA 1527
++ellington MACH_ELLINGTON ELLINGTON 1528
++xda_atom MACH_XDA_ATOM XDA_ATOM 1529
++energizer2 MACH_ENERGIZER2 ENERGIZER2 1530
++odin MACH_ODIN ODIN 1531
++actux4 MACH_ACTUX4 ACTUX4 1532
++esl_omap MACH_ESL_OMAP ESL_OMAP 1533
++omap2evm MACH_OMAP2EVM OMAP2EVM 1534
++omap3evm MACH_OMAP3EVM OMAP3EVM 1535
++adx_pcu57 MACH_ADX_PCU57 ADX_PCU57 1536
++monaco MACH_MONACO MONACO 1537
++levante MACH_LEVANTE LEVANTE 1538
++tmxipx425 MACH_TMXIPX425 TMXIPX425 1539
++leep MACH_LEEP LEEP 1540
++raad MACH_RAAD RAAD 1541
++dns323 MACH_DNS323 DNS323 1542
++ap1000 MACH_AP1000 AP1000 1543
++a9sam6432 MACH_A9SAM6432 A9SAM6432 1544
++shiny MACH_SHINY SHINY 1545
++omap3_beagle MACH_OMAP3_BEAGLE OMAP3_BEAGLE 1546
++csr_bdb2 MACH_CSR_BDB2 CSR_BDB2 1547
++nokia_n810 MACH_NOKIA_N810 NOKIA_N810 1548
++c270 MACH_C270 C270 1549
++sentry MACH_SENTRY SENTRY 1550
++pcm038 MACH_PCM038 PCM038 1551
++anc300 MACH_ANC300 ANC300 1552
++htckaiser MACH_HTCKAISER HTCKAISER 1553
++sbat100 MACH_SBAT100 SBAT100 1554
++modunorm MACH_MODUNORM MODUNORM 1555
++pelos_twarm MACH_PELOS_TWARM PELOS_TWARM 1556
++flank MACH_FLANK FLANK 1557
++sirloin MACH_SIRLOIN SIRLOIN 1558
++brisket MACH_BRISKET BRISKET 1559
++chuck MACH_CHUCK CHUCK 1560
++otter MACH_OTTER OTTER 1561
++davinci_ldk MACH_DAVINCI_LDK DAVINCI_LDK 1562
++phreedom MACH_PHREEDOM PHREEDOM 1563
++sg310 MACH_SG310 SG310 1564
++ts_x09 MACH_TS209 TS209 1565
++at91cap9adk MACH_AT91CAP9ADK AT91CAP9ADK 1566
++tion9315 MACH_TION9315 TION9315 1567
++mast MACH_MAST MAST 1568
++pfw MACH_PFW PFW 1569
++yl_p2440 MACH_YL_P2440 YL_P2440 1570
++zsbc32 MACH_ZSBC32 ZSBC32 1571
++omap_pace2 MACH_OMAP_PACE2 OMAP_PACE2 1572
++imx_pace2 MACH_IMX_PACE2 IMX_PACE2 1573
++mx31moboard MACH_MX31MOBOARD MX31MOBOARD 1574
++mx37_3ds MACH_MX37_3DS MX37_3DS 1575
++rcc MACH_RCC RCC 1576
++dmp MACH_ARM9 ARM9 1577
++vision_ep9307 MACH_VISION_EP9307 VISION_EP9307 1578
++scly1000 MACH_SCLY1000 SCLY1000 1579
++fontel_ep MACH_FONTEL_EP FONTEL_EP 1580
++voiceblue3g MACH_VOICEBLUE3G VOICEBLUE3G 1581
++tt9200 MACH_TT9200 TT9200 1582
++digi2410 MACH_DIGI2410 DIGI2410 1583
++terastation_pro2 MACH_TERASTATION_PRO2 TERASTATION_PRO2 1584
++linkstation_pro MACH_LINKSTATION_PRO LINKSTATION_PRO 1585
++motorola_a780 MACH_MOTOROLA_A780 MOTOROLA_A780 1587
++motorola_e6 MACH_MOTOROLA_E6 MOTOROLA_E6 1588
++motorola_e2 MACH_MOTOROLA_E2 MOTOROLA_E2 1589
++motorola_e680 MACH_MOTOROLA_E680 MOTOROLA_E680 1590
++ur2410 MACH_UR2410 UR2410 1591
++tas9261 MACH_TAS9261 TAS9261 1592
++davinci_hermes_hd MACH_HERMES_HD HERMES_HD 1593
++davinci_perseo_hd MACH_PERSEO_HD PERSEO_HD 1594
++stargazer2 MACH_STARGAZER2 STARGAZER2 1595
++e350 MACH_E350 E350 1596
++wpcm450 MACH_WPCM450 WPCM450 1597
++cartesio MACH_CARTESIO CARTESIO 1598
++toybox MACH_TOYBOX TOYBOX 1599
++tx27 MACH_TX27 TX27 1600
++ts409 MACH_TS409 TS409 1601
++p300 MACH_P300 P300 1602
++xdacomet MACH_XDACOMET XDACOMET 1603
++dexflex2 MACH_DEXFLEX2 DEXFLEX2 1604
++ow MACH_OW OW 1605
++armebs3 MACH_ARMEBS3 ARMEBS3 1606
++u3 MACH_U3 U3 1607
++smdk2450 MACH_SMDK2450 SMDK2450 1608
++rsi_ews MACH_RSI_EWS RSI_EWS 1609
++tnb MACH_TNB TNB 1610
++toepath MACH_TOEPATH TOEPATH 1611
++kb9263 MACH_KB9263 KB9263 1612
++mt7108 MACH_MT7108 MT7108 1613
++smtr2440 MACH_SMTR2440 SMTR2440 1614
++manao MACH_MANAO MANAO 1615
++cm_x300 MACH_CM_X300 CM_X300 1616
++gulfstream_kp MACH_GULFSTREAM_KP GULFSTREAM_KP 1617
++lanreadyfn522 MACH_LANREADYFN522 LANREADYFN522 1618
++arma37 MACH_ARMA37 ARMA37 1619
++mendel MACH_MENDEL MENDEL 1620
++pelco_iliad MACH_PELCO_ILIAD PELCO_ILIAD 1621
++unit2p MACH_UNIT2P UNIT2P 1622
++inc20otter MACH_INC20OTTER INC20OTTER 1623
++at91sam9g20ek MACH_AT91SAM9G20EK AT91SAM9G20EK 1624
++sc_ge2 MACH_STORCENTER STORCENTER 1625
++smdk6410 MACH_SMDK6410 SMDK6410 1626
++u300 MACH_U300 U300 1627
++u500 MACH_U500 U500 1628
++ds9260 MACH_DS9260 DS9260 1629
++riverrock MACH_RIVERROCK RIVERROCK 1630
++scibath MACH_SCIBATH SCIBATH 1631
++at91sam7se MACH_AT91SAM7SE512EK AT91SAM7SE512EK 1632
++wrt350n_v2 MACH_WRT350N_V2 WRT350N_V2 1633
++multimedia MACH_MULTIMEDIA MULTIMEDIA 1634
++marvin MACH_MARVIN MARVIN 1635
++x500 MACH_X500 X500 1636
++awlug4lcu MACH_AWLUG4LCU AWLUG4LCU 1637
++palermoc MACH_PALERMOC PALERMOC 1638
++omap_ldp MACH_OMAP_LDP OMAP_LDP 1639
++ip500 MACH_IP500 IP500 1640
++ase2 MACH_ASE2 ASE2 1642
++mx35evb MACH_MX35EVB MX35EVB 1643
++aml_m8050 MACH_AML_M8050 AML_M8050 1644
++mx35_3ds MACH_MX35_3DS MX35_3DS 1645
++mars MACH_MARS MARS 1646
++neuros_osd2 MACH_NEUROS_OSD2 NEUROS_OSD2 1647
++badger MACH_BADGER BADGER 1648
++trizeps4wl MACH_TRIZEPS4WL TRIZEPS4WL 1649
++trizeps5 MACH_TRIZEPS5 TRIZEPS5 1650
++marlin MACH_MARLIN MARLIN 1651
++ts78xx MACH_TS78XX TS78XX 1652
++hpipaq214 MACH_HPIPAQ214 HPIPAQ214 1653
++at572d940dcm MACH_AT572D940DCM AT572D940DCM 1654
++ne1board MACH_NE1BOARD NE1BOARD 1655
++zante MACH_ZANTE ZANTE 1656
++sffsdr MACH_SFFSDR SFFSDR 1657
++tw2662 MACH_TW2662 TW2662 1658
++vf10xx MACH_VF10XX VF10XX 1659
++zoran43xx MACH_ZORAN43XX ZORAN43XX 1660
++sonix926 MACH_SONIX926 SONIX926 1661
++celestialsemi MACH_CELESTIALSEMI CELESTIALSEMI 1662
++cc9m2443js MACH_CC9M2443JS CC9M2443JS 1663
++tw5334 MACH_TW5334 TW5334 1664
++omap_htcartemis MACH_HTCARTEMIS HTCARTEMIS 1665
++nal_hlite MACH_NAL_HLITE NAL_HLITE 1666
++htcvogue MACH_HTCVOGUE HTCVOGUE 1667
++smartweb MACH_SMARTWEB SMARTWEB 1668
++mv86xx MACH_MV86XX MV86XX 1669
++mv87xx MACH_MV87XX MV87XX 1670
++songyoungho MACH_SONGYOUNGHO SONGYOUNGHO 1671
++younghotema MACH_YOUNGHOTEMA YOUNGHOTEMA 1672
++pcm037 MACH_PCM037 PCM037 1673
++mmvp MACH_MMVP MMVP 1674
++mmap MACH_MMAP MMAP 1675
++ptid2410 MACH_PTID2410 PTID2410 1676
++james_926 MACH_JAMES_926 JAMES_926 1677
++fm6000 MACH_FM6000 FM6000 1678
++db88f6281_bp MACH_DB88F6281_BP DB88F6281_BP 1680
++rd88f6192_nas MACH_RD88F6192_NAS RD88F6192_NAS 1681
++rd88f6281 MACH_RD88F6281 RD88F6281 1682
++db78x00_bp MACH_DB78X00_BP DB78X00_BP 1683
++smdk2416 MACH_SMDK2416 SMDK2416 1685
++oce_spider_si MACH_OCE_SPIDER_SI OCE_SPIDER_SI 1686
++oce_spider_sk MACH_OCE_SPIDER_SK OCE_SPIDER_SK 1687
++rovern6 MACH_ROVERN6 ROVERN6 1688
++pelco_evolution MACH_PELCO_EVOLUTION PELCO_EVOLUTION 1689
++wbd111 MACH_WBD111 WBD111 1690
++elaracpe MACH_ELARACPE ELARACPE 1691
++mabv3 MACH_MABV3 MABV3 1692
++mv2120 MACH_MV2120 MV2120 1693
++csb737 MACH_CSB737 CSB737 1695
++mx51_3ds MACH_MX51_3DS MX51_3DS 1696
++g900 MACH_G900 G900 1697
++apf27 MACH_APF27 APF27 1698
++ggus2000 MACH_GGUS2000 GGUS2000 1699
++omap_2430_mimic MACH_OMAP_2430_MIMIC OMAP_2430_MIMIC 1700
++imx27lite MACH_IMX27LITE IMX27LITE 1701
++almex MACH_ALMEX ALMEX 1702
++control MACH_CONTROL CONTROL 1703
++mba2410 MACH_MBA2410 MBA2410 1704
++volcano MACH_VOLCANO VOLCANO 1705
++zenith MACH_ZENITH ZENITH 1706
++muchip MACH_MUCHIP MUCHIP 1707
++magellan MACH_MAGELLAN MAGELLAN 1708
++usb_a9260 MACH_USB_A9260 USB_A9260 1709
++usb_a9263 MACH_USB_A9263 USB_A9263 1710
++qil_a9260 MACH_QIL_A9260 QIL_A9260 1711
++cme9210 MACH_CME9210 CME9210 1712
++hczh4 MACH_HCZH4 HCZH4 1713
++spearbasic MACH_SPEARBASIC SPEARBASIC 1714
++dep2440 MACH_DEP2440 DEP2440 1715
++hdl_gxr MACH_HDL_GXR HDL_GXR 1716
++hdl_gt MACH_HDL_GT HDL_GT 1717
++hdl_4g MACH_HDL_4G HDL_4G 1718
++s3c6000 MACH_S3C6000 S3C6000 1719
++mmsp2_mdk MACH_MMSP2_MDK MMSP2_MDK 1720
++mpx220 MACH_MPX220 MPX220 1721
++kzm_arm11_01 MACH_KZM_ARM11_01 KZM_ARM11_01 1722
++htc_polaris MACH_HTC_POLARIS HTC_POLARIS 1723
++htc_kaiser MACH_HTC_KAISER HTC_KAISER 1724
++lg_ks20 MACH_LG_KS20 LG_KS20 1725
++hhgps MACH_HHGPS HHGPS 1726
++nokia_n810_wimax MACH_NOKIA_N810_WIMAX NOKIA_N810_WIMAX 1727
++insight MACH_INSIGHT INSIGHT 1728
++sapphire MACH_SAPPHIRE SAPPHIRE 1729
++csb637xo MACH_CSB637XO CSB637XO 1730
++evisiong MACH_EVISIONG EVISIONG 1731
++stmp37xx MACH_STMP37XX STMP37XX 1732
++stmp378x MACH_STMP378X STMP378X 1733
++tnt MACH_TNT TNT 1734
++tbxt MACH_TBXT TBXT 1735
++playmate MACH_PLAYMATE PLAYMATE 1736
++pns10 MACH_PNS10 PNS10 1737
++eznavi MACH_EZNAVI EZNAVI 1738
++ps4000 MACH_PS4000 PS4000 1739
++ezx_a780 MACH_EZX_A780 EZX_A780 1740
++ezx_e680 MACH_EZX_E680 EZX_E680 1741
++ezx_a1200 MACH_EZX_A1200 EZX_A1200 1742
++ezx_e6 MACH_EZX_E6 EZX_E6 1743
++ezx_e2 MACH_EZX_E2 EZX_E2 1744
++ezx_a910 MACH_EZX_A910 EZX_A910 1745
++cwmx31 MACH_CWMX31 CWMX31 1746
++sl2312 MACH_SL2312 SL2312 1747
++blenny MACH_BLENNY BLENNY 1748
++ds107 MACH_DS107 DS107 1749
++dsx07 MACH_DSX07 DSX07 1750
++picocom1 MACH_PICOCOM1 PICOCOM1 1751
++lynx_wolverine MACH_LYNX_WOLVERINE LYNX_WOLVERINE 1752
++ubisys_p9_sc19 MACH_UBISYS_P9_SC19 UBISYS_P9_SC19 1753
++kratos_low MACH_KRATOS_LOW KRATOS_LOW 1754
++m700 MACH_M700 M700 1755
++edmini_v2 MACH_EDMINI_V2 EDMINI_V2 1756
++zipit2 MACH_ZIPIT2 ZIPIT2 1757
++hslfemtocell MACH_HSLFEMTOCELL HSLFEMTOCELL 1758
++daintree_at91 MACH_DAINTREE_AT91 DAINTREE_AT91 1759
++sg560usb MACH_SG560USB SG560USB 1760
++omap3_pandora MACH_OMAP3_PANDORA OMAP3_PANDORA 1761
++usr8200 MACH_USR8200 USR8200 1762
++s1s65k MACH_S1S65K S1S65K 1763
++s2s65a MACH_S2S65A S2S65A 1764
++icore MACH_ICORE ICORE 1765
++mss2 MACH_MSS2 MSS2 1766
++belmont MACH_BELMONT BELMONT 1767
++asusp525 MACH_ASUSP525 ASUSP525 1768
++lb88rc8480 MACH_LB88RC8480 LB88RC8480 1769
++hipxa MACH_HIPXA HIPXA 1770
++mx25_3ds MACH_MX25_3DS MX25_3DS 1771
++m800 MACH_M800 M800 1772
++omap3530_lv_som MACH_OMAP3530_LV_SOM OMAP3530_LV_SOM 1773
++prima_evb MACH_PRIMA_EVB PRIMA_EVB 1774
++mx31bt1 MACH_MX31BT1 MX31BT1 1775
++atlas4_evb MACH_ATLAS4_EVB ATLAS4_EVB 1776
++mx31cicada MACH_MX31CICADA MX31CICADA 1777
++mi424wr MACH_MI424WR MI424WR 1778
++axs_ultrax MACH_AXS_ULTRAX AXS_ULTRAX 1779
++at572d940deb MACH_AT572D940DEB AT572D940DEB 1780
++davinci_da830_evm MACH_DAVINCI_DA830_EVM DAVINCI_DA830_EVM 1781
++ep9302 MACH_EP9302 EP9302 1782
++at572d940hfek MACH_AT572D940HFEB AT572D940HFEB 1783
++cybook3 MACH_CYBOOK3 CYBOOK3 1784
++wdg002 MACH_WDG002 WDG002 1785
++sg560adsl MACH_SG560ADSL SG560ADSL 1786
++nextio_n2800_ica MACH_NEXTIO_N2800_ICA NEXTIO_N2800_ICA 1787
++dove_db MACH_DOVE_DB DOVE_DB 1788
++marvell_newdb MACH_MARVELL_NEWDB MARVELL_NEWDB 1789
++vandihud MACH_VANDIHUD VANDIHUD 1790
++magx_e8 MACH_MAGX_E8 MAGX_E8 1791
++magx_z6 MACH_MAGX_Z6 MAGX_Z6 1792
++magx_v8 MACH_MAGX_V8 MAGX_V8 1793
++magx_u9 MACH_MAGX_U9 MAGX_U9 1794
++toughcf08 MACH_TOUGHCF08 TOUGHCF08 1795
++zw4400 MACH_ZW4400 ZW4400 1796
++marat91 MACH_MARAT91 MARAT91 1797
++overo MACH_OVERO OVERO 1798
++at2440evb MACH_AT2440EVB AT2440EVB 1799
++neocore926 MACH_NEOCORE926 NEOCORE926 1800
++wnr854t MACH_WNR854T WNR854T 1801
++imx27 MACH_IMX27 IMX27 1802
++moose_db MACH_MOOSE_DB MOOSE_DB 1803
++fab4 MACH_FAB4 FAB4 1804
++htcdiamond MACH_HTCDIAMOND HTCDIAMOND 1805
++fiona MACH_FIONA FIONA 1806
++mxc30030_x MACH_MXC30030_X MXC30030_X 1807
++bmp1000 MACH_BMP1000 BMP1000 1808
++logi9200 MACH_LOGI9200 LOGI9200 1809
++tqma31 MACH_TQMA31 TQMA31 1810
++ccw9p9215js MACH_CCW9P9215JS CCW9P9215JS 1811
++rd88f5181l_ge MACH_RD88F5181L_GE RD88F5181L_GE 1812
++sifmain MACH_SIFMAIN SIFMAIN 1813
++sam9_l9261 MACH_SAM9_L9261 SAM9_L9261 1814
++cc9m2443 MACH_CC9M2443 CC9M2443 1815
++xaria300 MACH_XARIA300 XARIA300 1816
++it9200 MACH_IT9200 IT9200 1817
++rd88f5181l_fxo MACH_RD88F5181L_FXO RD88F5181L_FXO 1818
++kriss_sensor MACH_KRISS_SENSOR KRISS_SENSOR 1819
++pilz_pmi5 MACH_PILZ_PMI5 PILZ_PMI5 1820
++jade MACH_JADE JADE 1821
++ks8695_softplc MACH_KS8695_SOFTPLC KS8695_SOFTPLC 1822
++gprisc3 MACH_GPRISC3 GPRISC3 1823
++stamp9g20 MACH_STAMP9G20 STAMP9G20 1824
++smdk6430 MACH_SMDK6430 SMDK6430 1825
++smdkc100 MACH_SMDKC100 SMDKC100 1826
++tavorevb MACH_TAVOREVB TAVOREVB 1827
++saar MACH_SAAR SAAR 1828
++deister_eyecam MACH_DEISTER_EYECAM DEISTER_EYECAM 1829
++at91sam9m10g45ek MACH_AT91SAM9M10G45EK AT91SAM9M10G45EK 1830
++linkstation_produo MACH_LINKSTATION_PRODUO LINKSTATION_PRODUO 1831
++hit_b0 MACH_HIT_B0 HIT_B0 1832
++adx_rmu MACH_ADX_RMU ADX_RMU 1833
++xg_cpe_main MACH_XG_CPE_MAIN XG_CPE_MAIN 1834
++edb9407a MACH_EDB9407A EDB9407A 1835
++dtb9608 MACH_DTB9608 DTB9608 1836
++em104v1 MACH_EM104V1 EM104V1 1837
++demo MACH_DEMO DEMO 1838
++logi9260 MACH_LOGI9260 LOGI9260 1839
++mx31_exm32 MACH_MX31_EXM32 MX31_EXM32 1840
++usb_a9g20 MACH_USB_A9G20 USB_A9G20 1841
++picproje2008 MACH_PICPROJE2008 PICPROJE2008 1842
++cs_e9315 MACH_CS_E9315 CS_E9315 1843
++qil_a9g20 MACH_QIL_A9G20 QIL_A9G20 1844
++sha_pon020 MACH_SHA_PON020 SHA_PON020 1845
++nad MACH_NAD NAD 1846
++sbc35_a9260 MACH_SBC35_A9260 SBC35_A9260 1847
++sbc35_a9g20 MACH_SBC35_A9G20 SBC35_A9G20 1848
++davinci_beginning MACH_DAVINCI_BEGINNING DAVINCI_BEGINNING 1849
++uwc MACH_UWC UWC 1850
++mxlads MACH_MXLADS MXLADS 1851
++htcnike MACH_HTCNIKE HTCNIKE 1852
++deister_pxa270 MACH_DEISTER_PXA270 DEISTER_PXA270 1853
++cme9210js MACH_CME9210JS CME9210JS 1854
++cc9p9360 MACH_CC9P9360 CC9P9360 1855
++mocha MACH_MOCHA MOCHA 1856
++wapd170ag MACH_WAPD170AG WAPD170AG 1857
++linkstation_mini MACH_LINKSTATION_MINI LINKSTATION_MINI 1858
++afeb9260 MACH_AFEB9260 AFEB9260 1859
++w90x900 MACH_W90X900 W90X900 1860
++w90x700 MACH_W90X700 W90X700 1861
++kt300ip MACH_KT300IP KT300IP 1862
++kt300ip_g20 MACH_KT300IP_G20 KT300IP_G20 1863
++srcm MACH_SRCM SRCM 1864
++wlnx_9260 MACH_WLNX_9260 WLNX_9260 1865
++openmoko_gta03 MACH_OPENMOKO_GTA03 OPENMOKO_GTA03 1866
++osprey2 MACH_OSPREY2 OSPREY2 1867
++kbio9260 MACH_KBIO9260 KBIO9260 1868
++ginza MACH_GINZA GINZA 1869
++a636n MACH_A636N A636N 1870
++imx27ipcam MACH_IMX27IPCAM IMX27IPCAM 1871
++nemoc MACH_NEMOC NEMOC 1872
++geneva MACH_GENEVA GENEVA 1873
++htcpharos MACH_HTCPHAROS HTCPHAROS 1874
++neonc MACH_NEONC NEONC 1875
++nas7100 MACH_NAS7100 NAS7100 1876
++teuphone MACH_TEUPHONE TEUPHONE 1877
++annax_eth2 MACH_ANNAX_ETH2 ANNAX_ETH2 1878
++csb733 MACH_CSB733 CSB733 1879
++bk3 MACH_BK3 BK3 1880
++omap_em32 MACH_OMAP_EM32 OMAP_EM32 1881
++et9261cp MACH_ET9261CP ET9261CP 1882
++jasperc MACH_JASPERC JASPERC 1883
++issi_arm9 MACH_ISSI_ARM9 ISSI_ARM9 1884
++ued MACH_UED UED 1885
++esiblade MACH_ESIBLADE ESIBLADE 1886
++eye02 MACH_EYE02 EYE02 1887
++imx27kbd MACH_IMX27KBD IMX27KBD 1888
++sst61vc010_fpga MACH_SST61VC010_FPGA SST61VC010_FPGA 1889
++kixvp435 MACH_KIXVP435 KIXVP435 1890
++kixnp435 MACH_KIXNP435 KIXNP435 1891
++africa MACH_AFRICA AFRICA 1892
++nh233 MACH_NH233 NH233 1893
++rd88f6183ap_ge MACH_RD88F6183AP_GE RD88F6183AP_GE 1894
++bcm4760 MACH_BCM4760 BCM4760 1895
++eddy_v2 MACH_EDDY_V2 EDDY_V2 1896
++realview_pba8 MACH_REALVIEW_PBA8 REALVIEW_PBA8 1897
++hid_a7 MACH_HID_A7 HID_A7 1898
++hero MACH_HERO HERO 1899
++omap_poseidon MACH_OMAP_POSEIDON OMAP_POSEIDON 1900
++realview_pbx MACH_REALVIEW_PBX REALVIEW_PBX 1901
++micro9s MACH_MICRO9S MICRO9S 1902
++mako MACH_MAKO MAKO 1903
++xdaflame MACH_XDAFLAME XDAFLAME 1904
++phidget_sbc2 MACH_PHIDGET_SBC2 PHIDGET_SBC2 1905
++limestone MACH_LIMESTONE LIMESTONE 1906
++iprobe_c32 MACH_IPROBE_C32 IPROBE_C32 1907
++rut100 MACH_RUT100 RUT100 1908
++asusp535 MACH_ASUSP535 ASUSP535 1909
++htcraphael MACH_HTCRAPHAEL HTCRAPHAEL 1910
++sygdg1 MACH_SYGDG1 SYGDG1 1911
++sygdg2 MACH_SYGDG2 SYGDG2 1912
++seoul MACH_SEOUL SEOUL 1913
++salerno MACH_SALERNO SALERNO 1914
++ucn_s3c64xx MACH_UCN_S3C64XX UCN_S3C64XX 1915
++msm7201a MACH_MSM7201A MSM7201A 1916
++lpr1 MACH_LPR1 LPR1 1917
++armadillo500fx MACH_ARMADILLO500FX ARMADILLO500FX 1918
++g3evm MACH_G3EVM G3EVM 1919
++z3_dm355 MACH_Z3_DM355 Z3_DM355 1920
++w90p910evb MACH_W90P910EVB W90P910EVB 1921
++w90p920evb MACH_W90P920EVB W90P920EVB 1922
++w90p950evb MACH_W90P950EVB W90P950EVB 1923
++w90n960evb MACH_W90N960EVB W90N960EVB 1924
++camhd MACH_CAMHD CAMHD 1925
++mvc100 MACH_MVC100 MVC100 1926
++electrum_200 MACH_ELECTRUM_200 ELECTRUM_200 1927
++htcjade MACH_HTCJADE HTCJADE 1928
++memphis MACH_MEMPHIS MEMPHIS 1929
++imx27sbc MACH_IMX27SBC IMX27SBC 1930
++lextar MACH_LEXTAR LEXTAR 1931
++mv88f6281gtw_ge MACH_MV88F6281GTW_GE MV88F6281GTW_GE 1932
++ncp MACH_NCP NCP 1933
++z32an_series MACH_Z32AN Z32AN 1934
++tmq_capd MACH_TMQ_CAPD TMQ_CAPD 1935
++omap3_wl MACH_OMAP3_WL OMAP3_WL 1936
++chumby MACH_CHUMBY CHUMBY 1937
++atsarm9 MACH_ATSARM9 ATSARM9 1938
++davinci_dm365_evm MACH_DAVINCI_DM365_EVM DAVINCI_DM365_EVM 1939
++bahamas MACH_BAHAMAS BAHAMAS 1940
++das MACH_DAS DAS 1941
++minidas MACH_MINIDAS MINIDAS 1942
++vk1000 MACH_VK1000 VK1000 1943
++centro MACH_CENTRO CENTRO 1944
++ctera_2bay MACH_CTERA_2BAY CTERA_2BAY 1945
++edgeconnect MACH_EDGECONNECT EDGECONNECT 1946
++nd27000 MACH_ND27000 ND27000 1947
++cobra MACH_GEMALTO_COBRA GEMALTO_COBRA 1948
++ingelabs_comet MACH_INGELABS_COMET INGELABS_COMET 1949
++pollux_wiz MACH_POLLUX_WIZ POLLUX_WIZ 1950
++blackstone MACH_BLACKSTONE BLACKSTONE 1951
++topaz MACH_TOPAZ TOPAZ 1952
++aixle MACH_AIXLE AIXLE 1953
++mw998 MACH_MW998 MW998 1954
++nokia_rx51 MACH_NOKIA_RX51 NOKIA_RX51 1955
++vsc5605ev MACH_VSC5605EV VSC5605EV 1956
++nt98700dk MACH_NT98700DK NT98700DK 1957
++icontact MACH_ICONTACT ICONTACT 1958
++swarco_frcpu MACH_SWARCO_FRCPU SWARCO_FRCPU 1959
++swarco_scpu MACH_SWARCO_SCPU SWARCO_SCPU 1960
++bbox_p16 MACH_BBOX_P16 BBOX_P16 1961
++bstd MACH_BSTD BSTD 1962
++sbc2440ii MACH_SBC2440II SBC2440II 1963
++pcm034 MACH_PCM034 PCM034 1964
++neso MACH_NESO NESO 1965
++wlnx_9g20 MACH_WLNX_9G20 WLNX_9G20 1966
++omap_zoom2 MACH_OMAP_ZOOM2 OMAP_ZOOM2 1967
++totemnova MACH_TOTEMNOVA TOTEMNOVA 1968
++c5000 MACH_C5000 C5000 1969
++unipo_at91sam9263 MACH_UNIPO_AT91SAM9263 UNIPO_AT91SAM9263 1970
++ethernut5 MACH_ETHERNUT5 ETHERNUT5 1971
++arm11 MACH_ARM11 ARM11 1972
++cpuat9260 MACH_CPUAT9260 CPUAT9260 1973
++cpupxa255 MACH_CPUPXA255 CPUPXA255 1974
++eukrea_cpuimx27 MACH_CPUIMX27 CPUIMX27 1975
++cheflux MACH_CHEFLUX CHEFLUX 1976
++eb_cpux9k2 MACH_EB_CPUX9K2 EB_CPUX9K2 1977
++opcotec MACH_OPCOTEC OPCOTEC 1978
++yt MACH_YT YT 1979
++motoq MACH_MOTOQ MOTOQ 1980
++bsb1 MACH_BSB1 BSB1 1981
++acs5k MACH_ACS5K ACS5K 1982
++milan MACH_MILAN MILAN 1983
++quartzv2 MACH_QUARTZV2 QUARTZV2 1984
++rsvp MACH_RSVP RSVP 1985
++rmp200 MACH_RMP200 RMP200 1986
++snapper_9260 MACH_SNAPPER_9260 SNAPPER_9260 1987
++dsm320 MACH_DSM320 DSM320 1988
++adsgcm MACH_ADSGCM ADSGCM 1989
++ase2_400 MACH_ASE2_400 ASE2_400 1990
++pizza MACH_PIZZA PIZZA 1991
++spot_ngpl MACH_SPOT_NGPL SPOT_NGPL 1992
++armata MACH_ARMATA ARMATA 1993
++exeda MACH_EXEDA EXEDA 1994
++mx31sf005 MACH_MX31SF005 MX31SF005 1995
++f5d8231_4_v2 MACH_F5D8231_4_V2 F5D8231_4_V2 1996
++q2440 MACH_Q2440 Q2440 1997
++qq2440 MACH_QQ2440 QQ2440 1998
++mini2440 MACH_MINI2440 MINI2440 1999
++colibri300 MACH_COLIBRI300 COLIBRI300 2000
++jades MACH_JADES JADES 2001
++spark MACH_SPARK SPARK 2002
++benzina MACH_BENZINA BENZINA 2003
++blaze MACH_BLAZE BLAZE 2004
++linkstation_ls_hgl MACH_LINKSTATION_LS_HGL LINKSTATION_LS_HGL 2005
++htckovsky MACH_HTCKOVSKY HTCKOVSKY 2006
++sony_prs505 MACH_SONY_PRS505 SONY_PRS505 2007
++hanlin_v3 MACH_HANLIN_V3 HANLIN_V3 2008
++sapphira MACH_SAPPHIRA SAPPHIRA 2009
++dack_sda_01 MACH_DACK_SDA_01 DACK_SDA_01 2010
++armbox MACH_ARMBOX ARMBOX 2011
++harris_rvp MACH_HARRIS_RVP HARRIS_RVP 2012
++ribaldo MACH_RIBALDO RIBALDO 2013
++agora MACH_AGORA AGORA 2014
++omap3_mini MACH_OMAP3_MINI OMAP3_MINI 2015
++a9sam6432_b MACH_A9SAM6432_B A9SAM6432_B 2016
++usg2410 MACH_USG2410 USG2410 2017
++pc72052_i10_revb MACH_PC72052_I10_REVB PC72052_I10_REVB 2018
++mx35_exm32 MACH_MX35_EXM32 MX35_EXM32 2019
++topas910 MACH_TOPAS910 TOPAS910 2020
++hyena MACH_HYENA HYENA 2021
++pospax MACH_POSPAX POSPAX 2022
++hdl_gx MACH_HDL_GX HDL_GX 2023
++ctera_4bay MACH_CTERA_4BAY CTERA_4BAY 2024
++ctera_plug_c MACH_CTERA_PLUG_C CTERA_PLUG_C 2025
++crwea_plug_i MACH_CRWEA_PLUG_I CRWEA_PLUG_I 2026
++egauge2 MACH_EGAUGE2 EGAUGE2 2027
++didj MACH_DIDJ DIDJ 2028
++m_s3c2443 MACH_MEISTER MEISTER 2029
++htcblackstone MACH_HTCBLACKSTONE HTCBLACKSTONE 2030
++cpuat9g20 MACH_CPUAT9G20 CPUAT9G20 2031
++smdk6440 MACH_SMDK6440 SMDK6440 2032
++omap_35xx_mvp MACH_OMAP_35XX_MVP OMAP_35XX_MVP 2033
++ctera_plug_i MACH_CTERA_PLUG_I CTERA_PLUG_I 2034
++pvg610_100 MACH_PVG610 PVG610 2035
++hprw6815 MACH_HPRW6815 HPRW6815 2036
++omap3_oswald MACH_OMAP3_OSWALD OMAP3_OSWALD 2037
++nas4220b MACH_NAS4220B NAS4220B 2038
++htcraphael_cdma MACH_HTCRAPHAEL_CDMA HTCRAPHAEL_CDMA 2039
++htcdiamond_cdma MACH_HTCDIAMOND_CDMA HTCDIAMOND_CDMA 2040
++scaler MACH_SCALER SCALER 2041
++zylonite2 MACH_ZYLONITE2 ZYLONITE2 2042
++aspenite MACH_ASPENITE ASPENITE 2043
++teton MACH_TETON TETON 2044
++ttc_dkb MACH_TTC_DKB TTC_DKB 2045
++bishop2 MACH_BISHOP2 BISHOP2 2046
++ippv5 MACH_IPPV5 IPPV5 2047
++farm926 MACH_FARM926 FARM926 2048
++mmccpu MACH_MMCCPU MMCCPU 2049
++sgmsfl MACH_SGMSFL SGMSFL 2050
++tt8000 MACH_TT8000 TT8000 2051
++zrn4300lp MACH_ZRN4300LP ZRN4300LP 2052
++mptc MACH_MPTC MPTC 2053
++h6051 MACH_H6051 H6051 2054
++pvg610_101 MACH_PVG610_101 PVG610_101 2055
++stamp9261_pc_evb MACH_STAMP9261_PC_EVB STAMP9261_PC_EVB 2056
++pelco_odysseus MACH_PELCO_ODYSSEUS PELCO_ODYSSEUS 2057
++tny_a9260 MACH_TNY_A9260 TNY_A9260 2058
++tny_a9g20 MACH_TNY_A9G20 TNY_A9G20 2059
++aesop_mp2530f MACH_AESOP_MP2530F AESOP_MP2530F 2060
++dx900 MACH_DX900 DX900 2061
++cpodc2 MACH_CPODC2 CPODC2 2062
++tilt_8925 MACH_TILT_8925 TILT_8925 2063
++davinci_dm357_evm MACH_DAVINCI_DM357_EVM DAVINCI_DM357_EVM 2064
++swordfish MACH_SWORDFISH SWORDFISH 2065
++corvus MACH_CORVUS CORVUS 2066
++taurus MACH_TAURUS TAURUS 2067
++axm MACH_AXM AXM 2068
++axc MACH_AXC AXC 2069
++baby MACH_BABY BABY 2070
++mp200 MACH_MP200 MP200 2071
++pcm043 MACH_PCM043 PCM043 2072
++hanlin_v3c MACH_HANLIN_V3C HANLIN_V3C 2073
++kbk9g20 MACH_KBK9G20 KBK9G20 2074
++adsturbog5 MACH_ADSTURBOG5 ADSTURBOG5 2075
++avenger_lite1 MACH_AVENGER_LITE1 AVENGER_LITE1 2076
++suc82x MACH_SUC SUC 2077
++at91sam7s256 MACH_AT91SAM7S256 AT91SAM7S256 2078
++mendoza MACH_MENDOZA MENDOZA 2079
++kira MACH_KIRA KIRA 2080
++mx1hbm MACH_MX1HBM MX1HBM 2081
++quatro43xx MACH_QUATRO43XX QUATRO43XX 2082
++quatro4230 MACH_QUATRO4230 QUATRO4230 2083
++nsb400 MACH_NSB400 NSB400 2084
++drp255 MACH_DRP255 DRP255 2085
++thoth MACH_THOTH THOTH 2086
++firestone MACH_FIRESTONE FIRESTONE 2087
++asusp750 MACH_ASUSP750 ASUSP750 2088
++ctera_dl MACH_CTERA_DL CTERA_DL 2089
++socr MACH_SOCR SOCR 2090
++htcoxygen MACH_HTCOXYGEN HTCOXYGEN 2091
++heroc MACH_HEROC HEROC 2092
++zeno6800 MACH_ZENO6800 ZENO6800 2093
++sc2mcs MACH_SC2MCS SC2MCS 2094
++gene100 MACH_GENE100 GENE100 2095
++as353x MACH_AS353X AS353X 2096
++sheevaplug MACH_SHEEVAPLUG SHEEVAPLUG 2097
++at91sam9g20 MACH_AT91SAM9G20 AT91SAM9G20 2098
++mv88f6192gtw_fe MACH_MV88F6192GTW_FE MV88F6192GTW_FE 2099
++cc9200 MACH_CC9200 CC9200 2100
++sm9200 MACH_SM9200 SM9200 2101
++tp9200 MACH_TP9200 TP9200 2102
++snapperdv MACH_SNAPPERDV SNAPPERDV 2103
++avengers_lite MACH_AVENGERS_LITE AVENGERS_LITE 2104
++avengers_lite1 MACH_AVENGERS_LITE1 AVENGERS_LITE1 2105
++omap3axon MACH_OMAP3AXON OMAP3AXON 2106
++ma8xx MACH_MA8XX MA8XX 2107
++mp201ek MACH_MP201EK MP201EK 2108
++davinci_tux MACH_DAVINCI_TUX DAVINCI_TUX 2109
++mpa1600 MACH_MPA1600 MPA1600 2110
++pelco_troy MACH_PELCO_TROY PELCO_TROY 2111
++nsb667 MACH_NSB667 NSB667 2112
++rovers5_4mpix MACH_ROVERS5_4MPIX ROVERS5_4MPIX 2113
++twocom MACH_TWOCOM TWOCOM 2114
++ubisys_p9_rcu3r2 MACH_UBISYS_P9_RCU3R2 UBISYS_P9_RCU3R2 2115
++hero_espresso MACH_HERO_ESPRESSO HERO_ESPRESSO 2116
++afeusb MACH_AFEUSB AFEUSB 2117
++t830 MACH_T830 T830 2118
++spd8020_cc MACH_SPD8020_CC SPD8020_CC 2119
++om_3d7k MACH_OM_3D7K OM_3D7K 2120
++picocom2 MACH_PICOCOM2 PICOCOM2 2121
++uwg4mx27 MACH_UWG4MX27 UWG4MX27 2122
++uwg4mx31 MACH_UWG4MX31 UWG4MX31 2123
++cherry MACH_CHERRY CHERRY 2124
++mx51_babbage MACH_MX51_BABBAGE MX51_BABBAGE 2125
++s3c2440turkiye MACH_S3C2440TURKIYE S3C2440TURKIYE 2126
++tx37 MACH_TX37 TX37 2127
++sbc2800_9g20 MACH_SBC2800_9G20 SBC2800_9G20 2128
++benzglb MACH_BENZGLB BENZGLB 2129
++benztd MACH_BENZTD BENZTD 2130
++cartesio_plus MACH_CARTESIO_PLUS CARTESIO_PLUS 2131
++solrad_g20 MACH_SOLRAD_G20 SOLRAD_G20 2132
++mx27wallace MACH_MX27WALLACE MX27WALLACE 2133
++fmzwebmodul MACH_FMZWEBMODUL FMZWEBMODUL 2134
++rd78x00_masa MACH_RD78X00_MASA RD78X00_MASA 2135
++smallogger MACH_SMALLOGGER SMALLOGGER 2136
++ccw9p9215 MACH_CCW9P9215 CCW9P9215 2137
++dm355_leopard MACH_DM355_LEOPARD DM355_LEOPARD 2138
++ts219 MACH_TS219 TS219 2139
++tny_a9263 MACH_TNY_A9263 TNY_A9263 2140
++apollo MACH_APOLLO APOLLO 2141
++at91cap9stk MACH_AT91CAP9STK AT91CAP9STK 2142
++spc300 MACH_SPC300 SPC300 2143
++eko MACH_EKO EKO 2144
++ccw9m2443 MACH_CCW9M2443 CCW9M2443 2145
++ccw9m2443js MACH_CCW9M2443JS CCW9M2443JS 2146
++m2m_router_device MACH_M2M_ROUTER_DEVICE M2M_ROUTER_DEVICE 2147
++str9104nas MACH_STAR9104NAS STAR9104NAS 2148
++pca100 MACH_PCA100 PCA100 2149
++z3_dm365_mod_01 MACH_Z3_DM365_MOD_01 Z3_DM365_MOD_01 2150
++hipox MACH_HIPOX HIPOX 2151
++omap3_piteds MACH_OMAP3_PITEDS OMAP3_PITEDS 2152
++bm150r MACH_BM150R BM150R 2153
++tbone MACH_TBONE TBONE 2154
++merlin MACH_MERLIN MERLIN 2155
++falcon MACH_FALCON FALCON 2156
++davinci_da850_evm MACH_DAVINCI_DA850_EVM DAVINCI_DA850_EVM 2157
++s5p6440 MACH_S5P6440 S5P6440 2158
++at91sam9g10ek MACH_AT91SAM9G10EK AT91SAM9G10EK 2159
++omap_4430sdp MACH_OMAP_4430SDP OMAP_4430SDP 2160
++lpc313x MACH_LPC313X LPC313X 2161
++magx_zn5 MACH_MAGX_ZN5 MAGX_ZN5 2162
++magx_em30 MACH_MAGX_EM30 MAGX_EM30 2163
++magx_ve66 MACH_MAGX_VE66 MAGX_VE66 2164
++meesc MACH_MEESC MEESC 2165
++otc570 MACH_OTC570 OTC570 2166
++bcu2412 MACH_BCU2412 BCU2412 2167
++beacon MACH_BEACON BEACON 2168
++actia_tgw MACH_ACTIA_TGW ACTIA_TGW 2169
++e4430 MACH_E4430 E4430 2170
++ql300 MACH_QL300 QL300 2171
++btmavb101 MACH_BTMAVB101 BTMAVB101 2172
++btmawb101 MACH_BTMAWB101 BTMAWB101 2173
++sq201 MACH_SQ201 SQ201 2174
++quatro45xx MACH_QUATRO45XX QUATRO45XX 2175
++openpad MACH_OPENPAD OPENPAD 2176
++tx25 MACH_TX25 TX25 2177
++omap3_torpedo MACH_OMAP3_TORPEDO OMAP3_TORPEDO 2178
++htcraphael_k MACH_HTCRAPHAEL_K HTCRAPHAEL_K 2179
++lal43 MACH_LAL43 LAL43 2181
++htcraphael_cdma500 MACH_HTCRAPHAEL_CDMA500 HTCRAPHAEL_CDMA500 2182
++anw6410 MACH_ANW6410 ANW6410 2183
++htcprophet MACH_HTCPROPHET HTCPROPHET 2185
++cfa_10022 MACH_CFA_10022 CFA_10022 2186
++imx27_visstrim_m10 MACH_IMX27_VISSTRIM_M10 IMX27_VISSTRIM_M10 2187
++px2imx27 MACH_PX2IMX27 PX2IMX27 2188
++stm3210e_eval MACH_STM3210E_EVAL STM3210E_EVAL 2189
++dvs10 MACH_DVS10 DVS10 2190
++portuxg20 MACH_PORTUXG20 PORTUXG20 2191
++arm_spv MACH_ARM_SPV ARM_SPV 2192
++smdkc110 MACH_SMDKC110 SMDKC110 2193
++cabespresso MACH_CABESPRESSO CABESPRESSO 2194
++hmc800 MACH_HMC800 HMC800 2195
++sholes MACH_SHOLES SHOLES 2196
++btmxc31 MACH_BTMXC31 BTMXC31 2197
++dt501 MACH_DT501 DT501 2198
++ktx MACH_KTX KTX 2199
++omap3517evm MACH_OMAP3517EVM OMAP3517EVM 2200
++netspace_v2 MACH_NETSPACE_V2 NETSPACE_V2 2201
++netspace_max_v2 MACH_NETSPACE_MAX_V2 NETSPACE_MAX_V2 2202
++d2net_v2 MACH_D2NET_V2 D2NET_V2 2203
++net2big_v2 MACH_NET2BIG_V2 NET2BIG_V2 2204
++net4big_v2 MACH_NET4BIG_V2 NET4BIG_V2 2205
++net5big_v2 MACH_NET5BIG_V2 NET5BIG_V2 2206
++endb2443 MACH_ENDB2443 ENDB2443 2207
++inetspace_v2 MACH_INETSPACE_V2 INETSPACE_V2 2208
++tros MACH_TROS TROS 2209
++pelco_homer MACH_PELCO_HOMER PELCO_HOMER 2210
++ofsp8 MACH_OFSP8 OFSP8 2211
++at91sam9g45ekes MACH_AT91SAM9G45EKES AT91SAM9G45EKES 2212
++guf_cupid MACH_GUF_CUPID GUF_CUPID 2213
++eab1r MACH_EAB1R EAB1R 2214
++desirec MACH_DESIREC DESIREC 2215
++cordoba MACH_CORDOBA CORDOBA 2216
++irvine MACH_IRVINE IRVINE 2217
++sff772 MACH_SFF772 SFF772 2218
++pelco_milano MACH_PELCO_MILANO PELCO_MILANO 2219
++pc7302 MACH_PC7302 PC7302 2220
++bip6000 MACH_BIP6000 BIP6000 2221
++silvermoon MACH_SILVERMOON SILVERMOON 2222
++vc0830 MACH_VC0830 VC0830 2223
++dt430 MACH_DT430 DT430 2224
++ji42pf MACH_JI42PF JI42PF 2225
++gnet_ksm MACH_GNET_KSM GNET_KSM 2226
++gnet_sgm MACH_GNET_SGM GNET_SGM 2227
++gnet_sgr MACH_GNET_SGR GNET_SGR 2228
++omap3_icetekevm MACH_OMAP3_ICETEKEVM OMAP3_ICETEKEVM 2229
++pnp MACH_PNP PNP 2230
++ctera_2bay_k MACH_CTERA_2BAY_K CTERA_2BAY_K 2231
++ctera_2bay_u MACH_CTERA_2BAY_U CTERA_2BAY_U 2232
++sas_c MACH_SAS_C SAS_C 2233
++vma2315 MACH_VMA2315 VMA2315 2234
++vcs MACH_VCS VCS 2235
++spear600 MACH_SPEAR600 SPEAR600 2236
++spear300 MACH_SPEAR300 SPEAR300 2237
++spear1300 MACH_SPEAR1300 SPEAR1300 2238
++lilly1131 MACH_LILLY1131 LILLY1131 2239
++arvoo_ax301 MACH_ARVOO_AX301 ARVOO_AX301 2240
++mapphone MACH_MAPPHONE MAPPHONE 2241
++legend MACH_LEGEND LEGEND 2242
++salsa MACH_SALSA SALSA 2243
++lounge MACH_LOUNGE LOUNGE 2244
++vision MACH_VISION VISION 2245
++vmb20 MACH_VMB20 VMB20 2246
++hy2410 MACH_HY2410 HY2410 2247
++hy9315 MACH_HY9315 HY9315 2248
++bullwinkle MACH_BULLWINKLE BULLWINKLE 2249
++arm_ultimator2 MACH_ARM_ULTIMATOR2 ARM_ULTIMATOR2 2250
++vs_v210 MACH_VS_V210 VS_V210 2252
++vs_v212 MACH_VS_V212 VS_V212 2253
++hmt MACH_HMT HMT 2254
++suen3 MACH_SUEN3 SUEN3 2255
++vesper MACH_VESPER VESPER 2256
++str9 MACH_STR9 STR9 2257
++omap3_wl_ff MACH_OMAP3_WL_FF OMAP3_WL_FF 2258
++simcom MACH_SIMCOM SIMCOM 2259
++mcwebio MACH_MCWEBIO MCWEBIO 2260
++omap3_phrazer MACH_OMAP3_PHRAZER OMAP3_PHRAZER 2261
++darwin MACH_DARWIN DARWIN 2262
++oratiscomu MACH_ORATISCOMU ORATISCOMU 2263
++rtsbc20 MACH_RTSBC20 RTSBC20 2264
++sgh_i780 MACH_I780 I780 2265
++gemini324 MACH_GEMINI324 GEMINI324 2266
++oratislan MACH_ORATISLAN ORATISLAN 2267
++oratisalog MACH_ORATISALOG ORATISALOG 2268
++oratismadi MACH_ORATISMADI ORATISMADI 2269
++oratisot16 MACH_ORATISOT16 ORATISOT16 2270
++oratisdesk MACH_ORATISDESK ORATISDESK 2271
++vexpress MACH_VEXPRESS VEXPRESS 2272
++sintexo MACH_SINTEXO SINTEXO 2273
++cm3389 MACH_CM3389 CM3389 2274
++omap3_cio MACH_OMAP3_CIO OMAP3_CIO 2275
++sgh_i900 MACH_SGH_I900 SGH_I900 2276
++bst100 MACH_BST100 BST100 2277
++passion MACH_PASSION PASSION 2278
++indesign_at91sam MACH_INDESIGN_AT91SAM INDESIGN_AT91SAM 2279
++c4_badger MACH_C4_BADGER C4_BADGER 2280
++c4_viper MACH_C4_VIPER C4_VIPER 2281
++d2net MACH_D2NET D2NET 2282
++bigdisk MACH_BIGDISK BIGDISK 2283
++notalvision MACH_NOTALVISION NOTALVISION 2284
++omap3_kboc MACH_OMAP3_KBOC OMAP3_KBOC 2285
++cyclone MACH_CYCLONE CYCLONE 2286
++ninja MACH_NINJA NINJA 2287
++at91sam9g20ek_2mmc MACH_AT91SAM9G20EK_2MMC AT91SAM9G20EK_2MMC 2288
++bcmring MACH_BCMRING BCMRING 2289
++resol_dl2 MACH_RESOL_DL2 RESOL_DL2 2290
++ifosw MACH_IFOSW IFOSW 2291
++htcrhodium MACH_HTCRHODIUM HTCRHODIUM 2292
++htctopaz MACH_HTCTOPAZ HTCTOPAZ 2293
++matrix504 MACH_MATRIX504 MATRIX504 2294
++mrfsa MACH_MRFSA MRFSA 2295
++sc_p270 MACH_SC_P270 SC_P270 2296
++atlas5_evb MACH_ATLAS5_EVB ATLAS5_EVB 2297
++pelco_lobox MACH_PELCO_LOBOX PELCO_LOBOX 2298
++dilax_pcu200 MACH_DILAX_PCU200 DILAX_PCU200 2299
++leonardo MACH_LEONARDO LEONARDO 2300
++zoran_approach7 MACH_ZORAN_APPROACH7 ZORAN_APPROACH7 2301
++dp6xx MACH_DP6XX DP6XX 2302
++bcm2153_vesper MACH_BCM2153_VESPER BCM2153_VESPER 2303
++mahimahi MACH_MAHIMAHI MAHIMAHI 2304
++clickc MACH_CLICKC CLICKC 2305
++zb_gateway MACH_ZB_GATEWAY ZB_GATEWAY 2306
++tazcard MACH_TAZCARD TAZCARD 2307
++tazdev MACH_TAZDEV TAZDEV 2308
++annax_cb_arm MACH_ANNAX_CB_ARM ANNAX_CB_ARM 2309
++annax_dm3 MACH_ANNAX_DM3 ANNAX_DM3 2310
++cerebric MACH_CEREBRIC CEREBRIC 2311
++orca MACH_ORCA ORCA 2312
++pc9260 MACH_PC9260 PC9260 2313
++ems285a MACH_EMS285A EMS285A 2314
++gec2410 MACH_GEC2410 GEC2410 2315
++gec2440 MACH_GEC2440 GEC2440 2316
++mw903 MACH_ARCH_MW903 ARCH_MW903 2317
++mw2440 MACH_MW2440 MW2440 2318
++ecac2378 MACH_ECAC2378 ECAC2378 2319
++tazkiosk MACH_TAZKIOSK TAZKIOSK 2320
++whiterabbit_mch MACH_WHITERABBIT_MCH WHITERABBIT_MCH 2321
++sbox9263 MACH_SBOX9263 SBOX9263 2322
++oreo MACH_OREO OREO 2323
++smdk6442 MACH_SMDK6442 SMDK6442 2324
++openrd_base MACH_OPENRD_BASE OPENRD_BASE 2325
++incredible MACH_INCREDIBLE INCREDIBLE 2326
++incrediblec MACH_INCREDIBLEC INCREDIBLEC 2327
++heroct MACH_HEROCT HEROCT 2328
++mmnet1000 MACH_MMNET1000 MMNET1000 2329
++devkit8000 MACH_DEVKIT8000 DEVKIT8000 2330
++devkit9000 MACH_DEVKIT9000 DEVKIT9000 2331
++mx31txtr MACH_MX31TXTR MX31TXTR 2332
++u380 MACH_U380 U380 2333
++oamp3_hualu MACH_HUALU_BOARD HUALU_BOARD 2334
++npcmx50 MACH_NPCMX50 NPCMX50 2335
++mx51_lange51 MACH_MX51_LANGE51 MX51_LANGE51 2336
++mx51_lange52 MACH_MX51_LANGE52 MX51_LANGE52 2337
++riom MACH_RIOM RIOM 2338
++comcas MACH_COMCAS COMCAS 2339
++wsi_mx27 MACH_WSI_MX27 WSI_MX27 2340
++cm_t35 MACH_CM_T35 CM_T35 2341
++net2big MACH_NET2BIG NET2BIG 2342
++motorola_a1600 MACH_MOTOROLA_A1600 MOTOROLA_A1600 2343
++igep0020 MACH_IGEP0020 IGEP0020 2344
++igep0010 MACH_IGEP0010 IGEP0010 2345
++mv6281gtwge2 MACH_MV6281GTWGE2 MV6281GTWGE2 2346
++scat100 MACH_SCAT100 SCAT100 2347
++sanmina MACH_SANMINA SANMINA 2348
++momento MACH_MOMENTO MOMENTO 2349
++nuc9xx MACH_NUC9XX NUC9XX 2350
++nuc910evb MACH_NUC910EVB NUC910EVB 2351
++nuc920evb MACH_NUC920EVB NUC920EVB 2352
++nuc950evb MACH_NUC950EVB NUC950EVB 2353
++nuc945evb MACH_NUC945EVB NUC945EVB 2354
++nuc960evb MACH_NUC960EVB NUC960EVB 2355
++nuc932evb MACH_NUC932EVB NUC932EVB 2356
++nuc900 MACH_NUC900 NUC900 2357
++sd1soc MACH_SD1SOC SD1SOC 2358
++ln2440bc MACH_LN2440BC LN2440BC 2359
++rsbc MACH_RSBC RSBC 2360
++openrd_client MACH_OPENRD_CLIENT OPENRD_CLIENT 2361
++hpipaq11x MACH_HPIPAQ11X HPIPAQ11X 2362
++wayland MACH_WAYLAND WAYLAND 2363
++acnbsx102 MACH_ACNBSX102 ACNBSX102 2364
++hwat91 MACH_HWAT91 HWAT91 2365
++at91sam9263cs MACH_AT91SAM9263CS AT91SAM9263CS 2366
++csb732 MACH_CSB732 CSB732 2367
++u8500 MACH_U8500 U8500 2368
++huqiu MACH_HUQIU HUQIU 2369
++mx51_kunlun MACH_MX51_KUNLUN MX51_KUNLUN 2370
++pmt1g MACH_PMT1G PMT1G 2371
++htcelf MACH_HTCELF HTCELF 2372
++armadillo420 MACH_ARMADILLO420 ARMADILLO420 2373
++armadillo440 MACH_ARMADILLO440 ARMADILLO440 2374
++u_chip_dual_arm MACH_U_CHIP_DUAL_ARM U_CHIP_DUAL_ARM 2375
++csr_bdb3 MACH_CSR_BDB3 CSR_BDB3 2376
++dolby_cat1018 MACH_DOLBY_CAT1018 DOLBY_CAT1018 2377
++hy9307 MACH_HY9307 HY9307 2378
++aspire_easystore MACH_A_ES A_ES 2379
++davinci_irif MACH_DAVINCI_IRIF DAVINCI_IRIF 2380
++agama9263 MACH_AGAMA9263 AGAMA9263 2381
++marvell_jasper MACH_MARVELL_JASPER MARVELL_JASPER 2382
++flint MACH_FLINT FLINT 2383
++tavorevb3 MACH_TAVOREVB3 TAVOREVB3 2384
++sch_m490 MACH_SCH_M490 SCH_M490 2386
++rbl01 MACH_RBL01 RBL01 2387
++omnifi MACH_OMNIFI OMNIFI 2388
++otavalo MACH_OTAVALO OTAVALO 2389
++sienna MACH_SIENNA SIENNA 2390
++htc_excalibur_s620 MACH_HTC_EXCALIBUR_S620 HTC_EXCALIBUR_S620 2391
++htc_opal MACH_HTC_OPAL HTC_OPAL 2392
++touchbook MACH_TOUCHBOOK TOUCHBOOK 2393
++latte MACH_LATTE LATTE 2394
++xa200 MACH_XA200 XA200 2395
++nimrod MACH_NIMROD NIMROD 2396
++cc9p9215_3g MACH_CC9P9215_3G CC9P9215_3G 2397
++cc9p9215_3gjs MACH_CC9P9215_3GJS CC9P9215_3GJS 2398
++tk71 MACH_TK71 TK71 2399
++comham3525 MACH_COMHAM3525 COMHAM3525 2400
++mx31erebus MACH_MX31EREBUS MX31EREBUS 2401
++mcardmx27 MACH_MCARDMX27 MCARDMX27 2402
++paradise MACH_PARADISE PARADISE 2403
++tide MACH_TIDE TIDE 2404
++wzl2440 MACH_WZL2440 WZL2440 2405
++sdrdemo MACH_SDRDEMO SDRDEMO 2406
++ethercan2 MACH_ETHERCAN2 ETHERCAN2 2407
++ecmimg20 MACH_ECMIMG20 ECMIMG20 2408
++omap_dragon MACH_OMAP_DRAGON OMAP_DRAGON 2409
++halo MACH_HALO HALO 2410
++huangshan MACH_HUANGSHAN HUANGSHAN 2411
++vl_ma2sc MACH_VL_MA2SC VL_MA2SC 2412
++raumfeld_rc MACH_RAUMFELD_RC RAUMFELD_RC 2413
++raumfeld_connector MACH_RAUMFELD_CONNECTOR RAUMFELD_CONNECTOR 2414
++raumfeld_speaker MACH_RAUMFELD_SPEAKER RAUMFELD_SPEAKER 2415
++multibus_master MACH_MULTIBUS_MASTER MULTIBUS_MASTER 2416
++multibus_pbk MACH_MULTIBUS_PBK MULTIBUS_PBK 2417
++tnetv107x MACH_TNETV107X TNETV107X 2418
++snake MACH_SNAKE SNAKE 2419
++cwmx27 MACH_CWMX27 CWMX27 2420
++sch_m480 MACH_SCH_M480 SCH_M480 2421
++platypus MACH_PLATYPUS PLATYPUS 2422
++pss2 MACH_PSS2 PSS2 2423
++davinci_apm150 MACH_DAVINCI_APM150 DAVINCI_APM150 2424
++str9100 MACH_STR9100 STR9100 2425
++net5big MACH_NET5BIG NET5BIG 2426
++seabed9263 MACH_SEABED9263 SEABED9263 2427
++mx51_m2id MACH_MX51_M2ID MX51_M2ID 2428
++octvocplus_eb MACH_OCTVOCPLUS_EB OCTVOCPLUS_EB 2429
++klk_firefox MACH_KLK_FIREFOX KLK_FIREFOX 2430
++klk_wirma_module MACH_KLK_WIRMA_MODULE KLK_WIRMA_MODULE 2431
++klk_wirma_mmi MACH_KLK_WIRMA_MMI KLK_WIRMA_MMI 2432
++supersonic MACH_SUPERSONIC SUPERSONIC 2433
++liberty MACH_LIBERTY LIBERTY 2434
++mh355 MACH_MH355 MH355 2435
++pc7802 MACH_PC7802 PC7802 2436
++gnet_sgc MACH_GNET_SGC GNET_SGC 2437
++einstein15 MACH_EINSTEIN15 EINSTEIN15 2438
++cmpd MACH_CMPD CMPD 2439
++davinci_hase1 MACH_DAVINCI_HASE1 DAVINCI_HASE1 2440
++lgeincitephone MACH_LGEINCITEPHONE LGEINCITEPHONE 2441
++ea313x MACH_EA313X EA313X 2442
++fwbd_39064 MACH_FWBD_39064 FWBD_39064 2443
++fwbd_390128 MACH_FWBD_390128 FWBD_390128 2444
++pelco_moe MACH_PELCO_MOE PELCO_MOE 2445
++minimix27 MACH_MINIMIX27 MINIMIX27 2446
++omap3_thunder MACH_OMAP3_THUNDER OMAP3_THUNDER 2447
++passionc MACH_PASSIONC PASSIONC 2448
++mx27amata MACH_MX27AMATA MX27AMATA 2449
++bgat1 MACH_BGAT1 BGAT1 2450
++buzz MACH_BUZZ BUZZ 2451
++mb9g20 MACH_MB9G20 MB9G20 2452
++yushan MACH_YUSHAN YUSHAN 2453
++lizard MACH_LIZARD LIZARD 2454
++omap3polycom MACH_OMAP3POLYCOM OMAP3POLYCOM 2455
++smdkv210 MACH_SMDKV210 SMDKV210 2456
++bravo MACH_BRAVO BRAVO 2457
++siogentoo1 MACH_SIOGENTOO1 SIOGENTOO1 2458
++siogentoo2 MACH_SIOGENTOO2 SIOGENTOO2 2459
++sm3k MACH_SM3K SM3K 2460
++acer_tempo_f900 MACH_ACER_TEMPO_F900 ACER_TEMPO_F900 2461
++sst61vc010_dev MACH_SST61VC010_DEV SST61VC010_DEV 2462
++glittertind MACH_GLITTERTIND GLITTERTIND 2463
++omap_zoom3 MACH_OMAP_ZOOM3 OMAP_ZOOM3 2464
++omap_3630sdp MACH_OMAP_3630SDP OMAP_3630SDP 2465
++cybook2440 MACH_CYBOOK2440 CYBOOK2440 2466
++torino_s MACH_TORINO_S TORINO_S 2467
++havana MACH_HAVANA HAVANA 2468
++beaumont_11 MACH_BEAUMONT_11 BEAUMONT_11 2469
++vanguard MACH_VANGUARD VANGUARD 2470
++s5pc110_draco MACH_S5PC110_DRACO S5PC110_DRACO 2471
++cartesio_two MACH_CARTESIO_TWO CARTESIO_TWO 2472
++aster MACH_ASTER ASTER 2473
++voguesv210 MACH_VOGUESV210 VOGUESV210 2474
++acm500x MACH_ACM500X ACM500X 2475
++km9260 MACH_KM9260 KM9260 2476
++nideflexg1 MACH_NIDEFLEXG1 NIDEFLEXG1 2477
++ctera_plug_io MACH_CTERA_PLUG_IO CTERA_PLUG_IO 2478
++smartq7 MACH_SMARTQ7 SMARTQ7 2479
++at91sam9g10ek2 MACH_AT91SAM9G10EK2 AT91SAM9G10EK2 2480
++asusp527 MACH_ASUSP527 ASUSP527 2481
++at91sam9g20mpm2 MACH_AT91SAM9G20MPM2 AT91SAM9G20MPM2 2482
++topasa900 MACH_TOPASA900 TOPASA900 2483
++electrum_100 MACH_ELECTRUM_100 ELECTRUM_100 2484
++mx51grb MACH_MX51GRB MX51GRB 2485
++xea300 MACH_XEA300 XEA300 2486
++htcstartrek MACH_HTCSTARTREK HTCSTARTREK 2487
++lima MACH_LIMA LIMA 2488
++csb740 MACH_CSB740 CSB740 2489
++usb_s8815 MACH_USB_S8815 USB_S8815 2490
++watson_efm_plugin MACH_WATSON_EFM_PLUGIN WATSON_EFM_PLUGIN 2491
++milkyway MACH_MILKYWAY MILKYWAY 2492
++g4evm MACH_G4EVM G4EVM 2493
++picomod6 MACH_PICOMOD6 PICOMOD6 2494
++omapl138_hawkboard MACH_OMAPL138_HAWKBOARD OMAPL138_HAWKBOARD 2495
++ip6000 MACH_IP6000 IP6000 2496
++ip6010 MACH_IP6010 IP6010 2497
++utm400 MACH_UTM400 UTM400 2498
++omap3_zybex MACH_OMAP3_ZYBEX OMAP3_ZYBEX 2499
++wireless_space MACH_WIRELESS_SPACE WIRELESS_SPACE 2500
++sx560 MACH_SX560 SX560 2501
++ts41x MACH_TS41X TS41X 2502
++elphel10373 MACH_ELPHEL10373 ELPHEL10373 2503
++rhobot MACH_RHOBOT RHOBOT 2504
++mx51_refresh MACH_MX51_REFRESH MX51_REFRESH 2505
++ls9260 MACH_LS9260 LS9260 2506
++shank MACH_SHANK SHANK 2507
++qsd8x50_st1 MACH_QSD8X50_ST1 QSD8X50_ST1 2508
++at91sam9m10ekes MACH_AT91SAM9M10EKES AT91SAM9M10EKES 2509
++hiram MACH_HIRAM HIRAM 2510
++phy3250 MACH_PHY3250 PHY3250 2511
++ea3250 MACH_EA3250 EA3250 2512
++fdi3250 MACH_FDI3250 FDI3250 2513
++whitestone MACH_WHITESTONE WHITESTONE 2514
++at91sam9263nit MACH_AT91SAM9263NIT AT91SAM9263NIT 2515
++ccmx51 MACH_CCMX51 CCMX51 2516
++ccmx51js MACH_CCMX51JS CCMX51JS 2517
++ccwmx51 MACH_CCWMX51 CCWMX51 2518
++ccwmx51js MACH_CCWMX51JS CCWMX51JS 2519
++mini6410 MACH_MINI6410 MINI6410 2520
++tiny6410 MACH_TINY6410 TINY6410 2521
++nano6410 MACH_NANO6410 NANO6410 2522
++at572d940hfnldb MACH_AT572D940HFNLDB AT572D940HFNLDB 2523
++htcleo MACH_HTCLEO HTCLEO 2524
++avp13 MACH_AVP13 AVP13 2525
++xxsvideod MACH_XXSVIDEOD XXSVIDEOD 2526
++vpnext MACH_VPNEXT VPNEXT 2527
++swarco_itc3 MACH_SWARCO_ITC3 SWARCO_ITC3 2528
++tx51 MACH_TX51 TX51 2529
++dolby_cat1021 MACH_DOLBY_CAT1021 DOLBY_CAT1021 2530
++mx28evk MACH_MX28EVK MX28EVK 2531
++phoenix260 MACH_PHOENIX260 PHOENIX260 2532
++uvaca_stork MACH_UVACA_STORK UVACA_STORK 2533
++smartq5 MACH_SMARTQ5 SMARTQ5 2534
++all3078 MACH_ALL3078 ALL3078 2535
++ctera_2bay_ds MACH_CTERA_2BAY_DS CTERA_2BAY_DS 2536
++siogentoo3 MACH_SIOGENTOO3 SIOGENTOO3 2537
++epb5000 MACH_EPB5000 EPB5000 2538
++hy9263 MACH_HY9263 HY9263 2539
++acer_tempo_m900 MACH_ACER_TEMPO_M900 ACER_TEMPO_M900 2540
++acer_tempo_dx650 MACH_ACER_TEMPO_DX900 ACER_TEMPO_DX900 2541
++acer_tempo_x960 MACH_ACER_TEMPO_X960 ACER_TEMPO_X960 2542
++acer_eten_v900 MACH_ACER_ETEN_V900 ACER_ETEN_V900 2543
++acer_eten_x900 MACH_ACER_ETEN_X900 ACER_ETEN_X900 2544
++bonnell MACH_BONNELL BONNELL 2545
++oht_mx27 MACH_OHT_MX27 OHT_MX27 2546
++htcquartz MACH_HTCQUARTZ HTCQUARTZ 2547
++davinci_dm6467tevm MACH_DAVINCI_DM6467TEVM DAVINCI_DM6467TEVM 2548
++c3ax03 MACH_C3AX03 C3AX03 2549
++mxt_td60 MACH_MXT_TD60 MXT_TD60 2550
++esyx MACH_ESYX ESYX 2551
++dove_db2 MACH_DOVE_DB2 DOVE_DB2 2552
++bulldog MACH_BULLDOG BULLDOG 2553
++derell_me2000 MACH_DERELL_ME2000 DERELL_ME2000 2554
++bcmring_base MACH_BCMRING_BASE BCMRING_BASE 2555
++bcmring_evm MACH_BCMRING_EVM BCMRING_EVM 2556
++bcmring_evm_jazz MACH_BCMRING_EVM_JAZZ BCMRING_EVM_JAZZ 2557
++bcmring_sp MACH_BCMRING_SP BCMRING_SP 2558
++bcmring_sv MACH_BCMRING_SV BCMRING_SV 2559
++bcmring_sv_jazz MACH_BCMRING_SV_JAZZ BCMRING_SV_JAZZ 2560
++bcmring_tablet MACH_BCMRING_TABLET BCMRING_TABLET 2561
++bcmring_vp MACH_BCMRING_VP BCMRING_VP 2562
++bcmring_evm_seikor MACH_BCMRING_EVM_SEIKOR BCMRING_EVM_SEIKOR 2563
++bcmring_sp_wqvga MACH_BCMRING_SP_WQVGA BCMRING_SP_WQVGA 2564
++bcmring_custom MACH_BCMRING_CUSTOM BCMRING_CUSTOM 2565
++acer_s200 MACH_ACER_S200 ACER_S200 2566
++bt270 MACH_BT270 BT270 2567
++iseo MACH_ISEO ISEO 2568
++cezanne MACH_CEZANNE CEZANNE 2569
++lucca MACH_LUCCA LUCCA 2570
++supersmart MACH_SUPERSMART SUPERSMART 2571
++arm11_board MACH_CS_MISANO CS_MISANO 2572
++magnolia2 MACH_MAGNOLIA2 MAGNOLIA2 2573
++emxx MACH_EMXX EMXX 2574
++outlaw MACH_OUTLAW OUTLAW 2575
++riot_bei2 MACH_RIOT_BEI2 RIOT_BEI2 2576
++riot_vox MACH_RIOT_VOX RIOT_VOX 2577
++riot_x37 MACH_RIOT_X37 RIOT_X37 2578
++mega25mx MACH_MEGA25MX MEGA25MX 2579
++benzina2 MACH_BENZINA2 BENZINA2 2580
++ignite MACH_IGNITE IGNITE 2581
++foggia MACH_FOGGIA FOGGIA 2582
++arezzo MACH_AREZZO AREZZO 2583
++leica_skywalker MACH_LEICA_SKYWALKER LEICA_SKYWALKER 2584
++jacinto2_jamr MACH_JACINTO2_JAMR JACINTO2_JAMR 2585
++gts_nova MACH_GTS_NOVA GTS_NOVA 2586
++p3600 MACH_P3600 P3600 2587
++dlt2 MACH_DLT2 DLT2 2588
++df3120 MACH_DF3120 DF3120 2589
++ecucore_9g20 MACH_ECUCORE_9G20 ECUCORE_9G20 2590
++nautel_lpc3240 MACH_NAUTEL_LPC3240 NAUTEL_LPC3240 2591
++glacier MACH_GLACIER GLACIER 2592
++phrazer_bulldog MACH_PHRAZER_BULLDOG PHRAZER_BULLDOG 2593
++omap3_bulldog MACH_OMAP3_BULLDOG OMAP3_BULLDOG 2594
++pca101 MACH_PCA101 PCA101 2595
++buzzc MACH_BUZZC BUZZC 2596
++sasie2 MACH_SASIE2 SASIE2 2597
++davinci_cio MACH_DAVINCI_CIO DAVINCI_CIO 2598
++smartmeter_dl MACH_SMARTMETER_DL SMARTMETER_DL 2599
++wzl6410 MACH_WZL6410 WZL6410 2600
++wzl6410m MACH_WZL6410M WZL6410M 2601
++wzl6410f MACH_WZL6410F WZL6410F 2602
++wzl6410i MACH_WZL6410I WZL6410I 2603
++spacecom1 MACH_SPACECOM1 SPACECOM1 2604
++pingu920 MACH_PINGU920 PINGU920 2605
++bravoc MACH_BRAVOC BRAVOC 2606
++cybo2440 MACH_CYBO2440 CYBO2440 2607
++vdssw MACH_VDSSW VDSSW 2608
++romulus MACH_ROMULUS ROMULUS 2609
++omap_magic MACH_OMAP_MAGIC OMAP_MAGIC 2610
++eltd100 MACH_ELTD100 ELTD100 2611
++capc7117 MACH_CAPC7117 CAPC7117 2612
++swan MACH_SWAN SWAN 2613
++veu MACH_VEU VEU 2614
++rm2 MACH_RM2 RM2 2615
++tt2100 MACH_TT2100 TT2100 2616
++venice MACH_VENICE VENICE 2617
++pc7323 MACH_PC7323 PC7323 2618
++masp MACH_MASP MASP 2619
++fujitsu_tvstbsoc0 MACH_FUJITSU_TVSTBSOC FUJITSU_TVSTBSOC 2620
++fujitsu_tvstbsoc1 MACH_FUJITSU_TVSTBSOC1 FUJITSU_TVSTBSOC1 2621
++lexikon MACH_LEXIKON LEXIKON 2622
++mini2440v2 MACH_MINI2440V2 MINI2440V2 2623
++icontrol MACH_ICONTROL ICONTROL 2624
++gplugd MACH_SHEEVAD SHEEVAD 2625
++qsd8x50a_st1_1 MACH_QSD8X50A_ST1_1 QSD8X50A_ST1_1 2626
++qsd8x50a_st1_5 MACH_QSD8X50A_ST1_5 QSD8X50A_ST1_5 2627
++bee MACH_BEE BEE 2628
++mx23evk MACH_MX23EVK MX23EVK 2629
++ap4evb MACH_AP4EVB AP4EVB 2630
++stockholm MACH_STOCKHOLM STOCKHOLM 2631
++lpc_h3131 MACH_LPC_H3131 LPC_H3131 2632
++stingray MACH_STINGRAY STINGRAY 2633
++kraken MACH_KRAKEN KRAKEN 2634
++gw2388 MACH_GW2388 GW2388 2635
++jadecpu MACH_JADECPU JADECPU 2636
++carlisle MACH_CARLISLE CARLISLE 2637
++lux_sf9 MACH_LUX_SFT9 LUX_SFT9 2638
++nemid_tb MACH_NEMID_TB NEMID_TB 2639
++terrier MACH_TERRIER TERRIER 2640
++turbot MACH_TURBOT TURBOT 2641
++sanddab MACH_SANDDAB SANDDAB 2642
++mx35_cicada MACH_MX35_CICADA MX35_CICADA 2643
++ghi2703d MACH_GHI2703D GHI2703D 2644
++lux_sfx9 MACH_LUX_SFX9 LUX_SFX9 2645
++lux_sf9g MACH_LUX_SF9G LUX_SF9G 2646
++lux_edk9 MACH_LUX_EDK9 LUX_EDK9 2647
++hw90240 MACH_HW90240 HW90240 2648
++dm365_leopard MACH_DM365_LEOPARD DM365_LEOPARD 2649
++mityomapl138 MACH_MITYOMAPL138 MITYOMAPL138 2650
++scat110 MACH_SCAT110 SCAT110 2651
++acer_a1 MACH_ACER_A1 ACER_A1 2652
++cmcontrol MACH_CMCONTROL CMCONTROL 2653
++pelco_lamar MACH_PELCO_LAMAR PELCO_LAMAR 2654
++rfp43 MACH_RFP43 RFP43 2655
++sk86r0301 MACH_SK86R0301 SK86R0301 2656
++ctpxa MACH_CTPXA CTPXA 2657
++epb_arm9_a MACH_EPB_ARM9_A EPB_ARM9_A 2658
++guruplug MACH_GURUPLUG GURUPLUG 2659
++spear310 MACH_SPEAR310 SPEAR310 2660
++spear320 MACH_SPEAR320 SPEAR320 2661
++robotx MACH_ROBOTX ROBOTX 2662
++lsxhl MACH_LSXHL LSXHL 2663
++smartlite MACH_SMARTLITE SMARTLITE 2664
++cws2 MACH_CWS2 CWS2 2665
++m619 MACH_M619 M619 2666
++smartview MACH_SMARTVIEW SMARTVIEW 2667
++lsa_salsa MACH_LSA_SALSA LSA_SALSA 2668
++kizbox MACH_KIZBOX KIZBOX 2669
++htccharmer MACH_HTCCHARMER HTCCHARMER 2670
++guf_neso_lt MACH_GUF_NESO_LT GUF_NESO_LT 2671
++pm9g45 MACH_PM9G45 PM9G45 2672
++htcpanther MACH_HTCPANTHER HTCPANTHER 2673
++htcpanther_cdma MACH_HTCPANTHER_CDMA HTCPANTHER_CDMA 2674
++reb01 MACH_REB01 REB01 2675
++aquila MACH_AQUILA AQUILA 2676
++spark_sls_hw2 MACH_SPARK_SLS_HW2 SPARK_SLS_HW2 2677
++sheeva_esata MACH_ESATA_SHEEVAPLUG ESATA_SHEEVAPLUG 2678
++msm7x30_surf MACH_MSM7X30_SURF MSM7X30_SURF 2679
++micro2440 MACH_MICRO2440 MICRO2440 2680
++am2440 MACH_AM2440 AM2440 2681
++tq2440 MACH_TQ2440 TQ2440 2682
++lpc2478oem MACH_LPC2478OEM LPC2478OEM 2683
++ak880x MACH_AK880X AK880X 2684
++cobra3530 MACH_COBRA3530 COBRA3530 2685
++pmppb MACH_PMPPB PMPPB 2686
++u6715 MACH_U6715 U6715 2687
++axar1500_sender MACH_AXAR1500_SENDER AXAR1500_SENDER 2688
++g30_dvb MACH_G30_DVB G30_DVB 2689
++vc088x MACH_VC088X VC088X 2690
++mioa702 MACH_MIOA702 MIOA702 2691
++hpmin MACH_HPMIN HPMIN 2692
++ak880xak MACH_AK880XAK AK880XAK 2693
++arm926tomap850 MACH_ARM926TOMAP850 ARM926TOMAP850 2694
++lkevm MACH_LKEVM LKEVM 2695
++mw6410 MACH_MW6410 MW6410 2696
++terastation_wxl MACH_TERASTATION_WXL TERASTATION_WXL 2697
++cpu8000e MACH_CPU8000E CPU8000E 2698
++catania MACH_CATANIA CATANIA 2699
++tokyo MACH_TOKYO TOKYO 2700
++msm7201a_surf MACH_MSM7201A_SURF MSM7201A_SURF 2701
++msm7201a_ffa MACH_MSM7201A_FFA MSM7201A_FFA 2702
++msm7x25_surf MACH_MSM7X25_SURF MSM7X25_SURF 2703
++msm7x25_ffa MACH_MSM7X25_FFA MSM7X25_FFA 2704
++msm7x27_surf MACH_MSM7X27_SURF MSM7X27_SURF 2705
++msm7x27_ffa MACH_MSM7X27_FFA MSM7X27_FFA 2706
++msm7x30_ffa MACH_MSM7X30_FFA MSM7X30_FFA 2707
++qsd8x50_surf MACH_QSD8X50_SURF QSD8X50_SURF 2708
++qsd8x50_comet MACH_QSD8X50_COMET QSD8X50_COMET 2709
++qsd8x50_ffa MACH_QSD8X50_FFA QSD8X50_FFA 2710
++qsd8x50a_surf MACH_QSD8X50A_SURF QSD8X50A_SURF 2711
++qsd8x50a_ffa MACH_QSD8X50A_FFA QSD8X50A_FFA 2712
++adx_xgcp10 MACH_ADX_XGCP10 ADX_XGCP10 2713
++mcgwumts2a MACH_MCGWUMTS2A MCGWUMTS2A 2714
++mobikt MACH_MOBIKT MOBIKT 2715
++mx53_evk MACH_MX53_EVK MX53_EVK 2716
++igep0030 MACH_IGEP0030 IGEP0030 2717
++axell_h40_h50_ctrl MACH_AXELL_H40_H50_CTRL AXELL_H40_H50_CTRL 2718
++dtcommod MACH_DTCOMMOD DTCOMMOD 2719
++gould MACH_GOULD GOULD 2720
++siberia MACH_SIBERIA SIBERIA 2721
++sbc3530 MACH_SBC3530 SBC3530 2722
++qarm MACH_QARM QARM 2723
++mips MACH_MIPS MIPS 2724
++mx27grb MACH_MX27GRB MX27GRB 2725
++sbc8100 MACH_SBC8100 SBC8100 2726
++saarb MACH_SAARB SAARB 2727
++omap3mini MACH_OMAP3MINI OMAP3MINI 2728
++cnmbook7se MACH_CNMBOOK7SE CNMBOOK7SE 2729
++catan MACH_CATAN CATAN 2730
++harmony MACH_HARMONY HARMONY 2731
++tonga MACH_TONGA TONGA 2732
++cybook_orizon MACH_CYBOOK_ORIZON CYBOOK_ORIZON 2733
++htcrhodiumcdma MACH_HTCRHODIUMCDMA HTCRHODIUMCDMA 2734
++epc_g45 MACH_EPC_G45 EPC_G45 2735
++epc_lpc3250 MACH_EPC_LPC3250 EPC_LPC3250 2736
++mxc91341evb MACH_MXC91341EVB MXC91341EVB 2737
++rtw1000 MACH_RTW1000 RTW1000 2738
++bobcat MACH_BOBCAT BOBCAT 2739
++trizeps6 MACH_TRIZEPS6 TRIZEPS6 2740
++msm7x30_fluid MACH_MSM7X30_FLUID MSM7X30_FLUID 2741
++nedap9263 MACH_NEDAP9263 NEDAP9263 2742
++netgear_ms2110 MACH_NETGEAR_MS2110 NETGEAR_MS2110 2743
++bmx MACH_BMX BMX 2744
++netstream MACH_NETSTREAM NETSTREAM 2745
++vpnext_rcu MACH_VPNEXT_RCU VPNEXT_RCU 2746
++vpnext_mpu MACH_VPNEXT_MPU VPNEXT_MPU 2747
++bcmring_tablet_v1 MACH_BCMRING_TABLET_V1 BCMRING_TABLET_V1 2748
++sgarm10 MACH_SGARM10 SGARM10 2749
++cm_t3517 MACH_CM_T3517 CM_T3517 2750
++omap3_cps MACH_OMAP3_CPS OMAP3_CPS 2751
++axar1500_receiver MACH_AXAR1500_RECEIVER AXAR1500_RECEIVER 2752
++wbd222 MACH_WBD222 WBD222 2753
++mt65xx MACH_MT65XX MT65XX 2754
++msm8x60_surf MACH_MSM8X60_SURF MSM8X60_SURF 2755
++msm8x60_sim MACH_MSM8X60_SIM MSM8X60_SIM 2756
++vmc300 MACH_VMC300 VMC300 2757
++tcc8000_sdk MACH_TCC8000_SDK TCC8000_SDK 2758
++nanos MACH_NANOS NANOS 2759
++stamp9g10 MACH_STAMP9G10 STAMP9G10 2760
++stamp9g45 MACH_STAMP9G45 STAMP9G45 2761
++h6053 MACH_H6053 H6053 2762
++smint01 MACH_SMINT01 SMINT01 2763
++prtlvt2 MACH_PRTLVT2 PRTLVT2 2764
++ap420 MACH_AP420 AP420 2765
++htcshift MACH_HTCSHIFT HTCSHIFT 2766
++davinci_dm365_fc MACH_DAVINCI_DM365_FC DAVINCI_DM365_FC 2767
++msm8x55_surf MACH_MSM8X55_SURF MSM8X55_SURF 2768
++msm8x55_ffa MACH_MSM8X55_FFA MSM8X55_FFA 2769
++esl_vamana MACH_ESL_VAMANA ESL_VAMANA 2770
++sbc35 MACH_SBC35 SBC35 2771
++mpx6446 MACH_MPX6446 MPX6446 2772
++oreo_controller MACH_OREO_CONTROLLER OREO_CONTROLLER 2773
++kopin_models MACH_KOPIN_MODELS KOPIN_MODELS 2774
++ttc_vision2 MACH_TTC_VISION2 TTC_VISION2 2775
++cns3420vb MACH_CNS3420VB CNS3420VB 2776
++lpc2 MACH_LPC2 LPC2 2777
++olympus MACH_OLYMPUS OLYMPUS 2778
++vortex MACH_VORTEX VORTEX 2779
++s5pc200 MACH_S5PC200 S5PC200 2780
++ecucore_9263 MACH_ECUCORE_9263 ECUCORE_9263 2781
++smdkc200 MACH_SMDKC200 SMDKC200 2782
++emsiso_sx27 MACH_EMSISO_SX27 EMSISO_SX27 2783
++apx_som9g45_ek MACH_APX_SOM9G45_EK APX_SOM9G45_EK 2784
++songshan MACH_SONGSHAN SONGSHAN 2785
++tianshan MACH_TIANSHAN TIANSHAN 2786
++vpx500 MACH_VPX500 VPX500 2787
++am3517sam MACH_AM3517SAM AM3517SAM 2788
++skat91_sim508 MACH_SKAT91_SIM508 SKAT91_SIM508 2789
++skat91_s3e MACH_SKAT91_S3E SKAT91_S3E 2790
++omap4_panda MACH_OMAP4_PANDA OMAP4_PANDA 2791
++df7220 MACH_DF7220 DF7220 2792
++nemini MACH_NEMINI NEMINI 2793
++t8200 MACH_T8200 T8200 2794
++apf51 MACH_APF51 APF51 2795
++dr_rc_unit MACH_DR_RC_UNIT DR_RC_UNIT 2796
++bordeaux MACH_BORDEAUX BORDEAUX 2797
++catania_b MACH_CATANIA_B CATANIA_B 2798
++mx51_ocean MACH_MX51_OCEAN MX51_OCEAN 2799
++ti8168evm MACH_TI8168EVM TI8168EVM 2800
++neocoreomap MACH_NEOCOREOMAP NEOCOREOMAP 2801
++withings_wbp MACH_WITHINGS_WBP WITHINGS_WBP 2802
++dbps MACH_DBPS DBPS 2803
++sbc9261 MACH_SBC9261 SBC9261 2804
++pcbfp0001 MACH_PCBFP0001 PCBFP0001 2805
++speedy MACH_SPEEDY SPEEDY 2806
++chrysaor MACH_CHRYSAOR CHRYSAOR 2807
++tango MACH_TANGO TANGO 2808
++synology_dsx11 MACH_SYNOLOGY_DSX11 SYNOLOGY_DSX11 2809
++hanlin_v3ext MACH_HANLIN_V3EXT HANLIN_V3EXT 2810
++hanlin_v5 MACH_HANLIN_V5 HANLIN_V5 2811
++hanlin_v3plus MACH_HANLIN_V3PLUS HANLIN_V3PLUS 2812
++iriver_story MACH_IRIVER_STORY IRIVER_STORY 2813
++irex_iliad MACH_IREX_ILIAD IREX_ILIAD 2814
++irex_dr1000 MACH_IREX_DR1000 IREX_DR1000 2815
++teton_bga MACH_TETON_BGA TETON_BGA 2816
++snapper9g45 MACH_SNAPPER9G45 SNAPPER9G45 2817
++tam3517 MACH_TAM3517 TAM3517 2818
++pdc100 MACH_PDC100 PDC100 2819
++eukrea_cpuimx25sd MACH_EUKREA_CPUIMX25 EUKREA_CPUIMX25 2820
++eukrea_cpuimx35sd MACH_EUKREA_CPUIMX35 EUKREA_CPUIMX35 2821
++eukrea_cpuimx51sd MACH_EUKREA_CPUIMX51SD EUKREA_CPUIMX51SD 2822
++eukrea_cpuimx51 MACH_EUKREA_CPUIMX51 EUKREA_CPUIMX51 2823
++p565 MACH_P565 P565 2824
++acer_a4 MACH_ACER_A4 ACER_A4 2825
++davinci_dm368_bip MACH_DAVINCI_DM368_BIP DAVINCI_DM368_BIP 2826
++eshare MACH_ESHARE ESHARE 2827
++hw_omapl138_europa MACH_HW_OMAPL138_EUROPA HW_OMAPL138_EUROPA 2828
++wlbargn MACH_WLBARGN WLBARGN 2829
++bm170 MACH_BM170 BM170 2830
++netspace_mini_v2 MACH_NETSPACE_MINI_V2 NETSPACE_MINI_V2 2831
++netspace_plug_v2 MACH_NETSPACE_PLUG_V2 NETSPACE_PLUG_V2 2832
++siemens_l1 MACH_SIEMENS_L1 SIEMENS_L1 2833
++elv_lcu1 MACH_ELV_LCU1 ELV_LCU1 2834
++mcu1 MACH_MCU1 MCU1 2835
++omap3_tao3530 MACH_OMAP3_TAO3530 OMAP3_TAO3530 2836
++omap3_pcutouch MACH_OMAP3_PCUTOUCH OMAP3_PCUTOUCH 2837
++smdkc210 MACH_SMDKC210 SMDKC210 2838
++omap3_braillo MACH_OMAP3_BRAILLO OMAP3_BRAILLO 2839
++spyplug MACH_SPYPLUG SPYPLUG 2840
++ginger MACH_GINGER GINGER 2841
++tny_t3530 MACH_TNY_T3530 TNY_T3530 2842
++pca102 MACH_PCA102 PCA102 2843
++spade MACH_SPADE SPADE 2844
++mxc25_topaz MACH_MXC25_TOPAZ MXC25_TOPAZ 2845
++t5325 MACH_T5325 T5325 2846
++gw2361 MACH_GW2361 GW2361 2847
++elog MACH_ELOG ELOG 2848
++income MACH_INCOME INCOME 2849
++bcm589x MACH_BCM589X BCM589X 2850
++etna MACH_ETNA ETNA 2851
++hawks MACH_HAWKS HAWKS 2852
++meson MACH_MESON MESON 2853
++xsbase255 MACH_XSBASE255 XSBASE255 2854
++pvm2030 MACH_PVM2030 PVM2030 2855
++mioa502 MACH_MIOA502 MIOA502 2856
++vvbox_sdorig2 MACH_VVBOX_SDORIG2 VVBOX_SDORIG2 2857
++vvbox_sdlite2 MACH_VVBOX_SDLITE2 VVBOX_SDLITE2 2858
++vvbox_sdpro4 MACH_VVBOX_SDPRO4 VVBOX_SDPRO4 2859
++htc_spv_m700 MACH_HTC_SPV_M700 HTC_SPV_M700 2860
++mx257sx MACH_MX257SX MX257SX 2861
++goni MACH_GONI GONI 2862
++msm8x55_svlte_ffa MACH_MSM8X55_SVLTE_FFA MSM8X55_SVLTE_FFA 2863
++msm8x55_svlte_surf MACH_MSM8X55_SVLTE_SURF MSM8X55_SVLTE_SURF 2864
++quickstep MACH_QUICKSTEP QUICKSTEP 2865
++dmw96 MACH_DMW96 DMW96 2866
++hammerhead MACH_HAMMERHEAD HAMMERHEAD 2867
++trident MACH_TRIDENT TRIDENT 2868
++lightning MACH_LIGHTNING LIGHTNING 2869
++iconnect MACH_ICONNECT ICONNECT 2870
++autobot MACH_AUTOBOT AUTOBOT 2871
++coconut MACH_COCONUT COCONUT 2872
++durian MACH_DURIAN DURIAN 2873
++cayenne MACH_CAYENNE CAYENNE 2874
++fuji MACH_FUJI FUJI 2875
++synology_6282 MACH_SYNOLOGY_6282 SYNOLOGY_6282 2876
++em1sy MACH_EM1SY EM1SY 2877
++m502 MACH_M502 M502 2878
++matrix518 MACH_MATRIX518 MATRIX518 2879
++tiny_gurnard MACH_TINY_GURNARD TINY_GURNARD 2880
++spear1310 MACH_SPEAR1310 SPEAR1310 2881
++bv07 MACH_BV07 BV07 2882
++mxt_td61 MACH_MXT_TD61 MXT_TD61 2883
++openrd_ultimate MACH_OPENRD_ULTIMATE OPENRD_ULTIMATE 2884
++devixp MACH_DEVIXP DEVIXP 2885
++miccpt MACH_MICCPT MICCPT 2886
++mic256 MACH_MIC256 MIC256 2887
++as1167 MACH_AS1167 AS1167 2888
++omap3_ibiza MACH_OMAP3_IBIZA OMAP3_IBIZA 2889
++u5500 MACH_U5500 U5500 2890
++davinci_picto MACH_DAVINCI_PICTO DAVINCI_PICTO 2891
++mecha MACH_MECHA MECHA 2892
++bubba3 MACH_BUBBA3 BUBBA3 2893
++pupitre MACH_PUPITRE PUPITRE 2894
++tegra_harmony MACH_TEGRA_HARMONY TEGRA_HARMONY 2895
++tegra_vogue MACH_TEGRA_VOGUE TEGRA_VOGUE 2896
++tegra_e1165 MACH_TEGRA_E1165 TEGRA_E1165 2897
++simplenet MACH_SIMPLENET SIMPLENET 2898
++ec4350tbm MACH_EC4350TBM EC4350TBM 2899
++pec_tc MACH_PEC_TC PEC_TC 2900
++pec_hc2 MACH_PEC_HC2 PEC_HC2 2901
++esl_mobilis_a MACH_ESL_MOBILIS_A ESL_MOBILIS_A 2902
++esl_mobilis_b MACH_ESL_MOBILIS_B ESL_MOBILIS_B 2903
++esl_wave_a MACH_ESL_WAVE_A ESL_WAVE_A 2904
++esl_wave_b MACH_ESL_WAVE_B ESL_WAVE_B 2905
++unisense_mmm MACH_UNISENSE_MMM UNISENSE_MMM 2906
++blueshark MACH_BLUESHARK BLUESHARK 2907
++e10 MACH_E10 E10 2908
++app3k_robin MACH_APP3K_ROBIN APP3K_ROBIN 2909
++pov15hd MACH_POV15HD POV15HD 2910
++stella MACH_STELLA STELLA 2911
++linkstation_lschl MACH_LINKSTATION_LSCHL LINKSTATION_LSCHL 2913
++netwalker MACH_NETWALKER NETWALKER 2914
++acsx106 MACH_ACSX106 ACSX106 2915
++atlas5_c1 MACH_ATLAS5_C1 ATLAS5_C1 2916
++nsb3ast MACH_NSB3AST NSB3AST 2917
++gnet_slc MACH_GNET_SLC GNET_SLC 2918
++af4000 MACH_AF4000 AF4000 2919
++ark9431 MACH_ARK9431 ARK9431 2920
++fs_s5pc100 MACH_FS_S5PC100 FS_S5PC100 2921
++omap3505nova8 MACH_OMAP3505NOVA8 OMAP3505NOVA8 2922
++omap3621_edp1 MACH_OMAP3621_EDP1 OMAP3621_EDP1 2923
++oratisaes MACH_ORATISAES ORATISAES 2924
++smdkv310 MACH_SMDKV310 SMDKV310 2925
++siemens_l0 MACH_SIEMENS_L0 SIEMENS_L0 2926
++ventana MACH_VENTANA VENTANA 2927
++wm8505_7in_netbook MACH_WM8505_7IN_NETBOOK WM8505_7IN_NETBOOK 2928
++ec4350sdb MACH_EC4350SDB EC4350SDB 2929
++mimas MACH_MIMAS MIMAS 2930
++titan MACH_TITAN TITAN 2931
++craneboard MACH_CRANEBOARD CRANEBOARD 2932
++es2440 MACH_ES2440 ES2440 2933
++najay_a9263 MACH_NAJAY_A9263 NAJAY_A9263 2934
++htctornado MACH_HTCTORNADO HTCTORNADO 2935
++dimm_mx257 MACH_DIMM_MX257 DIMM_MX257 2936
++jigen301 MACH_JIGEN JIGEN 2937
++smdk6450 MACH_SMDK6450 SMDK6450 2938
++meno_qng MACH_MENO_QNG MENO_QNG 2939
++ns2416 MACH_NS2416 NS2416 2940
++rpc353 MACH_RPC353 RPC353 2941
++tq6410 MACH_TQ6410 TQ6410 2942
++sky6410 MACH_SKY6410 SKY6410 2943
++dynasty MACH_DYNASTY DYNASTY 2944
++vivo MACH_VIVO VIVO 2945
++bury_bl7582 MACH_BURY_BL7582 BURY_BL7582 2946
++bury_bps5270 MACH_BURY_BPS5270 BURY_BPS5270 2947
++basi MACH_BASI BASI 2948
++tn200 MACH_TN200 TN200 2949
++c2mmi MACH_C2MMI C2MMI 2950
++meson_6236m MACH_MESON_6236M MESON_6236M 2951
++meson_8626m MACH_MESON_8626M MESON_8626M 2952
++tube MACH_TUBE TUBE 2953
++messina MACH_MESSINA MESSINA 2954
++mx50_arm2 MACH_MX50_ARM2 MX50_ARM2 2955
++cetus9263 MACH_CETUS9263 CETUS9263 2956
++brownstone MACH_BROWNSTONE BROWNSTONE 2957
++vmx25 MACH_VMX25 VMX25 2958
++vmx51 MACH_VMX51 VMX51 2959
++abacus MACH_ABACUS ABACUS 2960
++cm4745 MACH_CM4745 CM4745 2961
++oratislink MACH_ORATISLINK ORATISLINK 2962
++davinci_dm365_dvr MACH_DAVINCI_DM365_DVR DAVINCI_DM365_DVR 2963
++netviz MACH_NETVIZ NETVIZ 2964
++flexibity MACH_FLEXIBITY FLEXIBITY 2965
++wlan_computer MACH_WLAN_COMPUTER WLAN_COMPUTER 2966
+diff -rupN linux-2.6.35.11/drivers/base/core.c linux-2.6.35.11-ts7500/drivers/base/core.c
+--- linux-2.6.35.11/drivers/base/core.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/base/core.c 2011-03-14 11:18:24.000000000 -0400
+@@ -1323,6 +1323,8 @@ struct device *device_find_child(struct
+
+ int __init devices_init(void)
+ {
++ //printk("devices_init(), calling kset_create_and_add(devices)\n");
++
+ devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
+ if (!devices_kset)
+ return -ENOMEM;
+@@ -1336,6 +1338,7 @@ int __init devices_init(void)
+ if (!sysfs_dev_char_kobj)
+ goto char_kobj_err;
+
++//printk("devices_init() done OK\n");
+ return 0;
+
+ char_kobj_err:
+diff -rupN linux-2.6.35.11/drivers/base/init.c linux-2.6.35.11-ts7500/drivers/base/init.c
+--- linux-2.6.35.11/drivers/base/init.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/base/init.c 2011-03-14 11:18:24.000000000 -0400
+@@ -20,18 +20,28 @@
+ void __init driver_init(void)
+ {
+ /* These are the core pieces */
++ //printk("calling devtmpfs_init()\n");
+ devtmpfs_init();
++ //printk("calling devices_init()\n");
+ devices_init();
++ //printk("calling buses_init()\n");
+ buses_init();
++ //printk("calling classes_init()\n");
+ classes_init();
++ //printk("calling firmware_init()\n");
+ firmware_init();
++ //printk("calling hypervisor_init()\n");
+ hypervisor_init();
+-
++
+ /* These are also core pieces, but must come after the
+ * core core pieces.
+ */
++ // printk("calling platform_bus_init()\n");
+ platform_bus_init();
++ //printk("calling system_bus_init()\n");
+ system_bus_init();
++ //printk("calling cpu_dev_init()\n");
+ cpu_dev_init();
++ //printk("calling memory_dev_init()\n");
+ memory_dev_init();
+ }
+diff -rupN linux-2.6.35.11/drivers/base/platform.c linux-2.6.35.11-ts7500/drivers/base/platform.c
+--- linux-2.6.35.11/drivers/base/platform.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/base/platform.c 2011-03-14 11:18:24.000000000 -0400
+@@ -1021,11 +1021,17 @@ int __init platform_bus_init(void)
+ {
+ int error;
+
++ //printk("platform_bus_init() calling early_platform_cleanup()\n");
++
+ early_platform_cleanup();
+
++ //printk("platform_bus_init() calling device_register()\n");
++
+ error = device_register(&platform_bus);
+ if (error)
+ return error;
++ //printk("platform_bus_init() calling bus_register()\n");
++
+ error = bus_register(&platform_bus_type);
+ if (error)
+ device_unregister(&platform_bus);
+diff -rupN linux-2.6.35.11/drivers/base/platform.c.orig linux-2.6.35.11-ts7500/drivers/base/platform.c.orig
+--- linux-2.6.35.11/drivers/base/platform.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/base/platform.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,1340 @@
++/*
++ * platform.c - platform 'pseudo' bus for legacy devices
++ *
++ * Copyright (c) 2002-3 Patrick Mochel
++ * Copyright (c) 2002-3 Open Source Development Labs
++ *
++ * This file is released under the GPLv2
++ *
++ * Please see Documentation/driver-model/platform.txt for more
++ * information.
++ */
++
++#include <linux/string.h>
++#include <linux/platform_device.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/dma-mapping.h>
++#include <linux/bootmem.h>
++#include <linux/err.h>
++#include <linux/slab.h>
++#include <linux/pm_runtime.h>
++
++#include "base.h"
++
++#define to_platform_driver(drv) (container_of((drv), struct platform_driver, \
++ driver))
++
++struct device platform_bus = {
++ .init_name = "platform",
++};
++EXPORT_SYMBOL_GPL(platform_bus);
++
++/**
++ * platform_get_resource - get a resource for a device
++ * @dev: platform device
++ * @type: resource type
++ * @num: resource index
++ */
++struct resource *platform_get_resource(struct platform_device *dev,
++ unsigned int type, unsigned int num)
++{
++ int i;
++
++ for (i = 0; i < dev->num_resources; i++) {
++ struct resource *r = &dev->resource[i];
++
++ if (type == resource_type(r) && num-- == 0)
++ return r;
++ }
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(platform_get_resource);
++
++/**
++ * platform_get_irq - get an IRQ for a device
++ * @dev: platform device
++ * @num: IRQ number index
++ */
++int platform_get_irq(struct platform_device *dev, unsigned int num)
++{
++ struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);
++
++ return r ? r->start : -ENXIO;
++}
++EXPORT_SYMBOL_GPL(platform_get_irq);
++
++/**
++ * platform_get_resource_byname - get a resource for a device by name
++ * @dev: platform device
++ * @type: resource type
++ * @name: resource name
++ */
++struct resource *platform_get_resource_byname(struct platform_device *dev,
++ unsigned int type,
++ const char *name)
++{
++ int i;
++
++ for (i = 0; i < dev->num_resources; i++) {
++ struct resource *r = &dev->resource[i];
++
++ if (type == resource_type(r) && !strcmp(r->name, name))
++ return r;
++ }
++ return NULL;
++}
++EXPORT_SYMBOL_GPL(platform_get_resource_byname);
++
++/**
++ * platform_get_irq - get an IRQ for a device
++ * @dev: platform device
++ * @name: IRQ name
++ */
++int platform_get_irq_byname(struct platform_device *dev, const char *name)
++{
++ struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ,
++ name);
++
++ return r ? r->start : -ENXIO;
++}
++EXPORT_SYMBOL_GPL(platform_get_irq_byname);
++
++/**
++ * platform_add_devices - add a numbers of platform devices
++ * @devs: array of platform devices to add
++ * @num: number of platform devices in array
++ */
++int platform_add_devices(struct platform_device **devs, int num)
++{
++ int i, ret = 0;
++
++ for (i = 0; i < num; i++) {
++ ret = platform_device_register(devs[i]);
++ if (ret) {
++ while (--i >= 0)
++ platform_device_unregister(devs[i]);
++ break;
++ }
++ }
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(platform_add_devices);
++
++struct platform_object {
++ struct platform_device pdev;
++ char name[1];
++};
++
++/**
++ * platform_device_put - destroy a platform device
++ * @pdev: platform device to free
++ *
++ * Free all memory associated with a platform device. This function must
++ * _only_ be externally called in error cases. All other usage is a bug.
++ */
++void platform_device_put(struct platform_device *pdev)
++{
++ if (pdev)
++ put_device(&pdev->dev);
++}
++EXPORT_SYMBOL_GPL(platform_device_put);
++
++static void platform_device_release(struct device *dev)
++{
++ struct platform_object *pa = container_of(dev, struct platform_object,
++ pdev.dev);
++
++ kfree(pa->pdev.dev.platform_data);
++ kfree(pa->pdev.resource);
++ kfree(pa);
++}
++
++/**
++ * platform_device_alloc - create a platform device
++ * @name: base name of the device we're adding
++ * @id: instance id
++ *
++ * Create a platform device object which can have other objects attached
++ * to it, and which will have attached objects freed when it is released.
++ */
++struct platform_device *platform_device_alloc(const char *name, int id)
++{
++ struct platform_object *pa;
++
++ pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL);
++ if (pa) {
++ strcpy(pa->name, name);
++ pa->pdev.name = pa->name;
++ pa->pdev.id = id;
++ device_initialize(&pa->pdev.dev);
++ pa->pdev.dev.release = platform_device_release;
++ }
++
++ return pa ? &pa->pdev : NULL;
++}
++EXPORT_SYMBOL_GPL(platform_device_alloc);
++
++/**
++ * platform_device_add_resources - add resources to a platform device
++ * @pdev: platform device allocated by platform_device_alloc to add resources to
++ * @res: set of resources that needs to be allocated for the device
++ * @num: number of resources
++ *
++ * Add a copy of the resources to the platform device. The memory
++ * associated with the resources will be freed when the platform device is
++ * released.
++ */
++int platform_device_add_resources(struct platform_device *pdev,
++ const struct resource *res, unsigned int num)
++{
++ struct resource *r;
++
++ r = kmalloc(sizeof(struct resource) * num, GFP_KERNEL);
++ if (r) {
++ memcpy(r, res, sizeof(struct resource) * num);
++ pdev->resource = r;
++ pdev->num_resources = num;
++ }
++ return r ? 0 : -ENOMEM;
++}
++EXPORT_SYMBOL_GPL(platform_device_add_resources);
++
++/**
++ * platform_device_add_data - add platform-specific data to a platform device
++ * @pdev: platform device allocated by platform_device_alloc to add resources to
++ * @data: platform specific data for this platform device
++ * @size: size of platform specific data
++ *
++ * Add a copy of platform specific data to the platform device's
++ * platform_data pointer. The memory associated with the platform data
++ * will be freed when the platform device is released.
++ */
++int platform_device_add_data(struct platform_device *pdev, const void *data,
++ size_t size)
++{
++ void *d = kmemdup(data, size, GFP_KERNEL);
++
++ if (d) {
++ pdev->dev.platform_data = d;
++ return 0;
++ }
++ return -ENOMEM;
++}
++EXPORT_SYMBOL_GPL(platform_device_add_data);
++
++/**
++ * platform_device_add - add a platform device to device hierarchy
++ * @pdev: platform device we're adding
++ *
++ * This is part 2 of platform_device_register(), though may be called
++ * separately _iff_ pdev was allocated by platform_device_alloc().
++ */
++int platform_device_add(struct platform_device *pdev)
++{
++ int i, ret = 0;
++
++ if (!pdev)
++ return -EINVAL;
++
++ if (!pdev->dev.parent)
++ pdev->dev.parent = &platform_bus;
++
++ pdev->dev.bus = &platform_bus_type;
++
++ if (pdev->id != -1)
++ dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
++ else
++ dev_set_name(&pdev->dev, "%s", pdev->name);
++
++ for (i = 0; i < pdev->num_resources; i++) {
++ struct resource *p, *r = &pdev->resource[i];
++
++ if (r->name == NULL)
++ r->name = dev_name(&pdev->dev);
++
++ p = r->parent;
++ if (!p) {
++ if (resource_type(r) == IORESOURCE_MEM)
++ p = &iomem_resource;
++ else if (resource_type(r) == IORESOURCE_IO)
++ p = &ioport_resource;
++ }
++
++ if (p && insert_resource(p, r)) {
++ printk(KERN_ERR
++ "%s: failed to claim resource %d\n",
++ dev_name(&pdev->dev), i);
++ ret = -EBUSY;
++ goto failed;
++ }
++ }
++
++ pr_debug("Registering platform device '%s'. Parent at %s\n",
++ dev_name(&pdev->dev), dev_name(pdev->dev.parent));
++
++ ret = device_add(&pdev->dev);
++ if (ret == 0)
++ return ret;
++
++ failed:
++ while (--i >= 0) {
++ struct resource *r = &pdev->resource[i];
++ unsigned long type = resource_type(r);
++
++ if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
++ release_resource(r);
++ }
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(platform_device_add);
++
++/**
++ * platform_device_del - remove a platform-level device
++ * @pdev: platform device we're removing
++ *
++ * Note that this function will also release all memory- and port-based
++ * resources owned by the device (@dev->resource). This function must
++ * _only_ be externally called in error cases. All other usage is a bug.
++ */
++void platform_device_del(struct platform_device *pdev)
++{
++ int i;
++
++ if (pdev) {
++ device_del(&pdev->dev);
++
++ for (i = 0; i < pdev->num_resources; i++) {
++ struct resource *r = &pdev->resource[i];
++ unsigned long type = resource_type(r);
++
++ if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
++ release_resource(r);
++ }
++ }
++}
++EXPORT_SYMBOL_GPL(platform_device_del);
++
++/**
++ * platform_device_register - add a platform-level device
++ * @pdev: platform device we're adding
++ */
++int platform_device_register(struct platform_device *pdev)
++{
++ device_initialize(&pdev->dev);
++ return platform_device_add(pdev);
++}
++EXPORT_SYMBOL_GPL(platform_device_register);
++
++/**
++ * platform_device_unregister - unregister a platform-level device
++ * @pdev: platform device we're unregistering
++ *
++ * Unregistration is done in 2 steps. First we release all resources
++ * and remove it from the subsystem, then we drop reference count by
++ * calling platform_device_put().
++ */
++void platform_device_unregister(struct platform_device *pdev)
++{
++ platform_device_del(pdev);
++ platform_device_put(pdev);
++}
++EXPORT_SYMBOL_GPL(platform_device_unregister);
++
++/**
++ * platform_device_register_simple - add a platform-level device and its resources
++ * @name: base name of the device we're adding
++ * @id: instance id
++ * @res: set of resources that needs to be allocated for the device
++ * @num: number of resources
++ *
++ * This function creates a simple platform device that requires minimal
++ * resource and memory management. Canned release function freeing memory
++ * allocated for the device allows drivers using such devices to be
++ * unloaded without waiting for the last reference to the device to be
++ * dropped.
++ *
++ * This interface is primarily intended for use with legacy drivers which
++ * probe hardware directly. Because such drivers create sysfs device nodes
++ * themselves, rather than letting system infrastructure handle such device
++ * enumeration tasks, they don't fully conform to the Linux driver model.
++ * In particular, when such drivers are built as modules, they can't be
++ * "hotplugged".
++ *
++ * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
++ */
++struct platform_device *platform_device_register_simple(const char *name,
++ int id,
++ const struct resource *res,
++ unsigned int num)
++{
++ struct platform_device *pdev;
++ int retval;
++
++ pdev = platform_device_alloc(name, id);
++ if (!pdev) {
++ retval = -ENOMEM;
++ goto error;
++ }
++
++ if (num) {
++ retval = platform_device_add_resources(pdev, res, num);
++ if (retval)
++ goto error;
++ }
++
++ retval = platform_device_add(pdev);
++ if (retval)
++ goto error;
++
++ return pdev;
++
++error:
++ platform_device_put(pdev);
++ return ERR_PTR(retval);
++}
++EXPORT_SYMBOL_GPL(platform_device_register_simple);
++
++/**
++ * platform_device_register_data - add a platform-level device with platform-specific data
++ * @parent: parent device for the device we're adding
++ * @name: base name of the device we're adding
++ * @id: instance id
++ * @data: platform specific data for this platform device
++ * @size: size of platform specific data
++ *
++ * This function creates a simple platform device that requires minimal
++ * resource and memory management. Canned release function freeing memory
++ * allocated for the device allows drivers using such devices to be
++ * unloaded without waiting for the last reference to the device to be
++ * dropped.
++ *
++ * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
++ */
++struct platform_device *platform_device_register_data(
++ struct device *parent,
++ const char *name, int id,
++ const void *data, size_t size)
++{
++ struct platform_device *pdev;
++ int retval;
++
++ pdev = platform_device_alloc(name, id);
++ if (!pdev) {
++ retval = -ENOMEM;
++ goto error;
++ }
++
++ pdev->dev.parent = parent;
++
++ if (size) {
++ retval = platform_device_add_data(pdev, data, size);
++ if (retval)
++ goto error;
++ }
++
++ retval = platform_device_add(pdev);
++ if (retval)
++ goto error;
++
++ return pdev;
++
++error:
++ platform_device_put(pdev);
++ return ERR_PTR(retval);
++}
++EXPORT_SYMBOL_GPL(platform_device_register_data);
++
++static int platform_drv_probe(struct device *_dev)
++{
++ struct platform_driver *drv = to_platform_driver(_dev->driver);
++ struct platform_device *dev = to_platform_device(_dev);
++
++ return drv->probe(dev);
++}
++
++static int platform_drv_probe_fail(struct device *_dev)
++{
++ return -ENXIO;
++}
++
++static int platform_drv_remove(struct device *_dev)
++{
++ struct platform_driver *drv = to_platform_driver(_dev->driver);
++ struct platform_device *dev = to_platform_device(_dev);
++
++ return drv->remove(dev);
++}
++
++static void platform_drv_shutdown(struct device *_dev)
++{
++ struct platform_driver *drv = to_platform_driver(_dev->driver);
++ struct platform_device *dev = to_platform_device(_dev);
++
++ drv->shutdown(dev);
++}
++
++/**
++ * platform_driver_register - register a driver for platform-level devices
++ * @drv: platform driver structure
++ */
++int platform_driver_register(struct platform_driver *drv)
++{
++ drv->driver.bus = &platform_bus_type;
++ if (drv->probe)
++ drv->driver.probe = platform_drv_probe;
++ if (drv->remove)
++ drv->driver.remove = platform_drv_remove;
++ if (drv->shutdown)
++ drv->driver.shutdown = platform_drv_shutdown;
++
++ return driver_register(&drv->driver);
++}
++EXPORT_SYMBOL_GPL(platform_driver_register);
++
++/**
++ * platform_driver_unregister - unregister a driver for platform-level devices
++ * @drv: platform driver structure
++ */
++void platform_driver_unregister(struct platform_driver *drv)
++{
++ driver_unregister(&drv->driver);
++}
++EXPORT_SYMBOL_GPL(platform_driver_unregister);
++
++/**
++ * platform_driver_probe - register driver for non-hotpluggable device
++ * @drv: platform driver structure
++ * @probe: the driver probe routine, probably from an __init section
++ *
++ * Use this instead of platform_driver_register() when you know the device
++ * is not hotpluggable and has already been registered, and you want to
++ * remove its run-once probe() infrastructure from memory after the driver
++ * has bound to the device.
++ *
++ * One typical use for this would be with drivers for controllers integrated
++ * into system-on-chip processors, where the controller devices have been
++ * configured as part of board setup.
++ *
++ * Returns zero if the driver registered and bound to a device, else returns
++ * a negative error code and with the driver not registered.
++ */
++int __init_or_module platform_driver_probe(struct platform_driver *drv,
++ int (*probe)(struct platform_device *))
++{
++ int retval, code;
++
++ /* make sure driver won't have bind/unbind attributes */
++ drv->driver.suppress_bind_attrs = true;
++
++ /* temporary section violation during probe() */
++ drv->probe = probe;
++ retval = code = platform_driver_register(drv);
++
++ /*
++ * Fixup that section violation, being paranoid about code scanning
++ * the list of drivers in order to probe new devices. Check to see
++ * if the probe was successful, and make sure any forced probes of
++ * new devices fail.
++ */
++ spin_lock(&platform_bus_type.p->klist_drivers.k_lock);
++ drv->probe = NULL;
++ if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list))
++ retval = -ENODEV;
++ drv->driver.probe = platform_drv_probe_fail;
++ spin_unlock(&platform_bus_type.p->klist_drivers.k_lock);
++
++ if (code != retval)
++ platform_driver_unregister(drv);
++ return retval;
++}
++EXPORT_SYMBOL_GPL(platform_driver_probe);
++
++/**
++ * platform_create_bundle - register driver and create corresponding device
++ * @driver: platform driver structure
++ * @probe: the driver probe routine, probably from an __init section
++ * @res: set of resources that needs to be allocated for the device
++ * @n_res: number of resources
++ * @data: platform specific data for this platform device
++ * @size: size of platform specific data
++ *
++ * Use this in legacy-style modules that probe hardware directly and
++ * register a single platform device and corresponding platform driver.
++ *
++ * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
++ */
++struct platform_device * __init_or_module platform_create_bundle(
++ struct platform_driver *driver,
++ int (*probe)(struct platform_device *),
++ struct resource *res, unsigned int n_res,
++ const void *data, size_t size)
++{
++ struct platform_device *pdev;
++ int error;
++
++ pdev = platform_device_alloc(driver->driver.name, -1);
++ if (!pdev) {
++ error = -ENOMEM;
++ goto err_out;
++ }
++
++ if (res) {
++ error = platform_device_add_resources(pdev, res, n_res);
++ if (error)
++ goto err_pdev_put;
++ }
++
++ if (data) {
++ error = platform_device_add_data(pdev, data, size);
++ if (error)
++ goto err_pdev_put;
++ }
++
++ error = platform_device_add(pdev);
++ if (error)
++ goto err_pdev_put;
++
++ error = platform_driver_probe(driver, probe);
++ if (error)
++ goto err_pdev_del;
++
++ return pdev;
++
++err_pdev_del:
++ platform_device_del(pdev);
++err_pdev_put:
++ platform_device_put(pdev);
++err_out:
++ return ERR_PTR(error);
++}
++EXPORT_SYMBOL_GPL(platform_create_bundle);
++
++/* modalias support enables more hands-off userspace setup:
++ * (a) environment variable lets new-style hotplug events work once system is
++ * fully running: "modprobe $MODALIAS"
++ * (b) sysfs attribute lets new-style coldplug recover from hotplug events
++ * mishandled before system is fully running: "modprobe $(cat modalias)"
++ */
++static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
++ char *buf)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ int len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name);
++
++ return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
++}
++
++static struct device_attribute platform_dev_attrs[] = {
++ __ATTR_RO(modalias),
++ __ATTR_NULL,
++};
++
++static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++
++ add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX,
++ (pdev->id_entry) ? pdev->id_entry->name : pdev->name);
++ return 0;
++}
++
++static const struct platform_device_id *platform_match_id(
++ const struct platform_device_id *id,
++ struct platform_device *pdev)
++{
++ while (id->name[0]) {
++ if (strcmp(pdev->name, id->name) == 0) {
++ pdev->id_entry = id;
++ return id;
++ }
++ id++;
++ }
++ return NULL;
++}
++
++/**
++ * platform_match - bind platform device to platform driver.
++ * @dev: device.
++ * @drv: driver.
++ *
++ * Platform device IDs are assumed to be encoded like this:
++ * "<name><instance>", where <name> is a short description of the type of
++ * device, like "pci" or "floppy", and <instance> is the enumerated
++ * instance of the device, like '0' or '42'. Driver IDs are simply
++ * "<name>". So, extract the <name> from the platform_device structure,
++ * and compare it against the name of the driver. Return whether they match
++ * or not.
++ */
++static int platform_match(struct device *dev, struct device_driver *drv)
++{
++ struct platform_device *pdev = to_platform_device(dev);
++ struct platform_driver *pdrv = to_platform_driver(drv);
++
++ /* match against the id table first */
++ if (pdrv->id_table)
++ return platform_match_id(pdrv->id_table, pdev) != NULL;
++
++ /* fall-back to driver name match */
++ return (strcmp(pdev->name, drv->name) == 0);
++}
++
++#ifdef CONFIG_PM_SLEEP
++
++static int platform_legacy_suspend(struct device *dev, pm_message_t mesg)
++{
++ struct platform_driver *pdrv = to_platform_driver(dev->driver);
++ struct platform_device *pdev = to_platform_device(dev);
++ int ret = 0;
++
++ if (dev->driver && pdrv->suspend)
++ ret = pdrv->suspend(pdev, mesg);
++
++ return ret;
++}
++
++static int platform_legacy_resume(struct device *dev)
++{
++ struct platform_driver *pdrv = to_platform_driver(dev->driver);
++ struct platform_device *pdev = to_platform_device(dev);
++ int ret = 0;
++
++ if (dev->driver && pdrv->resume)
++ ret = pdrv->resume(pdev);
++
++ return ret;
++}
++
++static int platform_pm_prepare(struct device *dev)
++{
++ struct device_driver *drv = dev->driver;
++ int ret = 0;
++
++ if (drv && drv->pm && drv->pm->prepare)
++ ret = drv->pm->prepare(dev);
++
++ return ret;
++}
++
++static void platform_pm_complete(struct device *dev)
++{
++ struct device_driver *drv = dev->driver;
++
++ if (drv && drv->pm && drv->pm->complete)
++ drv->pm->complete(dev);
++}
++
++#else /* !CONFIG_PM_SLEEP */
++
++#define platform_pm_prepare NULL
++#define platform_pm_complete NULL
++
++#endif /* !CONFIG_PM_SLEEP */
++
++#ifdef CONFIG_SUSPEND
++
++int __weak platform_pm_suspend(struct device *dev)
++{
++ struct device_driver *drv = dev->driver;
++ int ret = 0;
++
++ if (!drv)
++ return 0;
++
++ if (drv->pm) {
++ if (drv->pm->suspend)
++ ret = drv->pm->suspend(dev);
++ } else {
++ ret = platform_legacy_suspend(dev, PMSG_SUSPEND);
++ }
++
++ return ret;
++}
++
++int __weak platform_pm_suspend_noirq(struct device *dev)
++{
++ struct device_driver *drv = dev->driver;
++ int ret = 0;
++
++ if (!drv)
++ return 0;
++
++ if (drv->pm) {
++ if (drv->pm->suspend_noirq)
++ ret = drv->pm->suspend_noirq(dev);
++ }
++
++ return ret;
++}
++
++int __weak platform_pm_resume(struct device *dev)
++{
++ struct device_driver *drv = dev->driver;
++ int ret = 0;
++
++ if (!drv)
++ return 0;
++
++ if (drv->pm) {
++ if (drv->pm->resume)
++ ret = drv->pm->resume(dev);
++ } else {
++ ret = platform_legacy_resume(dev);
++ }
++
++ return ret;
++}
++
++int __weak platform_pm_resume_noirq(struct device *dev)
++{
++ struct device_driver *drv = dev->driver;
++ int ret = 0;
++
++ if (!drv)
++ return 0;
++
++ if (drv->pm) {
++ if (drv->pm->resume_noirq)
++ ret = drv->pm->resume_noirq(dev);
++ }
++
++ return ret;
++}
++
++#else /* !CONFIG_SUSPEND */
++
++#define platform_pm_suspend NULL
++#define platform_pm_resume NULL
++#define platform_pm_suspend_noirq NULL
++#define platform_pm_resume_noirq NULL
++
++#endif /* !CONFIG_SUSPEND */
++
++#ifdef CONFIG_HIBERNATION
++
++static int platform_pm_freeze(struct device *dev)
++{
++ struct device_driver *drv = dev->driver;
++ int ret = 0;
++
++ if (!drv)
++ return 0;
++
++ if (drv->pm) {
++ if (drv->pm->freeze)
++ ret = drv->pm->freeze(dev);
++ } else {
++ ret = platform_legacy_suspend(dev, PMSG_FREEZE);
++ }
++
++ return ret;
++}
++
++static int platform_pm_freeze_noirq(struct device *dev)
++{
++ struct device_driver *drv = dev->driver;
++ int ret = 0;
++
++ if (!drv)
++ return 0;
++
++ if (drv->pm) {
++ if (drv->pm->freeze_noirq)
++ ret = drv->pm->freeze_noirq(dev);
++ }
++
++ return ret;
++}
++
++static int platform_pm_thaw(struct device *dev)
++{
++ struct device_driver *drv = dev->driver;
++ int ret = 0;
++
++ if (!drv)
++ return 0;
++
++ if (drv->pm) {
++ if (drv->pm->thaw)
++ ret = drv->pm->thaw(dev);
++ } else {
++ ret = platform_legacy_resume(dev);
++ }
++
++ return ret;
++}
++
++static int platform_pm_thaw_noirq(struct device *dev)
++{
++ struct device_driver *drv = dev->driver;
++ int ret = 0;
++
++ if (!drv)
++ return 0;
++
++ if (drv->pm) {
++ if (drv->pm->thaw_noirq)
++ ret = drv->pm->thaw_noirq(dev);
++ }
++
++ return ret;
++}
++
++static int platform_pm_poweroff(struct device *dev)
++{
++ struct device_driver *drv = dev->driver;
++ int ret = 0;
++
++ if (!drv)
++ return 0;
++
++ if (drv->pm) {
++ if (drv->pm->poweroff)
++ ret = drv->pm->poweroff(dev);
++ } else {
++ ret = platform_legacy_suspend(dev, PMSG_HIBERNATE);
++ }
++
++ return ret;
++}
++
++static int platform_pm_poweroff_noirq(struct device *dev)
++{
++ struct device_driver *drv = dev->driver;
++ int ret = 0;
++
++ if (!drv)
++ return 0;
++
++ if (drv->pm) {
++ if (drv->pm->poweroff_noirq)
++ ret = drv->pm->poweroff_noirq(dev);
++ }
++
++ return ret;
++}
++
++static int platform_pm_restore(struct device *dev)
++{
++ struct device_driver *drv = dev->driver;
++ int ret = 0;
++
++ if (!drv)
++ return 0;
++
++ if (drv->pm) {
++ if (drv->pm->restore)
++ ret = drv->pm->restore(dev);
++ } else {
++ ret = platform_legacy_resume(dev);
++ }
++
++ return ret;
++}
++
++static int platform_pm_restore_noirq(struct device *dev)
++{
++ struct device_driver *drv = dev->driver;
++ int ret = 0;
++
++ if (!drv)
++ return 0;
++
++ if (drv->pm) {
++ if (drv->pm->restore_noirq)
++ ret = drv->pm->restore_noirq(dev);
++ }
++
++ return ret;
++}
++
++#else /* !CONFIG_HIBERNATION */
++
++#define platform_pm_freeze NULL
++#define platform_pm_thaw NULL
++#define platform_pm_poweroff NULL
++#define platform_pm_restore NULL
++#define platform_pm_freeze_noirq NULL
++#define platform_pm_thaw_noirq NULL
++#define platform_pm_poweroff_noirq NULL
++#define platform_pm_restore_noirq NULL
++
++#endif /* !CONFIG_HIBERNATION */
++
++#ifdef CONFIG_PM_RUNTIME
++
++int __weak platform_pm_runtime_suspend(struct device *dev)
++{
++ return pm_generic_runtime_suspend(dev);
++};
++
++int __weak platform_pm_runtime_resume(struct device *dev)
++{
++ return pm_generic_runtime_resume(dev);
++};
++
++int __weak platform_pm_runtime_idle(struct device *dev)
++{
++ return pm_generic_runtime_idle(dev);
++};
++
++#else /* !CONFIG_PM_RUNTIME */
++
++#define platform_pm_runtime_suspend NULL
++#define platform_pm_runtime_resume NULL
++#define platform_pm_runtime_idle NULL
++
++#endif /* !CONFIG_PM_RUNTIME */
++
++static const struct dev_pm_ops platform_dev_pm_ops = {
++ .prepare = platform_pm_prepare,
++ .complete = platform_pm_complete,
++ .suspend = platform_pm_suspend,
++ .resume = platform_pm_resume,
++ .freeze = platform_pm_freeze,
++ .thaw = platform_pm_thaw,
++ .poweroff = platform_pm_poweroff,
++ .restore = platform_pm_restore,
++ .suspend_noirq = platform_pm_suspend_noirq,
++ .resume_noirq = platform_pm_resume_noirq,
++ .freeze_noirq = platform_pm_freeze_noirq,
++ .thaw_noirq = platform_pm_thaw_noirq,
++ .poweroff_noirq = platform_pm_poweroff_noirq,
++ .restore_noirq = platform_pm_restore_noirq,
++ .runtime_suspend = platform_pm_runtime_suspend,
++ .runtime_resume = platform_pm_runtime_resume,
++ .runtime_idle = platform_pm_runtime_idle,
++};
++
++struct bus_type platform_bus_type = {
++ .name = "platform",
++ .dev_attrs = platform_dev_attrs,
++ .match = platform_match,
++ .uevent = platform_uevent,
++ .pm = &platform_dev_pm_ops,
++};
++EXPORT_SYMBOL_GPL(platform_bus_type);
++
++int __init platform_bus_init(void)
++{
++ int error;
++
++ early_platform_cleanup();
++
++ error = device_register(&platform_bus);
++ if (error)
++ return error;
++ error = bus_register(&platform_bus_type);
++ if (error)
++ device_unregister(&platform_bus);
++ return error;
++}
++
++#ifndef ARCH_HAS_DMA_GET_REQUIRED_MASK
++u64 dma_get_required_mask(struct device *dev)
++{
++ u32 low_totalram = ((max_pfn - 1) << PAGE_SHIFT);
++ u32 high_totalram = ((max_pfn - 1) >> (32 - PAGE_SHIFT));
++ u64 mask;
++
++ if (!high_totalram) {
++ /* convert to mask just covering totalram */
++ low_totalram = (1 << (fls(low_totalram) - 1));
++ low_totalram += low_totalram - 1;
++ mask = low_totalram;
++ } else {
++ high_totalram = (1 << (fls(high_totalram) - 1));
++ high_totalram += high_totalram - 1;
++ mask = (((u64)high_totalram) << 32) + 0xffffffff;
++ }
++ return mask;
++}
++EXPORT_SYMBOL_GPL(dma_get_required_mask);
++#endif
++
++static __initdata LIST_HEAD(early_platform_driver_list);
++static __initdata LIST_HEAD(early_platform_device_list);
++
++/**
++ * early_platform_driver_register - register early platform driver
++ * @epdrv: early_platform driver structure
++ * @buf: string passed from early_param()
++ *
++ * Helper function for early_platform_init() / early_platform_init_buffer()
++ */
++int __init early_platform_driver_register(struct early_platform_driver *epdrv,
++ char *buf)
++{
++ char *tmp;
++ int n;
++
++ /* Simply add the driver to the end of the global list.
++ * Drivers will by default be put on the list in compiled-in order.
++ */
++ if (!epdrv->list.next) {
++ INIT_LIST_HEAD(&epdrv->list);
++ list_add_tail(&epdrv->list, &early_platform_driver_list);
++ }
++
++ /* If the user has specified device then make sure the driver
++ * gets prioritized. The driver of the last device specified on
++ * command line will be put first on the list.
++ */
++ n = strlen(epdrv->pdrv->driver.name);
++ if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) {
++ list_move(&epdrv->list, &early_platform_driver_list);
++
++ /* Allow passing parameters after device name */
++ if (buf[n] == '\0' || buf[n] == ',')
++ epdrv->requested_id = -1;
++ else {
++ epdrv->requested_id = simple_strtoul(&buf[n + 1],
++ &tmp, 10);
++
++ if (buf[n] != '.' || (tmp == &buf[n + 1])) {
++ epdrv->requested_id = EARLY_PLATFORM_ID_ERROR;
++ n = 0;
++ } else
++ n += strcspn(&buf[n + 1], ",") + 1;
++ }
++
++ if (buf[n] == ',')
++ n++;
++
++ if (epdrv->bufsize) {
++ memcpy(epdrv->buffer, &buf[n],
++ min_t(int, epdrv->bufsize, strlen(&buf[n]) + 1));
++ epdrv->buffer[epdrv->bufsize - 1] = '\0';
++ }
++ }
++
++ return 0;
++}
++
++/**
++ * early_platform_add_devices - adds a number of early platform devices
++ * @devs: array of early platform devices to add
++ * @num: number of early platform devices in array
++ *
++ * Used by early architecture code to register early platform devices and
++ * their platform data.
++ */
++void __init early_platform_add_devices(struct platform_device **devs, int num)
++{
++ struct device *dev;
++ int i;
++
++ /* simply add the devices to list */
++ for (i = 0; i < num; i++) {
++ dev = &devs[i]->dev;
++
++ if (!dev->devres_head.next) {
++ INIT_LIST_HEAD(&dev->devres_head);
++ list_add_tail(&dev->devres_head,
++ &early_platform_device_list);
++ }
++ }
++}
++
++/**
++ * early_platform_driver_register_all - register early platform drivers
++ * @class_str: string to identify early platform driver class
++ *
++ * Used by architecture code to register all early platform drivers
++ * for a certain class. If omitted then only early platform drivers
++ * with matching kernel command line class parameters will be registered.
++ */
++void __init early_platform_driver_register_all(char *class_str)
++{
++ /* The "class_str" parameter may or may not be present on the kernel
++ * command line. If it is present then there may be more than one
++ * matching parameter.
++ *
++ * Since we register our early platform drivers using early_param()
++ * we need to make sure that they also get registered in the case
++ * when the parameter is missing from the kernel command line.
++ *
++ * We use parse_early_options() to make sure the early_param() gets
++ * called at least once. The early_param() may be called more than
++ * once since the name of the preferred device may be specified on
++ * the kernel command line. early_platform_driver_register() handles
++ * this case for us.
++ */
++ parse_early_options(class_str);
++}
++
++/**
++ * early_platform_match - find early platform device matching driver
++ * @epdrv: early platform driver structure
++ * @id: id to match against
++ */
++static __init struct platform_device *
++early_platform_match(struct early_platform_driver *epdrv, int id)
++{
++ struct platform_device *pd;
++
++ list_for_each_entry(pd, &early_platform_device_list, dev.devres_head)
++ if (platform_match(&pd->dev, &epdrv->pdrv->driver))
++ if (pd->id == id)
++ return pd;
++
++ return NULL;
++}
++
++/**
++ * early_platform_left - check if early platform driver has matching devices
++ * @epdrv: early platform driver structure
++ * @id: return true if id or above exists
++ */
++static __init int early_platform_left(struct early_platform_driver *epdrv,
++ int id)
++{
++ struct platform_device *pd;
++
++ list_for_each_entry(pd, &early_platform_device_list, dev.devres_head)
++ if (platform_match(&pd->dev, &epdrv->pdrv->driver))
++ if (pd->id >= id)
++ return 1;
++
++ return 0;
++}
++
++/**
++ * early_platform_driver_probe_id - probe drivers matching class_str and id
++ * @class_str: string to identify early platform driver class
++ * @id: id to match against
++ * @nr_probe: number of platform devices to successfully probe before exiting
++ */
++static int __init early_platform_driver_probe_id(char *class_str,
++ int id,
++ int nr_probe)
++{
++ struct early_platform_driver *epdrv;
++ struct platform_device *match;
++ int match_id;
++ int n = 0;
++ int left = 0;
++
++ list_for_each_entry(epdrv, &early_platform_driver_list, list) {
++ /* only use drivers matching our class_str */
++ if (strcmp(class_str, epdrv->class_str))
++ continue;
++
++ if (id == -2) {
++ match_id = epdrv->requested_id;
++ left = 1;
++
++ } else {
++ match_id = id;
++ left += early_platform_left(epdrv, id);
++
++ /* skip requested id */
++ switch (epdrv->requested_id) {
++ case EARLY_PLATFORM_ID_ERROR:
++ case EARLY_PLATFORM_ID_UNSET:
++ break;
++ default:
++ if (epdrv->requested_id == id)
++ match_id = EARLY_PLATFORM_ID_UNSET;
++ }
++ }
++
++ switch (match_id) {
++ case EARLY_PLATFORM_ID_ERROR:
++ pr_warning("%s: unable to parse %s parameter\n",
++ class_str, epdrv->pdrv->driver.name);
++ /* fall-through */
++ case EARLY_PLATFORM_ID_UNSET:
++ match = NULL;
++ break;
++ default:
++ match = early_platform_match(epdrv, match_id);
++ }
++
++ if (match) {
++ /*
++ * Set up a sensible init_name to enable
++ * dev_name() and others to be used before the
++ * rest of the driver core is initialized.
++ */
++ if (!match->dev.init_name && slab_is_available()) {
++ if (match->id != -1)
++ match->dev.init_name =
++ kasprintf(GFP_KERNEL, "%s.%d",
++ match->name,
++ match->id);
++ else
++ match->dev.init_name =
++ kasprintf(GFP_KERNEL, "%s",
++ match->name);
++
++ if (!match->dev.init_name)
++ return -ENOMEM;
++ }
++
++ if (epdrv->pdrv->probe(match))
++ pr_warning("%s: unable to probe %s early.\n",
++ class_str, match->name);
++ else
++ n++;
++ }
++
++ if (n >= nr_probe)
++ break;
++ }
++
++ if (left)
++ return n;
++ else
++ return -ENODEV;
++}
++
++/**
++ * early_platform_driver_probe - probe a class of registered drivers
++ * @class_str: string to identify early platform driver class
++ * @nr_probe: number of platform devices to successfully probe before exiting
++ * @user_only: only probe user specified early platform devices
++ *
++ * Used by architecture code to probe registered early platform drivers
++ * within a certain class. For probe to happen a registered early platform
++ * device matching a registered early platform driver is needed.
++ */
++int __init early_platform_driver_probe(char *class_str,
++ int nr_probe,
++ int user_only)
++{
++ int k, n, i;
++
++ n = 0;
++ for (i = -2; n < nr_probe; i++) {
++ k = early_platform_driver_probe_id(class_str, i, nr_probe - n);
++
++ if (k < 0)
++ break;
++
++ n += k;
++
++ if (user_only)
++ break;
++ }
++
++ return n;
++}
++
++/**
++ * early_platform_cleanup - clean up early platform code
++ */
++void __init early_platform_cleanup(void)
++{
++ struct platform_device *pd, *pd2;
++
++ /* clean up the devres list used to chain devices */
++ list_for_each_entry_safe(pd, pd2, &early_platform_device_list,
++ dev.devres_head) {
++ list_del(&pd->dev.devres_head);
++ memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head));
++ }
++}
++
+diff -rupN linux-2.6.35.11/drivers/base/sys.c linux-2.6.35.11-ts7500/drivers/base/sys.c
+--- linux-2.6.35.11/drivers/base/sys.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/base/sys.c 2011-03-14 11:18:24.000000000 -0400
+@@ -500,6 +500,7 @@ EXPORT_SYMBOL_GPL(sysdev_resume);
+
+ int __init system_bus_init(void)
+ {
++ //printk("system_bus_init(), calling kset_create_and_add(system)\n");
+ system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj);
+ if (!system_kset)
+ return -ENOMEM;
+diff -rupN linux-2.6.35.11/drivers/char/mem.c linux-2.6.35.11-ts7500/drivers/char/mem.c
+--- linux-2.6.35.11/drivers/char/mem.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/char/mem.c 2011-03-14 11:18:24.000000000 -0400
+@@ -898,6 +898,8 @@ static int __init chr_dev_init(void)
+ int minor;
+ int err;
+
++ //printk("chr_dev_init(), calling bdi_init()\n");
++
+ err = bdi_init(&zero_bdi);
+ if (err)
+ return err;
+diff -rupN linux-2.6.35.11/drivers/i2c/busses/i2c-str8100.c linux-2.6.35.11-ts7500/drivers/i2c/busses/i2c-str8100.c
+--- linux-2.6.35.11/drivers/i2c/busses/i2c-str8100.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/i2c/busses/i2c-str8100.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,929 @@
++ /*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <asm/uaccess.h>
++#include <asm/irq.h>
++#include <linux/sysctl.h>
++
++#include <mach/star_intc.h>
++#include <mach/star_i2c.h>
++#include <mach/star_misc.h>
++#include <mach/star_powermgt.h>
++
++#include "i2c-str8100.h"
++
++#define STR8100_I2C_DATE "20060613"
++#define STR8100_I2C_VERSION "1.0.0"
++
++#define I2C_K 1000
++#define I2C_M 1000000
++
++//extern u32 PLL_clock;
++//extern u32 CPU_clock;
++//extern u32 AHB_clock;
++extern u32 APB_clock;
++#define I2C_PCLK APB_clock
++/*#if 1 // for ASIC
++#define I2C_PCLK 200000000
++#else // for FPGA
++#define I2C_PCLK 13000000
++#endif
++*/
++#define TWI_TIMEOUT 2*(HZ)
++
++#define I2C_100KHZ 100000
++#define I2C_200KHZ 200000
++#define I2C_300KHZ 300000
++#define I2C_400KHZ 400000
++
++static i2c_transfer_t i2c_cmd_transfer;
++
++unsigned int debug=0;
++module_param(debug, uint, 0);
++MODULE_PARM_DESC(debug, "STR8100 I2C debug option (0:off 1:on, default=0)");
++
++static unsigned int current_clock;
++unsigned int clock=400000;
++module_param(clock, uint, 0);
++MODULE_PARM_DESC(clock, "STR8100 I2C clock in Hz (default=400000)");
++
++static wait_queue_head_t waitqueue; /* wait queue for read/write to complete */
++
++extern void str8100_set_interrupt_trigger (unsigned int, unsigned int, unsigned int, unsigned int);
++#define u_int32 unsigned int
++
++/******************************************************************************
++ *
++ * FUNCTION: Hal_I2c_Is_Bus_Idle
++ * PURPOSE:
++ *
++ ******************************************************************************/
++u_int32 Hal_I2c_Is_Bus_Idle(void)
++{
++ /*
++ * Return value :
++ * 1 : Bus Idle
++ * 0 : Bus Busy
++ */
++ return ((I2C_CONTROLLER_REG & (0x1 << 6)) ? 0 : 1);
++}
++
++/******************************************************************************
++ *
++ * FUNCTION: Hal_I2c_Is_Action_Done
++ * PURPOSE:
++ *
++ ******************************************************************************/
++u_int32 Hal_I2c_Is_Action_Done(void)
++{
++ /*
++ * Return value :
++ * 1 : Action Done
++ * 0 : Action is NOT Done
++ */
++ return ((I2C_INTERRUPT_STATUS_REG & I2C_ACTION_DONE_FLAG) ? 1 : 0);
++}
++
++/******************************************************************************
++ *
++ * FUNCTION: Hal_I2c_Dispatch_Transfer
++ * PURPOSE:
++ *
++ ******************************************************************************/
++void Hal_I2c_Dispatch_Transfer(i2c_transfer_t *i2c_transfer)
++{
++ u_int32 volatile i2c_control;
++ u_int32 volatile i2c_control_reg;
++
++
++ /*
++ * Wait unti I2C Bus is idle and the previous action is done
++ */
++// while (!Hal_I2c_Is_Bus_Idle() && !Hal_I2c_Is_Action_Done());
++ int retries = 2000;
++
++ while (!Hal_I2c_Is_Bus_Idle() && !Hal_I2c_Is_Action_Done() && retries--);
++ udelay(1000);
++
++ if (retries == 0) {
++ printk ("%s: Bus idle fail!!\n",__FUNCTION__);
++ return;
++ }
++
++
++ // Configure transfer command, write data length, and read data length
++ i2c_control = ((i2c_transfer->transfer_cmd & 0x3) << 4) |
++ ((i2c_transfer->write_data_len & 0x3) << 2) |
++ ((i2c_transfer->read_data_len & 0x3) << 0);
++
++ // Note we enable I2C again!!
++ i2c_control_reg = I2C_CONTROLLER_REG;
++
++ i2c_control_reg &= ~(0x3F);
++ i2c_control_reg |= (i2c_control & 0x3F) | ((u_int32)0x1 << 31);
++
++ I2C_CONTROLLER_REG = i2c_control_reg;
++
++ // Write output data
++ I2C_WRITE_DATA_REG = i2c_transfer->write_data;
++
++ // Configure slave address
++ I2C_SLAVE_ADDRESS_REG = i2c_transfer->slave_addr & 0xFE;
++
++ // Start IC transfer
++ HAL_I2C_START_TRANSFER();
++}
++
++/******************************************************************************
++ *
++ * FUNCTION: I2c_Read_Only_Command
++ * PURPOSE:
++ *
++ ******************************************************************************/
++u_int32 I2c_Read_Only_Command(u_int32 slave_addr, u_int32 read_data_len,
++ u_int32 *read_data)
++{
++ long timeout;
++
++
++ // Clear previous I2C interrupt status
++ IO_OUT_WORD(I2C_INTERRUPT_STATUS_REG_ADDR, I2C_BUS_ERROR_FLAG | I2C_ACTION_DONE_FLAG);
++
++ // Enable I2C interrupt sources
++ IO_OUT_WORD(I2C_INTERRUPT_ENABLE_REG_ADDR, I2C_BUS_ERROR_FLAG | I2C_ACTION_DONE_FLAG);
++
++
++ /*
++ * Configure this I2C command tranfer settings
++ */
++ i2c_cmd_transfer.transfer_cmd = I2C_READ_ONLY_CMD;
++
++ i2c_cmd_transfer.write_data_len = 0;
++
++ i2c_cmd_transfer.read_data_len = read_data_len & 0x3;
++
++ i2c_cmd_transfer.slave_addr = slave_addr & 0xFF;
++
++ i2c_cmd_transfer.write_data = 0;
++
++ i2c_cmd_transfer.error_status = 0;
++
++ i2c_cmd_transfer.action_done = 0;
++
++
++ /*
++ * Issue this command
++ */
++ Hal_I2c_Dispatch_Transfer(&i2c_cmd_transfer);
++
++
++ // Check if this I2C bus action is done or not
++/* while (1)
++ {
++ Sys_Interrupt_Disable_Save_Flags(&cpsr_flags);
++
++ if ((i2c_cmd_transfer.action_done) || (i2c_cmd_transfer.error_status))
++ {
++ break;
++ }
++
++ Sys_Interrupt_Restore_Flags(cpsr_flags);
++ }
++
++ Sys_Interrupt_Restore_Flags(cpsr_flags);
++*/
++ timeout = interruptible_sleep_on_timeout(&waitqueue, TWI_TIMEOUT);
++ if (timeout == 0) return 0x99;
++
++ // I2C Bus error!!
++ if (i2c_cmd_transfer.error_status && (i2c_cmd_transfer.error_status != 0xFF))
++ {
++ return (i2c_cmd_transfer.error_status);
++ }
++
++ // Get the read data byte
++ i2c_cmd_transfer.read_data = IO_IN_WORD(I2C_READ_DATA_REG_ADDR);
++
++ switch (read_data_len & 0x3)
++ {
++ case I2C_DATA_LEN_1_BYTE :
++
++ i2c_cmd_transfer.read_data &= 0xFF;//8
++
++ break;
++
++ case I2C_DATA_LEN_2_BYTE :
++
++ i2c_cmd_transfer.read_data &= 0xFFFF;//16
++
++ break;
++
++ case I2C_DATA_LEN_3_BYTE :
++
++ i2c_cmd_transfer.read_data &= 0xFFFFFF;//24
++
++ break;
++
++ case I2C_DATA_LEN_4_BYTE :
++
++ default :
++
++ break;
++ }
++
++
++ // Set the data for return
++ *read_data = i2c_cmd_transfer.read_data;
++
++ return (0);
++}
++
++
++
++/******************************************************************************
++ *
++ * FUNCTION: I2c_Write_Only_Command
++ * PURPOSE:
++ *
++ ******************************************************************************/
++u_int32 I2c_Write_Only_Command(u_int32 slave_addr, u_int32 write_data_len,
++ u_int32 write_data)
++{
++ long timeout;
++
++
++ // Clear previous I2C interrupt status
++ IO_OUT_WORD(I2C_INTERRUPT_STATUS_REG_ADDR, I2C_BUS_ERROR_FLAG | I2C_ACTION_DONE_FLAG);
++
++ // Enable I2C interrupt sources
++ IO_OUT_WORD(I2C_INTERRUPT_ENABLE_REG_ADDR, I2C_BUS_ERROR_FLAG | I2C_ACTION_DONE_FLAG);
++
++
++ /*
++ * Configure this I2C command tranfer settings
++ */
++ i2c_cmd_transfer.transfer_cmd = I2C_WRITE_ONLY_CMD;
++
++ i2c_cmd_transfer.write_data_len = write_data_len & 0x3;
++
++ i2c_cmd_transfer.read_data_len = 0;
++
++ i2c_cmd_transfer.slave_addr = slave_addr & 0xFF;
++
++ switch (write_data_len & 0x3)
++ {
++ case I2C_DATA_LEN_1_BYTE :
++
++ i2c_cmd_transfer.write_data = write_data & 0xFF;
++
++ break;
++
++ case I2C_DATA_LEN_2_BYTE :
++
++ i2c_cmd_transfer.write_data = write_data & 0xFFFF;
++
++ break;
++
++ case I2C_DATA_LEN_3_BYTE :
++
++ i2c_cmd_transfer.write_data = write_data & 0xFFFFFF;
++
++ break;
++
++ case I2C_DATA_LEN_4_BYTE :
++
++ i2c_cmd_transfer.write_data = write_data;
++
++ default :
++
++ i2c_cmd_transfer.write_data = write_data;
++
++ break;
++ }
++
++ i2c_cmd_transfer.error_status = 0;
++
++ i2c_cmd_transfer.action_done = 0;
++
++
++ /*
++ * Issue this command
++ */
++ Hal_I2c_Dispatch_Transfer(&i2c_cmd_transfer);
++
++
++ // Check if this I2C bus action is done or not
++/* while (1)
++ {
++ Sys_Interrupt_Disable_Save_Flags(&cpsr_flags);
++
++ if ((i2c_cmd_transfer.action_done) || (i2c_cmd_transfer.error_status))
++ {
++ break;
++ }
++
++ Sys_Interrupt_Restore_Flags(cpsr_flags);
++ }
++
++ Sys_Interrupt_Restore_Flags(cpsr_flags);
++*/
++ timeout = interruptible_sleep_on_timeout(&waitqueue, TWI_TIMEOUT);
++ if (timeout == 0) return 0x99;
++
++ // I2C Bus error!!
++ if (i2c_cmd_transfer.error_status && (i2c_cmd_transfer.error_status != 0xFF))
++ {
++ return (i2c_cmd_transfer.error_status);
++ }
++ else
++ {
++ return (0);
++ }
++}
++
++
++/******************************************************************************
++ *
++ * FUNCTION: I2c_Write_Read_Command
++ * PURPOSE:
++ *
++ ******************************************************************************/
++u_int32 I2c_Write_Read_Command(u_int32 slave_addr,
++ u_int32 write_data_len, u_int32 write_data,
++ u_int32 read_data_len, u_int32 *read_data)
++{
++ long timeout;
++
++
++ // Clear previous I2C interrupt status
++ IO_OUT_WORD(I2C_INTERRUPT_STATUS_REG_ADDR, I2C_BUS_ERROR_FLAG | I2C_ACTION_DONE_FLAG);
++
++ // Enable I2C interrupt sources
++ IO_OUT_WORD(I2C_INTERRUPT_ENABLE_REG_ADDR, I2C_BUS_ERROR_FLAG | I2C_ACTION_DONE_FLAG);
++
++
++ /*
++ * Configure this I2C command tranfer settings
++ */
++ i2c_cmd_transfer.transfer_cmd = I2C_WRITE_READ_CMD;
++
++ i2c_cmd_transfer.write_data_len = write_data_len & 0x3;
++
++ i2c_cmd_transfer.read_data_len = read_data_len & 0x3;
++
++ i2c_cmd_transfer.slave_addr = slave_addr & 0xFF;
++
++ switch (write_data_len & 0x3)
++ {
++ case I2C_DATA_LEN_1_BYTE :
++
++ i2c_cmd_transfer.write_data = write_data & 0xFF;
++
++ break;
++
++ case I2C_DATA_LEN_2_BYTE :
++
++ i2c_cmd_transfer.write_data = write_data & 0xFFFF;
++
++ break;
++
++ case I2C_DATA_LEN_3_BYTE :
++
++ i2c_cmd_transfer.write_data = write_data & 0xFFFFFF;
++
++ break;
++
++ case I2C_DATA_LEN_4_BYTE :
++
++ i2c_cmd_transfer.write_data = write_data;
++
++ default :
++
++ i2c_cmd_transfer.write_data = write_data;
++
++ break;
++ }
++
++ i2c_cmd_transfer.error_status = 0;
++
++ i2c_cmd_transfer.action_done = 0;
++
++
++ /*
++ * Issue this command
++ */
++ Hal_I2c_Dispatch_Transfer(&i2c_cmd_transfer);
++
++
++ // Check if this I2C bus action is done or not
++/* while (1)
++ {
++ Sys_Interrupt_Disable_Save_Flags(&cpsr_flags);
++
++ if ((i2c_cmd_transfer.action_done) || (i2c_cmd_transfer.error_status))
++ {
++ break;
++ }
++
++ Sys_Interrupt_Restore_Flags(cpsr_flags);
++ }
++
++ Sys_Interrupt_Restore_Flags(cpsr_flags);
++*/
++ timeout = interruptible_sleep_on_timeout(&waitqueue, TWI_TIMEOUT);
++ if (timeout == 0) return 0x99;
++
++ // I2C Bus error!!
++ if (i2c_cmd_transfer.error_status && (i2c_cmd_transfer.error_status != 0xFF))
++ {
++ return (i2c_cmd_transfer.error_status);
++ }
++
++ // Get the read data byte
++ i2c_cmd_transfer.read_data = IO_IN_WORD(I2C_READ_DATA_REG_ADDR);
++
++ switch (read_data_len & 0x3)
++ {
++ case I2C_DATA_LEN_1_BYTE :
++
++ i2c_cmd_transfer.read_data &= 0xFF;
++
++ break;
++
++ case I2C_DATA_LEN_2_BYTE :
++
++ i2c_cmd_transfer.read_data &= 0xFFFF;
++
++ break;
++
++ case I2C_DATA_LEN_3_BYTE :
++
++ i2c_cmd_transfer.read_data &= 0xFFFFFF;
++
++ break;
++
++ case I2C_DATA_LEN_4_BYTE :
++
++ default :
++ break;
++ }
++
++
++ // Set the data for return
++ *read_data = i2c_cmd_transfer.read_data;
++
++ return (0);
++}
++
++
++
++/******************************************************************************
++ *
++ * FUNCTION: I2c_Read_Write_Command
++ * PURPOSE:
++ *
++ ******************************************************************************/
++u_int32 I2c_Read_Write_Command(u_int32 slave_addr,
++ u_int32 read_data_len, u_int32 *read_data,
++ u_int32 write_data_len, u_int32 write_data)
++{
++ long timeout;
++
++
++ // Clear previous I2C interrupt status
++ IO_OUT_WORD(I2C_INTERRUPT_STATUS_REG_ADDR, I2C_BUS_ERROR_FLAG | I2C_ACTION_DONE_FLAG);
++
++ // Enable I2C interrupt sources
++ IO_OUT_WORD(I2C_INTERRUPT_ENABLE_REG_ADDR, I2C_BUS_ERROR_FLAG | I2C_ACTION_DONE_FLAG);
++
++
++ /*
++ * Configure this I2C command tranfer settings
++ */
++ i2c_cmd_transfer.transfer_cmd = I2C_READ_WRITE_CMD;
++
++ i2c_cmd_transfer.write_data_len = write_data_len & 0x3;
++
++ i2c_cmd_transfer.read_data_len = read_data_len & 0x3;
++
++ i2c_cmd_transfer.slave_addr = slave_addr & 0xFF;
++
++ switch (write_data_len & 0x3)
++ {
++ case I2C_DATA_LEN_1_BYTE :
++
++ i2c_cmd_transfer.write_data = write_data & 0xFF;
++
++ break;
++
++ case I2C_DATA_LEN_2_BYTE :
++
++ i2c_cmd_transfer.write_data = write_data & 0xFFFF;
++
++ break;
++
++ case I2C_DATA_LEN_3_BYTE :
++
++ i2c_cmd_transfer.write_data = write_data & 0xFFFFFF;
++
++ break;
++
++ case I2C_DATA_LEN_4_BYTE :
++
++ i2c_cmd_transfer.write_data = write_data;
++
++ default :
++
++ i2c_cmd_transfer.write_data = write_data;
++
++ break;
++ }
++
++ i2c_cmd_transfer.error_status = 0;
++
++ i2c_cmd_transfer.action_done = 0;
++
++
++ /*
++ * Issue this command
++ */
++ Hal_I2c_Dispatch_Transfer(&i2c_cmd_transfer);
++
++
++ // Check if this I2C bus action is done or not
++/* while (1)
++ {
++ Sys_Interrupt_Disable_Save_Flags(&cpsr_flags);
++
++ if ((i2c_cmd_transfer.action_done) || (i2c_cmd_transfer.error_status))
++ {
++ break;
++ }
++
++ Sys_Interrupt_Restore_Flags(cpsr_flags);
++ }
++
++ Sys_Interrupt_Restore_Flags(cpsr_flags);
++*/
++ timeout = interruptible_sleep_on_timeout(&waitqueue, TWI_TIMEOUT);
++ if (timeout == 0) return 0x99;
++
++
++ // I2C Bus error!!
++ if (i2c_cmd_transfer.error_status && (i2c_cmd_transfer.error_status != 0xFF))
++ {
++ return (i2c_cmd_transfer.error_status);
++ }
++
++ // Get the read data byte
++ i2c_cmd_transfer.read_data = IO_IN_WORD(I2C_READ_DATA_REG_ADDR);
++
++ switch (read_data_len & 0x3)
++ {
++ case I2C_DATA_LEN_1_BYTE :
++
++ i2c_cmd_transfer.read_data &= 0xFF;
++
++ break;
++
++ case I2C_DATA_LEN_2_BYTE :
++
++ i2c_cmd_transfer.read_data &= 0xFFFF;
++
++ break;
++
++ case I2C_DATA_LEN_3_BYTE :
++
++ i2c_cmd_transfer.read_data &= 0xFFFFFF;
++
++ break;
++
++ case I2C_DATA_LEN_4_BYTE :
++
++ default :
++
++ break;
++ }
++
++ // Set the data for return
++ *read_data = i2c_cmd_transfer.read_data;
++
++ return (0);
++}
++//====================================================================================
++// Eileen , for linux kernel 2.6.24 , 20080416
++// old :static void str8100_i2c_init()
++static void str8100_i2c_init(void)
++{
++// unsigned long clock = 100 * (priv->twi_cwgr + 1) * I2C_K;
++
++ current_clock=clock;
++// if(debug)
++ printk("%s: current_clock=%ul, CLKDIV=%d\n",__FUNCTION__,current_clock,(I2C_PCLK / (2 * current_clock) - 1));
++
++ HAL_MISC_ENABLE_I2C_PINS();
++
++ HAL_PWRMGT_ENABLE_I2C_CLOCK();
++
++#if 0
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << PWRMGT_P2S_SOFTWARE_RESET_BIT_INDEX);
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG &= ~(0x1 << PWRMGT_P2S_SOFTWARE_RESET_BIT_INDEX);
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << PWRMGT_P2S_SOFTWARE_RESET_BIT_INDEX);
++#endif
++// I2C_CONTROLLER_REG = (0 << 6) | (0 << 24) | (0 << 31);
++ I2C_CONTROLLER_REG = 0 ;
++// I2C_TIME_OUT_REG = (((I2C_PCLK / (2 * clock) - 1)<<8)|(1 << 7)|0x40);
++ I2C_TIME_OUT_REG = (((I2C_PCLK / (2 * current_clock) - 1)<<8)|(1 << 7)|0x10);
++ I2C_INTERRUPT_ENABLE_REG = 0;
++ I2C_INTERRUPT_STATUS_REG = I2C_BUS_ERROR_FLAG | I2C_ACTION_DONE_FLAG;
++ HAL_I2C_ENABLE_I2C();
++
++}
++/*
++typedef union __data_t{
++ struct{
++ unsigned char byte[4];
++ } byte;
++ unsigned int u32;
++} data;
++
++unsigned int i2c_read_len(unsigned int addr, unsigned char *buf, unsigned int len){
++ data data;
++ if((ret=I2c_Read_Only_Command(addr,&data.u32,len)))
++ return ret;
++
++ switch(rem_len){
++ case 1:
++ *tmp_buf=byte[0];tmp_buf++;
++ break;
++ case 2:
++ *tmp_buf=byte[1];tmp_buf++;
++ *tmp_buf=byte[0];tmp_buf++;
++ break;
++ case 3:
++ *tmp_buf=byte[2];tmp_buf++;
++ *tmp_buf=byte[1];tmp_buf++;
++ *tmp_buf=byte[0];tmp_buf++;
++ break;
++ case 4:
++ *tmp_buf=byte[3];tmp_buf++;
++ *tmp_buf=byte[2];tmp_buf++;
++ *tmp_buf=byte[1];tmp_buf++;
++ *tmp_buf=byte[0];tmp_buf++;
++ break;
++ default:
++ return 99;
++ }
++ return 0;
++}
++*/
++static int
++i2c_read(unsigned int addr, unsigned char *buf, unsigned int len)
++{
++ unsigned int i;
++ unsigned int data;
++ int ret;
++
++ if (len == 0) return 0;
++
++ for(i=0;i<len;i++){
++// if(I2c_Write_Read_Command((addr<<1),0,0,3,&data)){
++// if(I2c_Eeprom_AT24C16A_Read_Byte(0x0a,7,0,&data)){
++ if((ret=I2c_Read_Only_Command((addr<<1),0,&data))){
++ if(debug)
++ printk("Error %s: ret=0x%x\n",__FUNCTION__,ret);
++ return -EIO;
++ }
++ buf[i] = data;
++ }
++
++ return 0;
++}
++
++static int
++i2c_write(unsigned int addr, unsigned char *buf, unsigned int len)
++{
++ unsigned int i,data=0;
++ int ret;
++ if (len == 0) return 0;
++
++ if (len >4) return -EIO;
++
++ for(i=0;i<len;i++) data=data|(buf[i]<<(i<<3));
++
++ if((ret=I2c_Write_Only_Command((addr<<1),len-1,data))){
++ if(debug)
++ printk("Error %s: ret=0x%x\n",__FUNCTION__,ret);
++ return -EIO;
++ }
++
++ return 0;
++}
++
++static int str8100_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], int num)
++{
++ struct i2c_msg *p;
++ int i, err = 0;
++
++ // Eileen , for linux kernel 2.6.24 , 20080416
++ // old : if(clock!=current_clock) str8100_i2c_init(adapter);
++ if(clock!=current_clock) str8100_i2c_init();
++
++ if(debug)
++ printk("\n%s: num=%d\n",__FUNCTION__,num);
++ for (i = 0; !err && i < num; i++) {
++ if(debug)
++ printk("%s: %s msgs[%d] addr=%x len=%d\n",__FUNCTION__,(msgs[i].flags & I2C_M_RD)?"read":"write",i,msgs[i].addr,msgs[i].len);
++ p = &msgs[i];
++ if (!p->len) continue;
++ if (p->flags & I2C_M_RD)
++ err = i2c_read(p->addr, p->buf, p->len);
++ else
++ err = i2c_write(p->addr, p->buf, p->len);
++ }
++
++ /* Return the number of messages processed, or the error code.
++ */
++ if (err == 0)
++ err = num;
++
++ return err;
++}
++
++static u32 str8100_func(struct i2c_adapter *adapter)
++{
++/* return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE
++ | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA
++ | I2C_FUNC_SMBUS_BLOCK_DATA;
++*/
++// return I2C_FUNC_I2C;
++ return I2C_FUNC_SMBUS_EMUL|I2C_FUNC_I2C | I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE
++ | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA
++ | I2C_FUNC_SMBUS_BLOCK_DATA;
++}
++
++static int str8100_ioctl(struct i2c_adapter *adapter,unsigned int cmd, unsigned long arg)
++{
++ unsigned int s_msg;
++
++ if(debug)
++ printk("===> %s: \n",__FUNCTION__);
++ if (copy_from_user(&s_msg, (unsigned int *)arg, sizeof(unsigned int)))
++ return -EFAULT;
++ if ((clock != s_msg) && s_msg>= I2C_100KHZ && s_msg<= I2C_400KHZ){
++ clock=s_msg;
++ str8100_i2c_init();
++ }
++ return 0;
++}
++
++
++//MKL: adapter ====================================================================
++// Eileen , for linux kernel 2.6.24 , 20080416
++// old : static irqreturn_t str8100_i2c_int(int irq, void *private, struct pt_regs *regs)
++static irqreturn_t str8100_i2c_int(int irq, void *private)
++{
++ unsigned int volatile interrupt_status;
++
++ interrupt_status = *((u32 volatile *)I2C_INTERRUPT_STATUS_REG_ADDR);
++ *((u32 volatile *)I2C_INTERRUPT_STATUS_REG_ADDR) = interrupt_status;
++ i2c_cmd_transfer.action_done = (interrupt_status & I2C_ACTION_DONE_FLAG) ? 1 : 0;
++ i2c_cmd_transfer.error_status = (interrupt_status & I2C_BUS_ERROR_FLAG) ? ((interrupt_status >> 8) & 0xFF) : 0;
++ if(debug)
++ printk("%s: i2c_cmd_transfer.error_status=0x%x\n",__FUNCTION__,i2c_cmd_transfer.error_status);
++ if (i2c_cmd_transfer.error_status && (i2c_cmd_transfer.error_status != 0xFF))
++ HAL_I2C_DISABLE_I2C();
++ wake_up_interruptible(&waitqueue);
++ return IRQ_HANDLED;
++}
++
++#define I2C_HW_STR8100 0x1b0000
++static struct i2c_algorithm str8100_algorithm = {
++// name:"str8100 i2c",
++// id:I2C_ALGO_SMBUS,
++ master_xfer: str8100_xfer,
++ algo_control: str8100_ioctl,
++ functionality: str8100_func,
++};
++
++static struct i2c_adapter str8100_i2c_adapter = {
++ name: "Str8100 i2c",
++ id: I2C_HW_STR8100,
++ algo: &str8100_algorithm,
++};
++
++static ctl_table str8100_i2c_table[]={
++ { //.ctl_name = DEV_I2C_CLOCK,
++ .procname = "str8100_clock",
++ .data=&clock,
++ .maxlen=sizeof(clock),
++ .mode = 0644,
++ .proc_handler=&proc_dointvec
++ },
++ { //.ctl_name = DEV_I2C_DEBUG,
++ .procname = "str8100_debug",
++ .data=&debug,
++ .maxlen=sizeof(debug),
++ .mode = 0644,
++ .proc_handler=&proc_dointvec
++ },
++ //{ .ctl_name = 0 }
++};
++
++static ctl_table i2c_dir_table[] = {
++ { //.ctl_name = DEV_I2C,
++ .procname = "i2c",
++ .mode = 0555,
++ .child = str8100_i2c_table },
++ //{ .ctl_name = 0 }
++};
++
++static ctl_table i2c_root_table[] = {
++ { //.ctl_name = CTL_DEV,
++ .procname = "dev",
++ .mode = 0555,
++ .child = i2c_dir_table },
++ //{ .ctl_name = 0 }
++};
++static struct ctl_table_header *i2c_table_header;//=NULL;
++
++int str8100_i2c_dev_init(void)
++{
++
++ int rc;
++
++ printk(KERN_INFO "%s: i2c module version %s\n",__FUNCTION__, STR8100_I2C_VERSION);
++
++ init_waitqueue_head(&waitqueue);
++ str8100_i2c_init();
++ if ((rc = i2c_add_adapter(&str8100_i2c_adapter))) {
++ printk(KERN_ERR "%s: Adapter %s registration failed\n",__FUNCTION__, str8100_i2c_adapter.name);
++ }
++ if (request_irq(INTC_I2C_BIT_INDEX, str8100_i2c_int, 0, "HS STR8100_I2C", NULL)) {
++ printk("%s: unable to get IRQ %d\n",__FUNCTION__, INTC_I2C_BIT_INDEX);
++ return -EAGAIN;
++ }
++ // Eileen , for linux kernel 2.6.24 , 20080416
++ // old : i2c_table_header = register_sysctl_table(i2c_root_table, 1);
++ i2c_table_header = register_sysctl_table(i2c_root_table);
++
++ if(!i2c_table_header)
++ printk("%s: unable register sysctl\n",__FUNCTION__);
++
++ return rc;
++}
++
++static __init int i2c_init(void)
++{
++ if(debug)
++ printk("%s: \n",__FUNCTION__);
++ return str8100_i2c_dev_init();
++}
++
++static __exit void i2c_exit(void)
++{
++ int rc;
++ if(debug)
++ printk("%s: \n",__FUNCTION__);
++ if ((rc = i2c_del_adapter(&str8100_i2c_adapter))) printk(KERN_ERR "%s: i2c_del_adapter failed (%i), that's bad!\n",__FUNCTION__, rc);
++ unregister_sysctl_table(i2c_table_header);
++ free_irq(INTC_I2C_BIT_INDEX,NULL);
++
++}
++
++module_init(i2c_init);
++module_exit(i2c_exit);
++
++MODULE_AUTHOR("Mac Lin");
++MODULE_DESCRIPTION("I2C driver for Str8100");
++MODULE_LICENSE("GPL");
++
+diff -rupN linux-2.6.35.11/drivers/i2c/busses/i2c-str8100.h linux-2.6.35.11-ts7500/drivers/i2c/busses/i2c-str8100.h
+--- linux-2.6.35.11/drivers/i2c/busses/i2c-str8100.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/i2c/busses/i2c-str8100.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,23 @@
++#ifndef STR8100_I2C_H
++#define STR8100_I2C_H
++
++typedef struct _i2c_transfer_s_
++{
++ unsigned int transfer_cmd;
++ unsigned int write_data_len;
++ unsigned int read_data_len;
++ unsigned int write_data;
++ unsigned int read_data;
++ unsigned int slave_addr;
++ unsigned int action_done;
++ unsigned int error_status;
++}i2c_transfer_t;
++
++
++/*
++ * define 32 bit IO access macros
++ */
++#define IO_OUT_WORD(reg, data) ((*((volatile u_int32 *)(reg))) = (u_int32)(data))
++#define IO_IN_WORD(reg) (*((volatile u_int32 *)(reg)))
++
++#endif
+diff -rupN linux-2.6.35.11/drivers/i2c/busses/Kconfig linux-2.6.35.11-ts7500/drivers/i2c/busses/Kconfig
+--- linux-2.6.35.11/drivers/i2c/busses/Kconfig 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/i2c/busses/Kconfig 2011-03-14 11:18:24.000000000 -0400
+@@ -323,6 +323,11 @@ config I2C_BLACKFIN_TWI_CLK_KHZ
+ help
+ The unit of the TWI clock is kHz.
+
++
++config I2C_STR8100
++ tristate "STR8100 I2C"
++ depends on ARCH_STR8100
++
+ config I2C_CPM
+ tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)"
+ depends on (CPM1 || CPM2) && OF_I2C
+diff -rupN linux-2.6.35.11/drivers/i2c/busses/Makefile linux-2.6.35.11-ts7500/drivers/i2c/busses/Makefile
+--- linux-2.6.35.11/drivers/i2c/busses/Makefile 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/i2c/busses/Makefile 2011-03-14 11:18:24.000000000 -0400
+@@ -59,6 +59,7 @@ obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
+ obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
+ obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o
+ obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o
++obj-$(CONFIG_I2C_STR8100) += i2c-str8100.o
+
+ # External I2C/SMBus adapter drivers
+ obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
+diff -rupN linux-2.6.35.11/drivers/i2c/busses/Makefile.orig linux-2.6.35.11-ts7500/drivers/i2c/busses/Makefile.orig
+--- linux-2.6.35.11/drivers/i2c/busses/Makefile.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/i2c/busses/Makefile.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,80 @@
++#
++# Makefile for the i2c bus drivers.
++#
++
++# ACPI drivers
++obj-$(CONFIG_I2C_SCMI) += i2c-scmi.o
++
++# PC SMBus host controller drivers
++obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o
++obj-$(CONFIG_I2C_ALI1563) += i2c-ali1563.o
++obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o
++obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o
++obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o
++obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
++obj-$(CONFIG_I2C_I801) += i2c-i801.o
++obj-$(CONFIG_I2C_ISCH) += i2c-isch.o
++obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o
++obj-$(CONFIG_I2C_NFORCE2_S4985) += i2c-nforce2-s4985.o
++obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
++obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
++obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
++obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o
++obj-$(CONFIG_I2C_VIA) += i2c-via.o
++obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o
++
++# Mac SMBus host controller drivers
++obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
++obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
++
++# Embedded system I2C/SMBus host controller drivers
++obj-$(CONFIG_I2C_AT91) += i2c-at91.o
++obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
++obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
++obj-$(CONFIG_I2C_CPM) += i2c-cpm.o
++obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o
++obj-$(CONFIG_I2C_DESIGNWARE) += i2c-designware.o
++obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o
++obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o
++obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
++obj-$(CONFIG_I2C_IMX) += i2c-imx.o
++obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
++obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o
++obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
++obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
++obj-$(CONFIG_I2C_NOMADIK) += i2c-nomadik.o
++obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o
++obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
++obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
++obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
++obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
++obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
++obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
++obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
++obj-$(CONFIG_I2C_S6000) += i2c-s6000.o
++obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
++obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
++obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
++obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
++obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
++obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o
++obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o
++
++# External I2C/SMBus adapter drivers
++obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
++obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
++obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o
++obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o
++
++# Other I2C/SMBus bus drivers
++obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o
++obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
++obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
++obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
++obj-$(CONFIG_I2C_STUB) += i2c-stub.o
++obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
++obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
++
++ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
++EXTRA_CFLAGS += -DDEBUG
++endif
+diff -rupN linux-2.6.35.11/drivers/Makefile linux-2.6.35.11-ts7500/drivers/Makefile
+--- linux-2.6.35.11/drivers/Makefile 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/Makefile 2011-03-14 11:18:24.000000000 -0400
+@@ -113,3 +113,4 @@ obj-$(CONFIG_VLYNQ) += vlynq/
+ obj-$(CONFIG_STAGING) += staging/
+ obj-y += platform/
+ obj-y += ieee802154/
++obj-y += star/
+diff -rupN linux-2.6.35.11/drivers/Makefile.orig linux-2.6.35.11-ts7500/drivers/Makefile.orig
+--- linux-2.6.35.11/drivers/Makefile.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/Makefile.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,115 @@
++#
++# Makefile for the Linux kernel device drivers.
++#
++# 15 Sep 2000, Christoph Hellwig <hch at infradead.org>
++# Rewritten to use lists instead of if-statements.
++#
++
++obj-y += gpio/
++obj-$(CONFIG_PCI) += pci/
++obj-$(CONFIG_PARISC) += parisc/
++obj-$(CONFIG_RAPIDIO) += rapidio/
++obj-y += video/
++obj-y += idle/
++obj-$(CONFIG_ACPI) += acpi/
++obj-$(CONFIG_SFI) += sfi/
++# PnP must come after ACPI since it will eventually need to check if acpi
++# was used and do nothing if so
++obj-$(CONFIG_PNP) += pnp/
++obj-$(CONFIG_ARM_AMBA) += amba/
++
++obj-$(CONFIG_VIRTIO) += virtio/
++obj-$(CONFIG_XEN) += xen/
++
++# regulators early, since some subsystems rely on them to initialize
++obj-$(CONFIG_REGULATOR) += regulator/
++
++# char/ comes before serial/ etc so that the VT console is the boot-time
++# default.
++obj-y += char/
++
++# gpu/ comes after char for AGP vs DRM startup
++obj-y += gpu/
++
++obj-$(CONFIG_CONNECTOR) += connector/
++
++# i810fb and intelfb depend on char/agp/
++obj-$(CONFIG_FB_I810) += video/i810/
++obj-$(CONFIG_FB_INTEL) += video/intelfb/
++
++obj-y += serial/
++obj-$(CONFIG_PARPORT) += parport/
++obj-y += base/ block/ misc/ mfd/
++obj-$(CONFIG_NUBUS) += nubus/
++obj-y += macintosh/
++obj-$(CONFIG_IDE) += ide/
++obj-$(CONFIG_SCSI) += scsi/
++obj-$(CONFIG_ATA) += ata/
++obj-$(CONFIG_MTD) += mtd/
++obj-$(CONFIG_SPI) += spi/
++obj-y += net/
++obj-$(CONFIG_ATM) += atm/
++obj-$(CONFIG_FUSION) += message/
++obj-$(CONFIG_FIREWIRE) += firewire/
++obj-y += ieee1394/
++obj-$(CONFIG_UIO) += uio/
++obj-y += cdrom/
++obj-y += auxdisplay/
++obj-$(CONFIG_PCCARD) += pcmcia/
++obj-$(CONFIG_DIO) += dio/
++obj-$(CONFIG_SBUS) += sbus/
++obj-$(CONFIG_ZORRO) += zorro/
++obj-$(CONFIG_MAC) += macintosh/
++obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/
++obj-$(CONFIG_PARIDE) += block/paride/
++obj-$(CONFIG_TC) += tc/
++obj-$(CONFIG_UWB) += uwb/
++obj-$(CONFIG_USB_OTG_UTILS) += usb/otg/
++obj-$(CONFIG_USB) += usb/
++obj-$(CONFIG_USB_MUSB_HDRC) += usb/musb/
++obj-$(CONFIG_PCI) += usb/
++obj-$(CONFIG_USB_GADGET) += usb/gadget/
++obj-$(CONFIG_SERIO) += input/serio/
++obj-$(CONFIG_GAMEPORT) += input/gameport/
++obj-$(CONFIG_INPUT) += input/
++obj-$(CONFIG_I2O) += message/
++obj-$(CONFIG_RTC_LIB) += rtc/
++obj-y += i2c/ media/
++obj-$(CONFIG_PPS) += pps/
++obj-$(CONFIG_W1) += w1/
++obj-$(CONFIG_POWER_SUPPLY) += power/
++obj-$(CONFIG_HWMON) += hwmon/
++obj-$(CONFIG_THERMAL) += thermal/
++obj-$(CONFIG_WATCHDOG) += watchdog/
++obj-$(CONFIG_PHONE) += telephony/
++obj-$(CONFIG_MD) += md/
++obj-$(CONFIG_BT) += bluetooth/
++obj-$(CONFIG_ACCESSIBILITY) += accessibility/
++obj-$(CONFIG_ISDN) += isdn/
++obj-$(CONFIG_EDAC) += edac/
++obj-$(CONFIG_MCA) += mca/
++obj-$(CONFIG_EISA) += eisa/
++obj-y += lguest/
++obj-$(CONFIG_CPU_FREQ) += cpufreq/
++obj-$(CONFIG_CPU_IDLE) += cpuidle/
++obj-$(CONFIG_MMC) += mmc/
++obj-$(CONFIG_MEMSTICK) += memstick/
++obj-$(CONFIG_NEW_LEDS) += leds/
++obj-$(CONFIG_INFINIBAND) += infiniband/
++obj-$(CONFIG_SGI_SN) += sn/
++obj-y += firmware/
++obj-$(CONFIG_CRYPTO) += crypto/
++obj-$(CONFIG_SUPERH) += sh/
++obj-$(CONFIG_ARCH_SHMOBILE) += sh/
++obj-$(CONFIG_GENERIC_TIME) += clocksource/
++obj-$(CONFIG_DMA_ENGINE) += dma/
++obj-$(CONFIG_DCA) += dca/
++obj-$(CONFIG_HID) += hid/
++obj-$(CONFIG_PPC_PS3) += ps3/
++obj-$(CONFIG_OF) += of/
++obj-$(CONFIG_SSB) += ssb/
++obj-$(CONFIG_VHOST_NET) += vhost/
++obj-$(CONFIG_VLYNQ) += vlynq/
++obj-$(CONFIG_STAGING) += staging/
++obj-y += platform/
++obj-y += ieee802154/
+diff -rupN linux-2.6.35.11/drivers/net/e1000/e1000_main.c linux-2.6.35.11-ts7500/drivers/net/e1000/e1000_main.c
+--- linux-2.6.35.11/drivers/net/e1000/e1000_main.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/e1000/e1000_main.c 2011-03-14 11:18:24.000000000 -0400
+@@ -883,7 +883,12 @@ static int __devinit e1000_probe(struct
+ if (pci_resource_len(pdev, i) == 0)
+ continue;
+ if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
++#if defined(CONFIG_ARCH_STR9100) || defined(CONFIG_ARCH_STR8100)
++ hw.io_base = (unsigned long)ioremap(pci_resource_start(pdev, i),
++ pci_resource_len(pdev, i));
++#else
+ hw->io_base = pci_resource_start(pdev, i);
++#endif
+ break;
+ }
+ }
+diff -rupN linux-2.6.35.11/drivers/net/e1000/e1000_main.c.orig linux-2.6.35.11-ts7500/drivers/net/e1000/e1000_main.c.orig
+--- linux-2.6.35.11/drivers/net/e1000/e1000_main.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/e1000/e1000_main.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,4784 @@
++/*******************************************************************************
++
++ Intel PRO/1000 Linux driver
++ Copyright(c) 1999 - 2006 Intel Corporation.
++
++ This program is free software; you can redistribute it and/or modify it
++ under the terms and conditions of the GNU General Public License,
++ version 2, as published by the Free Software Foundation.
++
++ This program is distributed in the hope it will be useful, but WITHOUT
++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ more details.
++
++ You should have received a copy of the GNU General Public License along with
++ this program; if not, write to the Free Software Foundation, Inc.,
++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
++
++ The full GNU General Public License is included in this distribution in
++ the file called "COPYING".
++
++ Contact Information:
++ Linux NICS <linux.nics at intel.com>
++ e1000-devel Mailing List <e1000-devel at lists.sourceforge.net>
++ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
++
++*******************************************************************************/
++
++#include "e1000.h"
++#include <net/ip6_checksum.h>
++
++char e1000_driver_name[] = "e1000";
++static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
++#define DRV_VERSION "7.3.21-k8-NAPI"
++const char e1000_driver_version[] = DRV_VERSION;
++static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
++
++/* e1000_pci_tbl - PCI Device ID Table
++ *
++ * Last entry must be all 0s
++ *
++ * Macro expands to...
++ * {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
++ */
++static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
++ INTEL_E1000_ETHERNET_DEVICE(0x1000),
++ INTEL_E1000_ETHERNET_DEVICE(0x1001),
++ INTEL_E1000_ETHERNET_DEVICE(0x1004),
++ INTEL_E1000_ETHERNET_DEVICE(0x1008),
++ INTEL_E1000_ETHERNET_DEVICE(0x1009),
++ INTEL_E1000_ETHERNET_DEVICE(0x100C),
++ INTEL_E1000_ETHERNET_DEVICE(0x100D),
++ INTEL_E1000_ETHERNET_DEVICE(0x100E),
++ INTEL_E1000_ETHERNET_DEVICE(0x100F),
++ INTEL_E1000_ETHERNET_DEVICE(0x1010),
++ INTEL_E1000_ETHERNET_DEVICE(0x1011),
++ INTEL_E1000_ETHERNET_DEVICE(0x1012),
++ INTEL_E1000_ETHERNET_DEVICE(0x1013),
++ INTEL_E1000_ETHERNET_DEVICE(0x1014),
++ INTEL_E1000_ETHERNET_DEVICE(0x1015),
++ INTEL_E1000_ETHERNET_DEVICE(0x1016),
++ INTEL_E1000_ETHERNET_DEVICE(0x1017),
++ INTEL_E1000_ETHERNET_DEVICE(0x1018),
++ INTEL_E1000_ETHERNET_DEVICE(0x1019),
++ INTEL_E1000_ETHERNET_DEVICE(0x101A),
++ INTEL_E1000_ETHERNET_DEVICE(0x101D),
++ INTEL_E1000_ETHERNET_DEVICE(0x101E),
++ INTEL_E1000_ETHERNET_DEVICE(0x1026),
++ INTEL_E1000_ETHERNET_DEVICE(0x1027),
++ INTEL_E1000_ETHERNET_DEVICE(0x1028),
++ INTEL_E1000_ETHERNET_DEVICE(0x1075),
++ INTEL_E1000_ETHERNET_DEVICE(0x1076),
++ INTEL_E1000_ETHERNET_DEVICE(0x1077),
++ INTEL_E1000_ETHERNET_DEVICE(0x1078),
++ INTEL_E1000_ETHERNET_DEVICE(0x1079),
++ INTEL_E1000_ETHERNET_DEVICE(0x107A),
++ INTEL_E1000_ETHERNET_DEVICE(0x107B),
++ INTEL_E1000_ETHERNET_DEVICE(0x107C),
++ INTEL_E1000_ETHERNET_DEVICE(0x108A),
++ INTEL_E1000_ETHERNET_DEVICE(0x1099),
++ INTEL_E1000_ETHERNET_DEVICE(0x10B5),
++ /* required last entry */
++ {0,}
++};
++
++MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
++
++int e1000_up(struct e1000_adapter *adapter);
++void e1000_down(struct e1000_adapter *adapter);
++void e1000_reinit_locked(struct e1000_adapter *adapter);
++void e1000_reset(struct e1000_adapter *adapter);
++int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx);
++int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
++int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
++void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
++void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
++static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
++ struct e1000_tx_ring *txdr);
++static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rxdr);
++static void e1000_free_tx_resources(struct e1000_adapter *adapter,
++ struct e1000_tx_ring *tx_ring);
++static void e1000_free_rx_resources(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring);
++void e1000_update_stats(struct e1000_adapter *adapter);
++
++static int e1000_init_module(void);
++static void e1000_exit_module(void);
++static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
++static void __devexit e1000_remove(struct pci_dev *pdev);
++static int e1000_alloc_queues(struct e1000_adapter *adapter);
++static int e1000_sw_init(struct e1000_adapter *adapter);
++static int e1000_open(struct net_device *netdev);
++static int e1000_close(struct net_device *netdev);
++static void e1000_configure_tx(struct e1000_adapter *adapter);
++static void e1000_configure_rx(struct e1000_adapter *adapter);
++static void e1000_setup_rctl(struct e1000_adapter *adapter);
++static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter);
++static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter);
++static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
++ struct e1000_tx_ring *tx_ring);
++static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring);
++static void e1000_set_rx_mode(struct net_device *netdev);
++static void e1000_update_phy_info(unsigned long data);
++static void e1000_watchdog(unsigned long data);
++static void e1000_82547_tx_fifo_stall(unsigned long data);
++static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
++ struct net_device *netdev);
++static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
++static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
++static int e1000_set_mac(struct net_device *netdev, void *p);
++static irqreturn_t e1000_intr(int irq, void *data);
++static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
++ struct e1000_tx_ring *tx_ring);
++static int e1000_clean(struct napi_struct *napi, int budget);
++static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring,
++ int *work_done, int work_to_do);
++static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring,
++ int *work_done, int work_to_do);
++static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring,
++ int cleaned_count);
++static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring,
++ int cleaned_count);
++static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
++static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
++ int cmd);
++static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
++static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
++static void e1000_tx_timeout(struct net_device *dev);
++static void e1000_reset_task(struct work_struct *work);
++static void e1000_smartspeed(struct e1000_adapter *adapter);
++static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
++ struct sk_buff *skb);
++
++static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
++static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
++static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
++static void e1000_restore_vlan(struct e1000_adapter *adapter);
++
++#ifdef CONFIG_PM
++static int e1000_suspend(struct pci_dev *pdev, pm_message_t state);
++static int e1000_resume(struct pci_dev *pdev);
++#endif
++static void e1000_shutdown(struct pci_dev *pdev);
++
++#ifdef CONFIG_NET_POLL_CONTROLLER
++/* for netdump / net console */
++static void e1000_netpoll (struct net_device *netdev);
++#endif
++
++#define COPYBREAK_DEFAULT 256
++static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT;
++module_param(copybreak, uint, 0644);
++MODULE_PARM_DESC(copybreak,
++ "Maximum size of packet that is copied to a new buffer on receive");
++
++static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
++ pci_channel_state_t state);
++static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev);
++static void e1000_io_resume(struct pci_dev *pdev);
++
++static struct pci_error_handlers e1000_err_handler = {
++ .error_detected = e1000_io_error_detected,
++ .slot_reset = e1000_io_slot_reset,
++ .resume = e1000_io_resume,
++};
++
++static struct pci_driver e1000_driver = {
++ .name = e1000_driver_name,
++ .id_table = e1000_pci_tbl,
++ .probe = e1000_probe,
++ .remove = __devexit_p(e1000_remove),
++#ifdef CONFIG_PM
++ /* Power Managment Hooks */
++ .suspend = e1000_suspend,
++ .resume = e1000_resume,
++#endif
++ .shutdown = e1000_shutdown,
++ .err_handler = &e1000_err_handler
++};
++
++MODULE_AUTHOR("Intel Corporation, <linux.nics at intel.com>");
++MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(DRV_VERSION);
++
++static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE;
++module_param(debug, int, 0);
++MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
++
++/**
++ * e1000_get_hw_dev - return device
++ * used by hardware layer to print debugging information
++ *
++ **/
++struct net_device *e1000_get_hw_dev(struct e1000_hw *hw)
++{
++ struct e1000_adapter *adapter = hw->back;
++ return adapter->netdev;
++}
++
++/**
++ * e1000_init_module - Driver Registration Routine
++ *
++ * e1000_init_module is the first routine called when the driver is
++ * loaded. All it does is register with the PCI subsystem.
++ **/
++
++static int __init e1000_init_module(void)
++{
++ int ret;
++ pr_info("%s - version %s\n", e1000_driver_string, e1000_driver_version);
++
++ pr_info("%s\n", e1000_copyright);
++
++ ret = pci_register_driver(&e1000_driver);
++ if (copybreak != COPYBREAK_DEFAULT) {
++ if (copybreak == 0)
++ pr_info("copybreak disabled\n");
++ else
++ pr_info("copybreak enabled for "
++ "packets <= %u bytes\n", copybreak);
++ }
++ return ret;
++}
++
++module_init(e1000_init_module);
++
++/**
++ * e1000_exit_module - Driver Exit Cleanup Routine
++ *
++ * e1000_exit_module is called just before the driver is removed
++ * from memory.
++ **/
++
++static void __exit e1000_exit_module(void)
++{
++ pci_unregister_driver(&e1000_driver);
++}
++
++module_exit(e1000_exit_module);
++
++static int e1000_request_irq(struct e1000_adapter *adapter)
++{
++ struct net_device *netdev = adapter->netdev;
++ irq_handler_t handler = e1000_intr;
++ int irq_flags = IRQF_SHARED;
++ int err;
++
++ err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name,
++ netdev);
++ if (err) {
++ e_err("Unable to allocate interrupt Error: %d\n", err);
++ }
++
++ return err;
++}
++
++static void e1000_free_irq(struct e1000_adapter *adapter)
++{
++ struct net_device *netdev = adapter->netdev;
++
++ free_irq(adapter->pdev->irq, netdev);
++}
++
++/**
++ * e1000_irq_disable - Mask off interrupt generation on the NIC
++ * @adapter: board private structure
++ **/
++
++static void e1000_irq_disable(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++
++ ew32(IMC, ~0);
++ E1000_WRITE_FLUSH();
++ synchronize_irq(adapter->pdev->irq);
++}
++
++/**
++ * e1000_irq_enable - Enable default interrupt generation settings
++ * @adapter: board private structure
++ **/
++
++static void e1000_irq_enable(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++
++ ew32(IMS, IMS_ENABLE_MASK);
++ E1000_WRITE_FLUSH();
++}
++
++static void e1000_update_mng_vlan(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ u16 vid = hw->mng_cookie.vlan_id;
++ u16 old_vid = adapter->mng_vlan_id;
++ if (adapter->vlgrp) {
++ if (!vlan_group_get_device(adapter->vlgrp, vid)) {
++ if (hw->mng_cookie.status &
++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
++ e1000_vlan_rx_add_vid(netdev, vid);
++ adapter->mng_vlan_id = vid;
++ } else
++ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
++
++ if ((old_vid != (u16)E1000_MNG_VLAN_NONE) &&
++ (vid != old_vid) &&
++ !vlan_group_get_device(adapter->vlgrp, old_vid))
++ e1000_vlan_rx_kill_vid(netdev, old_vid);
++ } else
++ adapter->mng_vlan_id = vid;
++ }
++}
++
++static void e1000_init_manageability(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++
++ if (adapter->en_mng_pt) {
++ u32 manc = er32(MANC);
++
++ /* disable hardware interception of ARP */
++ manc &= ~(E1000_MANC_ARP_EN);
++
++ ew32(MANC, manc);
++ }
++}
++
++static void e1000_release_manageability(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++
++ if (adapter->en_mng_pt) {
++ u32 manc = er32(MANC);
++
++ /* re-enable hardware interception of ARP */
++ manc |= E1000_MANC_ARP_EN;
++
++ ew32(MANC, manc);
++ }
++}
++
++/**
++ * e1000_configure - configure the hardware for RX and TX
++ * @adapter = private board structure
++ **/
++static void e1000_configure(struct e1000_adapter *adapter)
++{
++ struct net_device *netdev = adapter->netdev;
++ int i;
++
++ e1000_set_rx_mode(netdev);
++
++ e1000_restore_vlan(adapter);
++ e1000_init_manageability(adapter);
++
++ e1000_configure_tx(adapter);
++ e1000_setup_rctl(adapter);
++ e1000_configure_rx(adapter);
++ /* call E1000_DESC_UNUSED which always leaves
++ * at least 1 descriptor unused to make sure
++ * next_to_use != next_to_clean */
++ for (i = 0; i < adapter->num_rx_queues; i++) {
++ struct e1000_rx_ring *ring = &adapter->rx_ring[i];
++ adapter->alloc_rx_buf(adapter, ring,
++ E1000_DESC_UNUSED(ring));
++ }
++}
++
++int e1000_up(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++
++ /* hardware has been reset, we need to reload some things */
++ e1000_configure(adapter);
++
++ clear_bit(__E1000_DOWN, &adapter->flags);
++
++ napi_enable(&adapter->napi);
++
++ e1000_irq_enable(adapter);
++
++ netif_wake_queue(adapter->netdev);
++
++ /* fire a link change interrupt to start the watchdog */
++ ew32(ICS, E1000_ICS_LSC);
++ return 0;
++}
++
++/**
++ * e1000_power_up_phy - restore link in case the phy was powered down
++ * @adapter: address of board private structure
++ *
++ * The phy may be powered down to save power and turn off link when the
++ * driver is unloaded and wake on lan is not enabled (among others)
++ * *** this routine MUST be followed by a call to e1000_reset ***
++ *
++ **/
++
++void e1000_power_up_phy(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ u16 mii_reg = 0;
++
++ /* Just clear the power down bit to wake the phy back up */
++ if (hw->media_type == e1000_media_type_copper) {
++ /* according to the manual, the phy will retain its
++ * settings across a power-down/up cycle */
++ e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
++ mii_reg &= ~MII_CR_POWER_DOWN;
++ e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
++ }
++}
++
++static void e1000_power_down_phy(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++
++ /* Power down the PHY so no link is implied when interface is down *
++ * The PHY cannot be powered down if any of the following is true *
++ * (a) WoL is enabled
++ * (b) AMT is active
++ * (c) SoL/IDER session is active */
++ if (!adapter->wol && hw->mac_type >= e1000_82540 &&
++ hw->media_type == e1000_media_type_copper) {
++ u16 mii_reg = 0;
++
++ switch (hw->mac_type) {
++ case e1000_82540:
++ case e1000_82545:
++ case e1000_82545_rev_3:
++ case e1000_82546:
++ case e1000_82546_rev_3:
++ case e1000_82541:
++ case e1000_82541_rev_2:
++ case e1000_82547:
++ case e1000_82547_rev_2:
++ if (er32(MANC) & E1000_MANC_SMBUS_EN)
++ goto out;
++ break;
++ default:
++ goto out;
++ }
++ e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg);
++ mii_reg |= MII_CR_POWER_DOWN;
++ e1000_write_phy_reg(hw, PHY_CTRL, mii_reg);
++ mdelay(1);
++ }
++out:
++ return;
++}
++
++void e1000_down(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ u32 rctl, tctl;
++
++
++ /* disable receives in the hardware */
++ rctl = er32(RCTL);
++ ew32(RCTL, rctl & ~E1000_RCTL_EN);
++ /* flush and sleep below */
++
++ netif_tx_disable(netdev);
++
++ /* disable transmits in the hardware */
++ tctl = er32(TCTL);
++ tctl &= ~E1000_TCTL_EN;
++ ew32(TCTL, tctl);
++ /* flush both disables and wait for them to finish */
++ E1000_WRITE_FLUSH();
++ msleep(10);
++
++ napi_disable(&adapter->napi);
++
++ e1000_irq_disable(adapter);
++
++ /*
++ * Setting DOWN must be after irq_disable to prevent
++ * a screaming interrupt. Setting DOWN also prevents
++ * timers and tasks from rescheduling.
++ */
++ set_bit(__E1000_DOWN, &adapter->flags);
++
++ del_timer_sync(&adapter->tx_fifo_stall_timer);
++ del_timer_sync(&adapter->watchdog_timer);
++ del_timer_sync(&adapter->phy_info_timer);
++
++ adapter->link_speed = 0;
++ adapter->link_duplex = 0;
++ netif_carrier_off(netdev);
++
++ e1000_reset(adapter);
++ e1000_clean_all_tx_rings(adapter);
++ e1000_clean_all_rx_rings(adapter);
++}
++
++void e1000_reinit_locked(struct e1000_adapter *adapter)
++{
++ WARN_ON(in_interrupt());
++ while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
++ msleep(1);
++ e1000_down(adapter);
++ e1000_up(adapter);
++ clear_bit(__E1000_RESETTING, &adapter->flags);
++}
++
++void e1000_reset(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ u32 pba = 0, tx_space, min_tx_space, min_rx_space;
++ bool legacy_pba_adjust = false;
++ u16 hwm;
++
++ /* Repartition Pba for greater than 9k mtu
++ * To take effect CTRL.RST is required.
++ */
++
++ switch (hw->mac_type) {
++ case e1000_82542_rev2_0:
++ case e1000_82542_rev2_1:
++ case e1000_82543:
++ case e1000_82544:
++ case e1000_82540:
++ case e1000_82541:
++ case e1000_82541_rev_2:
++ legacy_pba_adjust = true;
++ pba = E1000_PBA_48K;
++ break;
++ case e1000_82545:
++ case e1000_82545_rev_3:
++ case e1000_82546:
++ case e1000_82546_rev_3:
++ pba = E1000_PBA_48K;
++ break;
++ case e1000_82547:
++ case e1000_82547_rev_2:
++ legacy_pba_adjust = true;
++ pba = E1000_PBA_30K;
++ break;
++ case e1000_undefined:
++ case e1000_num_macs:
++ break;
++ }
++
++ if (legacy_pba_adjust) {
++ if (hw->max_frame_size > E1000_RXBUFFER_8192)
++ pba -= 8; /* allocate more FIFO for Tx */
++
++ if (hw->mac_type == e1000_82547) {
++ adapter->tx_fifo_head = 0;
++ adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
++ adapter->tx_fifo_size =
++ (E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
++ atomic_set(&adapter->tx_fifo_stall, 0);
++ }
++ } else if (hw->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) {
++ /* adjust PBA for jumbo frames */
++ ew32(PBA, pba);
++
++ /* To maintain wire speed transmits, the Tx FIFO should be
++ * large enough to accommodate two full transmit packets,
++ * rounded up to the next 1KB and expressed in KB. Likewise,
++ * the Rx FIFO should be large enough to accommodate at least
++ * one full receive packet and is similarly rounded up and
++ * expressed in KB. */
++ pba = er32(PBA);
++ /* upper 16 bits has Tx packet buffer allocation size in KB */
++ tx_space = pba >> 16;
++ /* lower 16 bits has Rx packet buffer allocation size in KB */
++ pba &= 0xffff;
++ /*
++ * the tx fifo also stores 16 bytes of information about the tx
++ * but don't include ethernet FCS because hardware appends it
++ */
++ min_tx_space = (hw->max_frame_size +
++ sizeof(struct e1000_tx_desc) -
++ ETH_FCS_LEN) * 2;
++ min_tx_space = ALIGN(min_tx_space, 1024);
++ min_tx_space >>= 10;
++ /* software strips receive CRC, so leave room for it */
++ min_rx_space = hw->max_frame_size;
++ min_rx_space = ALIGN(min_rx_space, 1024);
++ min_rx_space >>= 10;
++
++ /* If current Tx allocation is less than the min Tx FIFO size,
++ * and the min Tx FIFO size is less than the current Rx FIFO
++ * allocation, take space away from current Rx allocation */
++ if (tx_space < min_tx_space &&
++ ((min_tx_space - tx_space) < pba)) {
++ pba = pba - (min_tx_space - tx_space);
++
++ /* PCI/PCIx hardware has PBA alignment constraints */
++ switch (hw->mac_type) {
++ case e1000_82545 ... e1000_82546_rev_3:
++ pba &= ~(E1000_PBA_8K - 1);
++ break;
++ default:
++ break;
++ }
++
++ /* if short on rx space, rx wins and must trump tx
++ * adjustment or use Early Receive if available */
++ if (pba < min_rx_space)
++ pba = min_rx_space;
++ }
++ }
++
++ ew32(PBA, pba);
++
++ /*
++ * flow control settings:
++ * The high water mark must be low enough to fit one full frame
++ * (or the size used for early receive) above it in the Rx FIFO.
++ * Set it to the lower of:
++ * - 90% of the Rx FIFO size, and
++ * - the full Rx FIFO size minus the early receive size (for parts
++ * with ERT support assuming ERT set to E1000_ERT_2048), or
++ * - the full Rx FIFO size minus one full frame
++ */
++ hwm = min(((pba << 10) * 9 / 10),
++ ((pba << 10) - hw->max_frame_size));
++
++ hw->fc_high_water = hwm & 0xFFF8; /* 8-byte granularity */
++ hw->fc_low_water = hw->fc_high_water - 8;
++ hw->fc_pause_time = E1000_FC_PAUSE_TIME;
++ hw->fc_send_xon = 1;
++ hw->fc = hw->original_fc;
++
++ /* Allow time for pending master requests to run */
++ e1000_reset_hw(hw);
++ if (hw->mac_type >= e1000_82544)
++ ew32(WUC, 0);
++
++ if (e1000_init_hw(hw))
++ e_err("Hardware Error\n");
++ e1000_update_mng_vlan(adapter);
++
++ /* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */
++ if (hw->mac_type >= e1000_82544 &&
++ hw->autoneg == 1 &&
++ hw->autoneg_advertised == ADVERTISE_1000_FULL) {
++ u32 ctrl = er32(CTRL);
++ /* clear phy power management bit if we are in gig only mode,
++ * which if enabled will attempt negotiation to 100Mb, which
++ * can cause a loss of link at power off or driver unload */
++ ctrl &= ~E1000_CTRL_SWDPIN3;
++ ew32(CTRL, ctrl);
++ }
++
++ /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
++ ew32(VET, ETHERNET_IEEE_VLAN_TYPE);
++
++ e1000_reset_adaptive(hw);
++ e1000_phy_get_info(hw, &adapter->phy_info);
++
++ e1000_release_manageability(adapter);
++}
++
++/**
++ * Dump the eeprom for users having checksum issues
++ **/
++static void e1000_dump_eeprom(struct e1000_adapter *adapter)
++{
++ struct net_device *netdev = adapter->netdev;
++ struct ethtool_eeprom eeprom;
++ const struct ethtool_ops *ops = netdev->ethtool_ops;
++ u8 *data;
++ int i;
++ u16 csum_old, csum_new = 0;
++
++ eeprom.len = ops->get_eeprom_len(netdev);
++ eeprom.offset = 0;
++
++ data = kmalloc(eeprom.len, GFP_KERNEL);
++ if (!data) {
++ pr_err("Unable to allocate memory to dump EEPROM data\n");
++ return;
++ }
++
++ ops->get_eeprom(netdev, &eeprom, data);
++
++ csum_old = (data[EEPROM_CHECKSUM_REG * 2]) +
++ (data[EEPROM_CHECKSUM_REG * 2 + 1] << 8);
++ for (i = 0; i < EEPROM_CHECKSUM_REG * 2; i += 2)
++ csum_new += data[i] + (data[i + 1] << 8);
++ csum_new = EEPROM_SUM - csum_new;
++
++ pr_err("/*********************/\n");
++ pr_err("Current EEPROM Checksum : 0x%04x\n", csum_old);
++ pr_err("Calculated : 0x%04x\n", csum_new);
++
++ pr_err("Offset Values\n");
++ pr_err("======== ======\n");
++ print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, data, 128, 0);
++
++ pr_err("Include this output when contacting your support provider.\n");
++ pr_err("This is not a software error! Something bad happened to\n");
++ pr_err("your hardware or EEPROM image. Ignoring this problem could\n");
++ pr_err("result in further problems, possibly loss of data,\n");
++ pr_err("corruption or system hangs!\n");
++ pr_err("The MAC Address will be reset to 00:00:00:00:00:00,\n");
++ pr_err("which is invalid and requires you to set the proper MAC\n");
++ pr_err("address manually before continuing to enable this network\n");
++ pr_err("device. Please inspect the EEPROM dump and report the\n");
++ pr_err("issue to your hardware vendor or Intel Customer Support.\n");
++ pr_err("/*********************/\n");
++
++ kfree(data);
++}
++
++/**
++ * e1000_is_need_ioport - determine if an adapter needs ioport resources or not
++ * @pdev: PCI device information struct
++ *
++ * Return true if an adapter needs ioport resources
++ **/
++static int e1000_is_need_ioport(struct pci_dev *pdev)
++{
++ switch (pdev->device) {
++ case E1000_DEV_ID_82540EM:
++ case E1000_DEV_ID_82540EM_LOM:
++ case E1000_DEV_ID_82540EP:
++ case E1000_DEV_ID_82540EP_LOM:
++ case E1000_DEV_ID_82540EP_LP:
++ case E1000_DEV_ID_82541EI:
++ case E1000_DEV_ID_82541EI_MOBILE:
++ case E1000_DEV_ID_82541ER:
++ case E1000_DEV_ID_82541ER_LOM:
++ case E1000_DEV_ID_82541GI:
++ case E1000_DEV_ID_82541GI_LF:
++ case E1000_DEV_ID_82541GI_MOBILE:
++ case E1000_DEV_ID_82544EI_COPPER:
++ case E1000_DEV_ID_82544EI_FIBER:
++ case E1000_DEV_ID_82544GC_COPPER:
++ case E1000_DEV_ID_82544GC_LOM:
++ case E1000_DEV_ID_82545EM_COPPER:
++ case E1000_DEV_ID_82545EM_FIBER:
++ case E1000_DEV_ID_82546EB_COPPER:
++ case E1000_DEV_ID_82546EB_FIBER:
++ case E1000_DEV_ID_82546EB_QUAD_COPPER:
++ return true;
++ default:
++ return false;
++ }
++}
++
++static const struct net_device_ops e1000_netdev_ops = {
++ .ndo_open = e1000_open,
++ .ndo_stop = e1000_close,
++ .ndo_start_xmit = e1000_xmit_frame,
++ .ndo_get_stats = e1000_get_stats,
++ .ndo_set_rx_mode = e1000_set_rx_mode,
++ .ndo_set_mac_address = e1000_set_mac,
++ .ndo_tx_timeout = e1000_tx_timeout,
++ .ndo_change_mtu = e1000_change_mtu,
++ .ndo_do_ioctl = e1000_ioctl,
++ .ndo_validate_addr = eth_validate_addr,
++
++ .ndo_vlan_rx_register = e1000_vlan_rx_register,
++ .ndo_vlan_rx_add_vid = e1000_vlan_rx_add_vid,
++ .ndo_vlan_rx_kill_vid = e1000_vlan_rx_kill_vid,
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ .ndo_poll_controller = e1000_netpoll,
++#endif
++};
++
++/**
++ * e1000_probe - Device Initialization Routine
++ * @pdev: PCI device information struct
++ * @ent: entry in e1000_pci_tbl
++ *
++ * Returns 0 on success, negative on failure
++ *
++ * e1000_probe initializes an adapter identified by a pci_dev structure.
++ * The OS initialization, configuring of the adapter private structure,
++ * and a hardware reset occur.
++ **/
++static int __devinit e1000_probe(struct pci_dev *pdev,
++ const struct pci_device_id *ent)
++{
++ struct net_device *netdev;
++ struct e1000_adapter *adapter;
++ struct e1000_hw *hw;
++
++ static int cards_found = 0;
++ static int global_quad_port_a = 0; /* global ksp3 port a indication */
++ int i, err, pci_using_dac;
++ u16 eeprom_data = 0;
++ u16 eeprom_apme_mask = E1000_EEPROM_APME;
++ int bars, need_ioport;
++
++ /* do not allocate ioport bars when not needed */
++ need_ioport = e1000_is_need_ioport(pdev);
++ if (need_ioport) {
++ bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
++ err = pci_enable_device(pdev);
++ } else {
++ bars = pci_select_bars(pdev, IORESOURCE_MEM);
++ err = pci_enable_device_mem(pdev);
++ }
++ if (err)
++ return err;
++
++ if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) &&
++ !dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64))) {
++ pci_using_dac = 1;
++ } else {
++ err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
++ if (err) {
++ err = dma_set_coherent_mask(&pdev->dev,
++ DMA_BIT_MASK(32));
++ if (err) {
++ pr_err("No usable DMA config, aborting\n");
++ goto err_dma;
++ }
++ }
++ pci_using_dac = 0;
++ }
++
++ err = pci_request_selected_regions(pdev, bars, e1000_driver_name);
++ if (err)
++ goto err_pci_reg;
++
++ pci_set_master(pdev);
++ err = pci_save_state(pdev);
++ if (err)
++ goto err_alloc_etherdev;
++
++ err = -ENOMEM;
++ netdev = alloc_etherdev(sizeof(struct e1000_adapter));
++ if (!netdev)
++ goto err_alloc_etherdev;
++
++ SET_NETDEV_DEV(netdev, &pdev->dev);
++
++ pci_set_drvdata(pdev, netdev);
++ adapter = netdev_priv(netdev);
++ adapter->netdev = netdev;
++ adapter->pdev = pdev;
++ adapter->msg_enable = (1 << debug) - 1;
++ adapter->bars = bars;
++ adapter->need_ioport = need_ioport;
++
++ hw = &adapter->hw;
++ hw->back = adapter;
++
++ err = -EIO;
++ hw->hw_addr = pci_ioremap_bar(pdev, BAR_0);
++ if (!hw->hw_addr)
++ goto err_ioremap;
++
++ if (adapter->need_ioport) {
++ for (i = BAR_1; i <= BAR_5; i++) {
++ if (pci_resource_len(pdev, i) == 0)
++ continue;
++ if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
++ hw->io_base = pci_resource_start(pdev, i);
++ break;
++ }
++ }
++ }
++
++ netdev->netdev_ops = &e1000_netdev_ops;
++ e1000_set_ethtool_ops(netdev);
++ netdev->watchdog_timeo = 5 * HZ;
++ netif_napi_add(netdev, &adapter->napi, e1000_clean, 64);
++
++ strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
++
++ adapter->bd_number = cards_found;
++
++ /* setup the private structure */
++
++ err = e1000_sw_init(adapter);
++ if (err)
++ goto err_sw_init;
++
++ err = -EIO;
++
++ if (hw->mac_type >= e1000_82543) {
++ netdev->features = NETIF_F_SG |
++ NETIF_F_HW_CSUM |
++ NETIF_F_HW_VLAN_TX |
++ NETIF_F_HW_VLAN_RX |
++ NETIF_F_HW_VLAN_FILTER;
++ }
++
++ if ((hw->mac_type >= e1000_82544) &&
++ (hw->mac_type != e1000_82547))
++ netdev->features |= NETIF_F_TSO;
++
++ if (pci_using_dac)
++ netdev->features |= NETIF_F_HIGHDMA;
++
++ netdev->vlan_features |= NETIF_F_TSO;
++ netdev->vlan_features |= NETIF_F_HW_CSUM;
++ netdev->vlan_features |= NETIF_F_SG;
++
++ adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw);
++
++ /* initialize eeprom parameters */
++ if (e1000_init_eeprom_params(hw)) {
++ e_err("EEPROM initialization failed\n");
++ goto err_eeprom;
++ }
++
++ /* before reading the EEPROM, reset the controller to
++ * put the device in a known good starting state */
++
++ e1000_reset_hw(hw);
++
++ /* make sure the EEPROM is good */
++ if (e1000_validate_eeprom_checksum(hw) < 0) {
++ e_err("The EEPROM Checksum Is Not Valid\n");
++ e1000_dump_eeprom(adapter);
++ /*
++ * set MAC address to all zeroes to invalidate and temporary
++ * disable this device for the user. This blocks regular
++ * traffic while still permitting ethtool ioctls from reaching
++ * the hardware as well as allowing the user to run the
++ * interface after manually setting a hw addr using
++ * `ip set address`
++ */
++ memset(hw->mac_addr, 0, netdev->addr_len);
++ } else {
++ /* copy the MAC address out of the EEPROM */
++ if (e1000_read_mac_addr(hw))
++ e_err("EEPROM Read Error\n");
++ }
++ /* don't block initalization here due to bad MAC address */
++ memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len);
++ memcpy(netdev->perm_addr, hw->mac_addr, netdev->addr_len);
++
++ if (!is_valid_ether_addr(netdev->perm_addr))
++ e_err("Invalid MAC Address\n");
++
++ e1000_get_bus_info(hw);
++
++ init_timer(&adapter->tx_fifo_stall_timer);
++ adapter->tx_fifo_stall_timer.function = &e1000_82547_tx_fifo_stall;
++ adapter->tx_fifo_stall_timer.data = (unsigned long)adapter;
++
++ init_timer(&adapter->watchdog_timer);
++ adapter->watchdog_timer.function = &e1000_watchdog;
++ adapter->watchdog_timer.data = (unsigned long) adapter;
++
++ init_timer(&adapter->phy_info_timer);
++ adapter->phy_info_timer.function = &e1000_update_phy_info;
++ adapter->phy_info_timer.data = (unsigned long)adapter;
++
++ INIT_WORK(&adapter->reset_task, e1000_reset_task);
++
++ e1000_check_options(adapter);
++
++ /* Initial Wake on LAN setting
++ * If APM wake is enabled in the EEPROM,
++ * enable the ACPI Magic Packet filter
++ */
++
++ switch (hw->mac_type) {
++ case e1000_82542_rev2_0:
++ case e1000_82542_rev2_1:
++ case e1000_82543:
++ break;
++ case e1000_82544:
++ e1000_read_eeprom(hw,
++ EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
++ eeprom_apme_mask = E1000_EEPROM_82544_APM;
++ break;
++ case e1000_82546:
++ case e1000_82546_rev_3:
++ if (er32(STATUS) & E1000_STATUS_FUNC_1){
++ e1000_read_eeprom(hw,
++ EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
++ break;
++ }
++ /* Fall Through */
++ default:
++ e1000_read_eeprom(hw,
++ EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
++ break;
++ }
++ if (eeprom_data & eeprom_apme_mask)
++ adapter->eeprom_wol |= E1000_WUFC_MAG;
++
++ /* now that we have the eeprom settings, apply the special cases
++ * where the eeprom may be wrong or the board simply won't support
++ * wake on lan on a particular port */
++ switch (pdev->device) {
++ case E1000_DEV_ID_82546GB_PCIE:
++ adapter->eeprom_wol = 0;
++ break;
++ case E1000_DEV_ID_82546EB_FIBER:
++ case E1000_DEV_ID_82546GB_FIBER:
++ /* Wake events only supported on port A for dual fiber
++ * regardless of eeprom setting */
++ if (er32(STATUS) & E1000_STATUS_FUNC_1)
++ adapter->eeprom_wol = 0;
++ break;
++ case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
++ /* if quad port adapter, disable WoL on all but port A */
++ if (global_quad_port_a != 0)
++ adapter->eeprom_wol = 0;
++ else
++ adapter->quad_port_a = 1;
++ /* Reset for multiple quad port adapters */
++ if (++global_quad_port_a == 4)
++ global_quad_port_a = 0;
++ break;
++ }
++
++ /* initialize the wol settings based on the eeprom settings */
++ adapter->wol = adapter->eeprom_wol;
++ device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
++
++ /* reset the hardware with the new settings */
++ e1000_reset(adapter);
++
++ strcpy(netdev->name, "eth%d");
++ err = register_netdev(netdev);
++ if (err)
++ goto err_register;
++
++ /* print bus type/speed/width info */
++ e_info("(PCI%s:%dMHz:%d-bit) %pM\n",
++ ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""),
++ ((hw->bus_speed == e1000_bus_speed_133) ? 133 :
++ (hw->bus_speed == e1000_bus_speed_120) ? 120 :
++ (hw->bus_speed == e1000_bus_speed_100) ? 100 :
++ (hw->bus_speed == e1000_bus_speed_66) ? 66 : 33),
++ ((hw->bus_width == e1000_bus_width_64) ? 64 : 32),
++ netdev->dev_addr);
++
++ /* carrier off reporting is important to ethtool even BEFORE open */
++ netif_carrier_off(netdev);
++
++ e_info("Intel(R) PRO/1000 Network Connection\n");
++
++ cards_found++;
++ return 0;
++
++err_register:
++err_eeprom:
++ e1000_phy_hw_reset(hw);
++
++ if (hw->flash_address)
++ iounmap(hw->flash_address);
++ kfree(adapter->tx_ring);
++ kfree(adapter->rx_ring);
++err_sw_init:
++ iounmap(hw->hw_addr);
++err_ioremap:
++ free_netdev(netdev);
++err_alloc_etherdev:
++ pci_release_selected_regions(pdev, bars);
++err_pci_reg:
++err_dma:
++ pci_disable_device(pdev);
++ return err;
++}
++
++/**
++ * e1000_remove - Device Removal Routine
++ * @pdev: PCI device information struct
++ *
++ * e1000_remove is called by the PCI subsystem to alert the driver
++ * that it should release a PCI device. The could be caused by a
++ * Hot-Plug event, or because the driver is going to be removed from
++ * memory.
++ **/
++
++static void __devexit e1000_remove(struct pci_dev *pdev)
++{
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++
++ set_bit(__E1000_DOWN, &adapter->flags);
++ del_timer_sync(&adapter->tx_fifo_stall_timer);
++ del_timer_sync(&adapter->watchdog_timer);
++ del_timer_sync(&adapter->phy_info_timer);
++
++ cancel_work_sync(&adapter->reset_task);
++
++ e1000_release_manageability(adapter);
++
++ unregister_netdev(netdev);
++
++ e1000_phy_hw_reset(hw);
++
++ kfree(adapter->tx_ring);
++ kfree(adapter->rx_ring);
++
++ iounmap(hw->hw_addr);
++ if (hw->flash_address)
++ iounmap(hw->flash_address);
++ pci_release_selected_regions(pdev, adapter->bars);
++
++ free_netdev(netdev);
++
++ pci_disable_device(pdev);
++}
++
++/**
++ * e1000_sw_init - Initialize general software structures (struct e1000_adapter)
++ * @adapter: board private structure to initialize
++ *
++ * e1000_sw_init initializes the Adapter private data structure.
++ * Fields are initialized based on PCI device information and
++ * OS network device settings (MTU size).
++ **/
++
++static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ struct pci_dev *pdev = adapter->pdev;
++
++ /* PCI config space info */
++
++ hw->vendor_id = pdev->vendor;
++ hw->device_id = pdev->device;
++ hw->subsystem_vendor_id = pdev->subsystem_vendor;
++ hw->subsystem_id = pdev->subsystem_device;
++ hw->revision_id = pdev->revision;
++
++ pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
++
++ adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
++ hw->max_frame_size = netdev->mtu +
++ ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
++ hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
++
++ /* identify the MAC */
++
++ if (e1000_set_mac_type(hw)) {
++ e_err("Unknown MAC Type\n");
++ return -EIO;
++ }
++
++ switch (hw->mac_type) {
++ default:
++ break;
++ case e1000_82541:
++ case e1000_82547:
++ case e1000_82541_rev_2:
++ case e1000_82547_rev_2:
++ hw->phy_init_script = 1;
++ break;
++ }
++
++ e1000_set_media_type(hw);
++
++ hw->wait_autoneg_complete = false;
++ hw->tbi_compatibility_en = true;
++ hw->adaptive_ifs = true;
++
++ /* Copper options */
++
++ if (hw->media_type == e1000_media_type_copper) {
++ hw->mdix = AUTO_ALL_MODES;
++ hw->disable_polarity_correction = false;
++ hw->master_slave = E1000_MASTER_SLAVE;
++ }
++
++ adapter->num_tx_queues = 1;
++ adapter->num_rx_queues = 1;
++
++ if (e1000_alloc_queues(adapter)) {
++ e_err("Unable to allocate memory for queues\n");
++ return -ENOMEM;
++ }
++
++ /* Explicitly disable IRQ since the NIC can be in any state. */
++ e1000_irq_disable(adapter);
++
++ spin_lock_init(&adapter->stats_lock);
++
++ set_bit(__E1000_DOWN, &adapter->flags);
++
++ return 0;
++}
++
++/**
++ * e1000_alloc_queues - Allocate memory for all rings
++ * @adapter: board private structure to initialize
++ *
++ * We allocate one ring per queue at run-time since we don't know the
++ * number of queues at compile-time.
++ **/
++
++static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
++{
++ adapter->tx_ring = kcalloc(adapter->num_tx_queues,
++ sizeof(struct e1000_tx_ring), GFP_KERNEL);
++ if (!adapter->tx_ring)
++ return -ENOMEM;
++
++ adapter->rx_ring = kcalloc(adapter->num_rx_queues,
++ sizeof(struct e1000_rx_ring), GFP_KERNEL);
++ if (!adapter->rx_ring) {
++ kfree(adapter->tx_ring);
++ return -ENOMEM;
++ }
++
++ return E1000_SUCCESS;
++}
++
++/**
++ * e1000_open - Called when a network interface is made active
++ * @netdev: network interface device structure
++ *
++ * Returns 0 on success, negative value on failure
++ *
++ * The open entry point is called when a network interface is made
++ * active by the system (IFF_UP). At this point all resources needed
++ * for transmit and receive operations are allocated, the interrupt
++ * handler is registered with the OS, the watchdog timer is started,
++ * and the stack is notified that the interface is ready.
++ **/
++
++static int e1000_open(struct net_device *netdev)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++ int err;
++
++ /* disallow open during test */
++ if (test_bit(__E1000_TESTING, &adapter->flags))
++ return -EBUSY;
++
++ netif_carrier_off(netdev);
++
++ /* allocate transmit descriptors */
++ err = e1000_setup_all_tx_resources(adapter);
++ if (err)
++ goto err_setup_tx;
++
++ /* allocate receive descriptors */
++ err = e1000_setup_all_rx_resources(adapter);
++ if (err)
++ goto err_setup_rx;
++
++ e1000_power_up_phy(adapter);
++
++ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
++ if ((hw->mng_cookie.status &
++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
++ e1000_update_mng_vlan(adapter);
++ }
++
++ /* before we allocate an interrupt, we must be ready to handle it.
++ * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
++ * as soon as we call pci_request_irq, so we have to setup our
++ * clean_rx handler before we do so. */
++ e1000_configure(adapter);
++
++ err = e1000_request_irq(adapter);
++ if (err)
++ goto err_req_irq;
++
++ /* From here on the code is the same as e1000_up() */
++ clear_bit(__E1000_DOWN, &adapter->flags);
++
++ napi_enable(&adapter->napi);
++
++ e1000_irq_enable(adapter);
++
++ netif_start_queue(netdev);
++
++ /* fire a link status change interrupt to start the watchdog */
++ ew32(ICS, E1000_ICS_LSC);
++
++ return E1000_SUCCESS;
++
++err_req_irq:
++ e1000_power_down_phy(adapter);
++ e1000_free_all_rx_resources(adapter);
++err_setup_rx:
++ e1000_free_all_tx_resources(adapter);
++err_setup_tx:
++ e1000_reset(adapter);
++
++ return err;
++}
++
++/**
++ * e1000_close - Disables a network interface
++ * @netdev: network interface device structure
++ *
++ * Returns 0, this is not allowed to fail
++ *
++ * The close entry point is called when an interface is de-activated
++ * by the OS. The hardware is still under the drivers control, but
++ * needs to be disabled. A global MAC reset is issued to stop the
++ * hardware, and all transmit and receive resources are freed.
++ **/
++
++static int e1000_close(struct net_device *netdev)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++
++ WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
++ e1000_down(adapter);
++ e1000_power_down_phy(adapter);
++ e1000_free_irq(adapter);
++
++ e1000_free_all_tx_resources(adapter);
++ e1000_free_all_rx_resources(adapter);
++
++ /* kill manageability vlan ID if supported, but not if a vlan with
++ * the same ID is registered on the host OS (let 8021q kill it) */
++ if ((hw->mng_cookie.status &
++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
++ !(adapter->vlgrp &&
++ vlan_group_get_device(adapter->vlgrp, adapter->mng_vlan_id))) {
++ e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
++ }
++
++ return 0;
++}
++
++/**
++ * e1000_check_64k_bound - check that memory doesn't cross 64kB boundary
++ * @adapter: address of board private structure
++ * @start: address of beginning of memory
++ * @len: length of memory
++ **/
++static bool e1000_check_64k_bound(struct e1000_adapter *adapter, void *start,
++ unsigned long len)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ unsigned long begin = (unsigned long)start;
++ unsigned long end = begin + len;
++
++ /* First rev 82545 and 82546 need to not allow any memory
++ * write location to cross 64k boundary due to errata 23 */
++ if (hw->mac_type == e1000_82545 ||
++ hw->mac_type == e1000_82546) {
++ return ((begin ^ (end - 1)) >> 16) != 0 ? false : true;
++ }
++
++ return true;
++}
++
++/**
++ * e1000_setup_tx_resources - allocate Tx resources (Descriptors)
++ * @adapter: board private structure
++ * @txdr: tx descriptor ring (for a specific queue) to setup
++ *
++ * Return 0 on success, negative on failure
++ **/
++
++static int e1000_setup_tx_resources(struct e1000_adapter *adapter,
++ struct e1000_tx_ring *txdr)
++{
++ struct pci_dev *pdev = adapter->pdev;
++ int size;
++
++ size = sizeof(struct e1000_buffer) * txdr->count;
++ txdr->buffer_info = vmalloc(size);
++ if (!txdr->buffer_info) {
++ e_err("Unable to allocate memory for the Tx descriptor ring\n");
++ return -ENOMEM;
++ }
++ memset(txdr->buffer_info, 0, size);
++
++ /* round up to nearest 4K */
++
++ txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
++ txdr->size = ALIGN(txdr->size, 4096);
++
++ txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
++ GFP_KERNEL);
++ if (!txdr->desc) {
++setup_tx_desc_die:
++ vfree(txdr->buffer_info);
++ e_err("Unable to allocate memory for the Tx descriptor ring\n");
++ return -ENOMEM;
++ }
++
++ /* Fix for errata 23, can't cross 64kB boundary */
++ if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) {
++ void *olddesc = txdr->desc;
++ dma_addr_t olddma = txdr->dma;
++ e_err("txdr align check failed: %u bytes at %p\n",
++ txdr->size, txdr->desc);
++ /* Try again, without freeing the previous */
++ txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size,
++ &txdr->dma, GFP_KERNEL);
++ /* Failed allocation, critical failure */
++ if (!txdr->desc) {
++ dma_free_coherent(&pdev->dev, txdr->size, olddesc,
++ olddma);
++ goto setup_tx_desc_die;
++ }
++
++ if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) {
++ /* give up */
++ dma_free_coherent(&pdev->dev, txdr->size, txdr->desc,
++ txdr->dma);
++ dma_free_coherent(&pdev->dev, txdr->size, olddesc,
++ olddma);
++ e_err("Unable to allocate aligned memory "
++ "for the transmit descriptor ring\n");
++ vfree(txdr->buffer_info);
++ return -ENOMEM;
++ } else {
++ /* Free old allocation, new allocation was successful */
++ dma_free_coherent(&pdev->dev, txdr->size, olddesc,
++ olddma);
++ }
++ }
++ memset(txdr->desc, 0, txdr->size);
++
++ txdr->next_to_use = 0;
++ txdr->next_to_clean = 0;
++
++ return 0;
++}
++
++/**
++ * e1000_setup_all_tx_resources - wrapper to allocate Tx resources
++ * (Descriptors) for all queues
++ * @adapter: board private structure
++ *
++ * Return 0 on success, negative on failure
++ **/
++
++int e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
++{
++ int i, err = 0;
++
++ for (i = 0; i < adapter->num_tx_queues; i++) {
++ err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]);
++ if (err) {
++ e_err("Allocation for Tx Queue %u failed\n", i);
++ for (i-- ; i >= 0; i--)
++ e1000_free_tx_resources(adapter,
++ &adapter->tx_ring[i]);
++ break;
++ }
++ }
++
++ return err;
++}
++
++/**
++ * e1000_configure_tx - Configure 8254x Transmit Unit after Reset
++ * @adapter: board private structure
++ *
++ * Configure the Tx unit of the MAC after a reset.
++ **/
++
++static void e1000_configure_tx(struct e1000_adapter *adapter)
++{
++ u64 tdba;
++ struct e1000_hw *hw = &adapter->hw;
++ u32 tdlen, tctl, tipg;
++ u32 ipgr1, ipgr2;
++
++ /* Setup the HW Tx Head and Tail descriptor pointers */
++
++ switch (adapter->num_tx_queues) {
++ case 1:
++ default:
++ tdba = adapter->tx_ring[0].dma;
++ tdlen = adapter->tx_ring[0].count *
++ sizeof(struct e1000_tx_desc);
++ ew32(TDLEN, tdlen);
++ ew32(TDBAH, (tdba >> 32));
++ ew32(TDBAL, (tdba & 0x00000000ffffffffULL));
++ ew32(TDT, 0);
++ ew32(TDH, 0);
++ adapter->tx_ring[0].tdh = ((hw->mac_type >= e1000_82543) ? E1000_TDH : E1000_82542_TDH);
++ adapter->tx_ring[0].tdt = ((hw->mac_type >= e1000_82543) ? E1000_TDT : E1000_82542_TDT);
++ break;
++ }
++
++ /* Set the default values for the Tx Inter Packet Gap timer */
++ if ((hw->media_type == e1000_media_type_fiber ||
++ hw->media_type == e1000_media_type_internal_serdes))
++ tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
++ else
++ tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
++
++ switch (hw->mac_type) {
++ case e1000_82542_rev2_0:
++ case e1000_82542_rev2_1:
++ tipg = DEFAULT_82542_TIPG_IPGT;
++ ipgr1 = DEFAULT_82542_TIPG_IPGR1;
++ ipgr2 = DEFAULT_82542_TIPG_IPGR2;
++ break;
++ default:
++ ipgr1 = DEFAULT_82543_TIPG_IPGR1;
++ ipgr2 = DEFAULT_82543_TIPG_IPGR2;
++ break;
++ }
++ tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT;
++ tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT;
++ ew32(TIPG, tipg);
++
++ /* Set the Tx Interrupt Delay register */
++
++ ew32(TIDV, adapter->tx_int_delay);
++ if (hw->mac_type >= e1000_82540)
++ ew32(TADV, adapter->tx_abs_int_delay);
++
++ /* Program the Transmit Control Register */
++
++ tctl = er32(TCTL);
++ tctl &= ~E1000_TCTL_CT;
++ tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC |
++ (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
++
++ e1000_config_collision_dist(hw);
++
++ /* Setup Transmit Descriptor Settings for eop descriptor */
++ adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS;
++
++ /* only set IDE if we are delaying interrupts using the timers */
++ if (adapter->tx_int_delay)
++ adapter->txd_cmd |= E1000_TXD_CMD_IDE;
++
++ if (hw->mac_type < e1000_82543)
++ adapter->txd_cmd |= E1000_TXD_CMD_RPS;
++ else
++ adapter->txd_cmd |= E1000_TXD_CMD_RS;
++
++ /* Cache if we're 82544 running in PCI-X because we'll
++ * need this to apply a workaround later in the send path. */
++ if (hw->mac_type == e1000_82544 &&
++ hw->bus_type == e1000_bus_type_pcix)
++ adapter->pcix_82544 = 1;
++
++ ew32(TCTL, tctl);
++
++}
++
++/**
++ * e1000_setup_rx_resources - allocate Rx resources (Descriptors)
++ * @adapter: board private structure
++ * @rxdr: rx descriptor ring (for a specific queue) to setup
++ *
++ * Returns 0 on success, negative on failure
++ **/
++
++static int e1000_setup_rx_resources(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rxdr)
++{
++ struct pci_dev *pdev = adapter->pdev;
++ int size, desc_len;
++
++ size = sizeof(struct e1000_buffer) * rxdr->count;
++ rxdr->buffer_info = vmalloc(size);
++ if (!rxdr->buffer_info) {
++ e_err("Unable to allocate memory for the Rx descriptor ring\n");
++ return -ENOMEM;
++ }
++ memset(rxdr->buffer_info, 0, size);
++
++ desc_len = sizeof(struct e1000_rx_desc);
++
++ /* Round up to nearest 4K */
++
++ rxdr->size = rxdr->count * desc_len;
++ rxdr->size = ALIGN(rxdr->size, 4096);
++
++ rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
++ GFP_KERNEL);
++
++ if (!rxdr->desc) {
++ e_err("Unable to allocate memory for the Rx descriptor ring\n");
++setup_rx_desc_die:
++ vfree(rxdr->buffer_info);
++ return -ENOMEM;
++ }
++
++ /* Fix for errata 23, can't cross 64kB boundary */
++ if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
++ void *olddesc = rxdr->desc;
++ dma_addr_t olddma = rxdr->dma;
++ e_err("rxdr align check failed: %u bytes at %p\n",
++ rxdr->size, rxdr->desc);
++ /* Try again, without freeing the previous */
++ rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size,
++ &rxdr->dma, GFP_KERNEL);
++ /* Failed allocation, critical failure */
++ if (!rxdr->desc) {
++ dma_free_coherent(&pdev->dev, rxdr->size, olddesc,
++ olddma);
++ e_err("Unable to allocate memory for the Rx descriptor "
++ "ring\n");
++ goto setup_rx_desc_die;
++ }
++
++ if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
++ /* give up */
++ dma_free_coherent(&pdev->dev, rxdr->size, rxdr->desc,
++ rxdr->dma);
++ dma_free_coherent(&pdev->dev, rxdr->size, olddesc,
++ olddma);
++ e_err("Unable to allocate aligned memory for the Rx "
++ "descriptor ring\n");
++ goto setup_rx_desc_die;
++ } else {
++ /* Free old allocation, new allocation was successful */
++ dma_free_coherent(&pdev->dev, rxdr->size, olddesc,
++ olddma);
++ }
++ }
++ memset(rxdr->desc, 0, rxdr->size);
++
++ rxdr->next_to_clean = 0;
++ rxdr->next_to_use = 0;
++ rxdr->rx_skb_top = NULL;
++
++ return 0;
++}
++
++/**
++ * e1000_setup_all_rx_resources - wrapper to allocate Rx resources
++ * (Descriptors) for all queues
++ * @adapter: board private structure
++ *
++ * Return 0 on success, negative on failure
++ **/
++
++int e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
++{
++ int i, err = 0;
++
++ for (i = 0; i < adapter->num_rx_queues; i++) {
++ err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]);
++ if (err) {
++ e_err("Allocation for Rx Queue %u failed\n", i);
++ for (i-- ; i >= 0; i--)
++ e1000_free_rx_resources(adapter,
++ &adapter->rx_ring[i]);
++ break;
++ }
++ }
++
++ return err;
++}
++
++/**
++ * e1000_setup_rctl - configure the receive control registers
++ * @adapter: Board private structure
++ **/
++static void e1000_setup_rctl(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ u32 rctl;
++
++ rctl = er32(RCTL);
++
++ rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
++
++ rctl |= E1000_RCTL_EN | E1000_RCTL_BAM |
++ E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
++ (hw->mc_filter_type << E1000_RCTL_MO_SHIFT);
++
++ if (hw->tbi_compatibility_on == 1)
++ rctl |= E1000_RCTL_SBP;
++ else
++ rctl &= ~E1000_RCTL_SBP;
++
++ if (adapter->netdev->mtu <= ETH_DATA_LEN)
++ rctl &= ~E1000_RCTL_LPE;
++ else
++ rctl |= E1000_RCTL_LPE;
++
++ /* Setup buffer sizes */
++ rctl &= ~E1000_RCTL_SZ_4096;
++ rctl |= E1000_RCTL_BSEX;
++ switch (adapter->rx_buffer_len) {
++ case E1000_RXBUFFER_2048:
++ default:
++ rctl |= E1000_RCTL_SZ_2048;
++ rctl &= ~E1000_RCTL_BSEX;
++ break;
++ case E1000_RXBUFFER_4096:
++ rctl |= E1000_RCTL_SZ_4096;
++ break;
++ case E1000_RXBUFFER_8192:
++ rctl |= E1000_RCTL_SZ_8192;
++ break;
++ case E1000_RXBUFFER_16384:
++ rctl |= E1000_RCTL_SZ_16384;
++ break;
++ }
++
++ ew32(RCTL, rctl);
++}
++
++/**
++ * e1000_configure_rx - Configure 8254x Receive Unit after Reset
++ * @adapter: board private structure
++ *
++ * Configure the Rx unit of the MAC after a reset.
++ **/
++
++static void e1000_configure_rx(struct e1000_adapter *adapter)
++{
++ u64 rdba;
++ struct e1000_hw *hw = &adapter->hw;
++ u32 rdlen, rctl, rxcsum;
++
++ if (adapter->netdev->mtu > ETH_DATA_LEN) {
++ rdlen = adapter->rx_ring[0].count *
++ sizeof(struct e1000_rx_desc);
++ adapter->clean_rx = e1000_clean_jumbo_rx_irq;
++ adapter->alloc_rx_buf = e1000_alloc_jumbo_rx_buffers;
++ } else {
++ rdlen = adapter->rx_ring[0].count *
++ sizeof(struct e1000_rx_desc);
++ adapter->clean_rx = e1000_clean_rx_irq;
++ adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
++ }
++
++ /* disable receives while setting up the descriptors */
++ rctl = er32(RCTL);
++ ew32(RCTL, rctl & ~E1000_RCTL_EN);
++
++ /* set the Receive Delay Timer Register */
++ ew32(RDTR, adapter->rx_int_delay);
++
++ if (hw->mac_type >= e1000_82540) {
++ ew32(RADV, adapter->rx_abs_int_delay);
++ if (adapter->itr_setting != 0)
++ ew32(ITR, 1000000000 / (adapter->itr * 256));
++ }
++
++ /* Setup the HW Rx Head and Tail Descriptor Pointers and
++ * the Base and Length of the Rx Descriptor Ring */
++ switch (adapter->num_rx_queues) {
++ case 1:
++ default:
++ rdba = adapter->rx_ring[0].dma;
++ ew32(RDLEN, rdlen);
++ ew32(RDBAH, (rdba >> 32));
++ ew32(RDBAL, (rdba & 0x00000000ffffffffULL));
++ ew32(RDT, 0);
++ ew32(RDH, 0);
++ adapter->rx_ring[0].rdh = ((hw->mac_type >= e1000_82543) ? E1000_RDH : E1000_82542_RDH);
++ adapter->rx_ring[0].rdt = ((hw->mac_type >= e1000_82543) ? E1000_RDT : E1000_82542_RDT);
++ break;
++ }
++
++ /* Enable 82543 Receive Checksum Offload for TCP and UDP */
++ if (hw->mac_type >= e1000_82543) {
++ rxcsum = er32(RXCSUM);
++ if (adapter->rx_csum)
++ rxcsum |= E1000_RXCSUM_TUOFL;
++ else
++ /* don't need to clear IPPCSE as it defaults to 0 */
++ rxcsum &= ~E1000_RXCSUM_TUOFL;
++ ew32(RXCSUM, rxcsum);
++ }
++
++ /* Enable Receives */
++ ew32(RCTL, rctl);
++}
++
++/**
++ * e1000_free_tx_resources - Free Tx Resources per Queue
++ * @adapter: board private structure
++ * @tx_ring: Tx descriptor ring for a specific queue
++ *
++ * Free all transmit software resources
++ **/
++
++static void e1000_free_tx_resources(struct e1000_adapter *adapter,
++ struct e1000_tx_ring *tx_ring)
++{
++ struct pci_dev *pdev = adapter->pdev;
++
++ e1000_clean_tx_ring(adapter, tx_ring);
++
++ vfree(tx_ring->buffer_info);
++ tx_ring->buffer_info = NULL;
++
++ dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc,
++ tx_ring->dma);
++
++ tx_ring->desc = NULL;
++}
++
++/**
++ * e1000_free_all_tx_resources - Free Tx Resources for All Queues
++ * @adapter: board private structure
++ *
++ * Free all transmit software resources
++ **/
++
++void e1000_free_all_tx_resources(struct e1000_adapter *adapter)
++{
++ int i;
++
++ for (i = 0; i < adapter->num_tx_queues; i++)
++ e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
++}
++
++static void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
++ struct e1000_buffer *buffer_info)
++{
++ if (buffer_info->dma) {
++ if (buffer_info->mapped_as_page)
++ dma_unmap_page(&adapter->pdev->dev, buffer_info->dma,
++ buffer_info->length, DMA_TO_DEVICE);
++ else
++ dma_unmap_single(&adapter->pdev->dev, buffer_info->dma,
++ buffer_info->length,
++ DMA_TO_DEVICE);
++ buffer_info->dma = 0;
++ }
++ if (buffer_info->skb) {
++ dev_kfree_skb_any(buffer_info->skb);
++ buffer_info->skb = NULL;
++ }
++ buffer_info->time_stamp = 0;
++ /* buffer_info must be completely set up in the transmit path */
++}
++
++/**
++ * e1000_clean_tx_ring - Free Tx Buffers
++ * @adapter: board private structure
++ * @tx_ring: ring to be cleaned
++ **/
++
++static void e1000_clean_tx_ring(struct e1000_adapter *adapter,
++ struct e1000_tx_ring *tx_ring)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ struct e1000_buffer *buffer_info;
++ unsigned long size;
++ unsigned int i;
++
++ /* Free all the Tx ring sk_buffs */
++
++ for (i = 0; i < tx_ring->count; i++) {
++ buffer_info = &tx_ring->buffer_info[i];
++ e1000_unmap_and_free_tx_resource(adapter, buffer_info);
++ }
++
++ size = sizeof(struct e1000_buffer) * tx_ring->count;
++ memset(tx_ring->buffer_info, 0, size);
++
++ /* Zero out the descriptor ring */
++
++ memset(tx_ring->desc, 0, tx_ring->size);
++
++ tx_ring->next_to_use = 0;
++ tx_ring->next_to_clean = 0;
++ tx_ring->last_tx_tso = 0;
++
++ writel(0, hw->hw_addr + tx_ring->tdh);
++ writel(0, hw->hw_addr + tx_ring->tdt);
++}
++
++/**
++ * e1000_clean_all_tx_rings - Free Tx Buffers for all queues
++ * @adapter: board private structure
++ **/
++
++static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
++{
++ int i;
++
++ for (i = 0; i < adapter->num_tx_queues; i++)
++ e1000_clean_tx_ring(adapter, &adapter->tx_ring[i]);
++}
++
++/**
++ * e1000_free_rx_resources - Free Rx Resources
++ * @adapter: board private structure
++ * @rx_ring: ring to clean the resources from
++ *
++ * Free all receive software resources
++ **/
++
++static void e1000_free_rx_resources(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring)
++{
++ struct pci_dev *pdev = adapter->pdev;
++
++ e1000_clean_rx_ring(adapter, rx_ring);
++
++ vfree(rx_ring->buffer_info);
++ rx_ring->buffer_info = NULL;
++
++ dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc,
++ rx_ring->dma);
++
++ rx_ring->desc = NULL;
++}
++
++/**
++ * e1000_free_all_rx_resources - Free Rx Resources for All Queues
++ * @adapter: board private structure
++ *
++ * Free all receive software resources
++ **/
++
++void e1000_free_all_rx_resources(struct e1000_adapter *adapter)
++{
++ int i;
++
++ for (i = 0; i < adapter->num_rx_queues; i++)
++ e1000_free_rx_resources(adapter, &adapter->rx_ring[i]);
++}
++
++/**
++ * e1000_clean_rx_ring - Free Rx Buffers per Queue
++ * @adapter: board private structure
++ * @rx_ring: ring to free buffers from
++ **/
++
++static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ struct e1000_buffer *buffer_info;
++ struct pci_dev *pdev = adapter->pdev;
++ unsigned long size;
++ unsigned int i;
++
++ /* Free all the Rx ring sk_buffs */
++ for (i = 0; i < rx_ring->count; i++) {
++ buffer_info = &rx_ring->buffer_info[i];
++ if (buffer_info->dma &&
++ adapter->clean_rx == e1000_clean_rx_irq) {
++ dma_unmap_single(&pdev->dev, buffer_info->dma,
++ buffer_info->length,
++ DMA_FROM_DEVICE);
++ } else if (buffer_info->dma &&
++ adapter->clean_rx == e1000_clean_jumbo_rx_irq) {
++ dma_unmap_page(&pdev->dev, buffer_info->dma,
++ buffer_info->length,
++ DMA_FROM_DEVICE);
++ }
++
++ buffer_info->dma = 0;
++ if (buffer_info->page) {
++ put_page(buffer_info->page);
++ buffer_info->page = NULL;
++ }
++ if (buffer_info->skb) {
++ dev_kfree_skb(buffer_info->skb);
++ buffer_info->skb = NULL;
++ }
++ }
++
++ /* there also may be some cached data from a chained receive */
++ if (rx_ring->rx_skb_top) {
++ dev_kfree_skb(rx_ring->rx_skb_top);
++ rx_ring->rx_skb_top = NULL;
++ }
++
++ size = sizeof(struct e1000_buffer) * rx_ring->count;
++ memset(rx_ring->buffer_info, 0, size);
++
++ /* Zero out the descriptor ring */
++ memset(rx_ring->desc, 0, rx_ring->size);
++
++ rx_ring->next_to_clean = 0;
++ rx_ring->next_to_use = 0;
++
++ writel(0, hw->hw_addr + rx_ring->rdh);
++ writel(0, hw->hw_addr + rx_ring->rdt);
++}
++
++/**
++ * e1000_clean_all_rx_rings - Free Rx Buffers for all queues
++ * @adapter: board private structure
++ **/
++
++static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
++{
++ int i;
++
++ for (i = 0; i < adapter->num_rx_queues; i++)
++ e1000_clean_rx_ring(adapter, &adapter->rx_ring[i]);
++}
++
++/* The 82542 2.0 (revision 2) needs to have the receive unit in reset
++ * and memory write and invalidate disabled for certain operations
++ */
++static void e1000_enter_82542_rst(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ u32 rctl;
++
++ e1000_pci_clear_mwi(hw);
++
++ rctl = er32(RCTL);
++ rctl |= E1000_RCTL_RST;
++ ew32(RCTL, rctl);
++ E1000_WRITE_FLUSH();
++ mdelay(5);
++
++ if (netif_running(netdev))
++ e1000_clean_all_rx_rings(adapter);
++}
++
++static void e1000_leave_82542_rst(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ u32 rctl;
++
++ rctl = er32(RCTL);
++ rctl &= ~E1000_RCTL_RST;
++ ew32(RCTL, rctl);
++ E1000_WRITE_FLUSH();
++ mdelay(5);
++
++ if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
++ e1000_pci_set_mwi(hw);
++
++ if (netif_running(netdev)) {
++ /* No need to loop, because 82542 supports only 1 queue */
++ struct e1000_rx_ring *ring = &adapter->rx_ring[0];
++ e1000_configure_rx(adapter);
++ adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring));
++ }
++}
++
++/**
++ * e1000_set_mac - Change the Ethernet Address of the NIC
++ * @netdev: network interface device structure
++ * @p: pointer to an address structure
++ *
++ * Returns 0 on success, negative on failure
++ **/
++
++static int e1000_set_mac(struct net_device *netdev, void *p)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++ struct sockaddr *addr = p;
++
++ if (!is_valid_ether_addr(addr->sa_data))
++ return -EADDRNOTAVAIL;
++
++ /* 82542 2.0 needs to be in reset to write receive address registers */
++
++ if (hw->mac_type == e1000_82542_rev2_0)
++ e1000_enter_82542_rst(adapter);
++
++ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
++ memcpy(hw->mac_addr, addr->sa_data, netdev->addr_len);
++
++ e1000_rar_set(hw, hw->mac_addr, 0);
++
++ if (hw->mac_type == e1000_82542_rev2_0)
++ e1000_leave_82542_rst(adapter);
++
++ return 0;
++}
++
++/**
++ * e1000_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set
++ * @netdev: network interface device structure
++ *
++ * The set_rx_mode entry point is called whenever the unicast or multicast
++ * address lists or the network interface flags are updated. This routine is
++ * responsible for configuring the hardware for proper unicast, multicast,
++ * promiscuous mode, and all-multi behavior.
++ **/
++
++static void e1000_set_rx_mode(struct net_device *netdev)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++ struct netdev_hw_addr *ha;
++ bool use_uc = false;
++ u32 rctl;
++ u32 hash_value;
++ int i, rar_entries = E1000_RAR_ENTRIES;
++ int mta_reg_count = E1000_NUM_MTA_REGISTERS;
++ u32 *mcarray = kcalloc(mta_reg_count, sizeof(u32), GFP_ATOMIC);
++
++ if (!mcarray) {
++ e_err("memory allocation failed\n");
++ return;
++ }
++
++ /* Check for Promiscuous and All Multicast modes */
++
++ rctl = er32(RCTL);
++
++ if (netdev->flags & IFF_PROMISC) {
++ rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
++ rctl &= ~E1000_RCTL_VFE;
++ } else {
++ if (netdev->flags & IFF_ALLMULTI)
++ rctl |= E1000_RCTL_MPE;
++ else
++ rctl &= ~E1000_RCTL_MPE;
++ /* Enable VLAN filter if there is a VLAN */
++ if (adapter->vlgrp)
++ rctl |= E1000_RCTL_VFE;
++ }
++
++ if (netdev_uc_count(netdev) > rar_entries - 1) {
++ rctl |= E1000_RCTL_UPE;
++ } else if (!(netdev->flags & IFF_PROMISC)) {
++ rctl &= ~E1000_RCTL_UPE;
++ use_uc = true;
++ }
++
++ ew32(RCTL, rctl);
++
++ /* 82542 2.0 needs to be in reset to write receive address registers */
++
++ if (hw->mac_type == e1000_82542_rev2_0)
++ e1000_enter_82542_rst(adapter);
++
++ /* load the first 14 addresses into the exact filters 1-14. Unicast
++ * addresses take precedence to avoid disabling unicast filtering
++ * when possible.
++ *
++ * RAR 0 is used for the station MAC adddress
++ * if there are not 14 addresses, go ahead and clear the filters
++ */
++ i = 1;
++ if (use_uc)
++ netdev_for_each_uc_addr(ha, netdev) {
++ if (i == rar_entries)
++ break;
++ e1000_rar_set(hw, ha->addr, i++);
++ }
++
++ netdev_for_each_mc_addr(ha, netdev) {
++ if (i == rar_entries) {
++ /* load any remaining addresses into the hash table */
++ u32 hash_reg, hash_bit, mta;
++ hash_value = e1000_hash_mc_addr(hw, ha->addr);
++ hash_reg = (hash_value >> 5) & 0x7F;
++ hash_bit = hash_value & 0x1F;
++ mta = (1 << hash_bit);
++ mcarray[hash_reg] |= mta;
++ } else {
++ e1000_rar_set(hw, ha->addr, i++);
++ }
++ }
++
++ for (; i < rar_entries; i++) {
++ E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0);
++ E1000_WRITE_FLUSH();
++ E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0);
++ E1000_WRITE_FLUSH();
++ }
++
++ /* write the hash table completely, write from bottom to avoid
++ * both stupid write combining chipsets, and flushing each write */
++ for (i = mta_reg_count - 1; i >= 0 ; i--) {
++ /*
++ * If we are on an 82544 has an errata where writing odd
++ * offsets overwrites the previous even offset, but writing
++ * backwards over the range solves the issue by always
++ * writing the odd offset first
++ */
++ E1000_WRITE_REG_ARRAY(hw, MTA, i, mcarray[i]);
++ }
++ E1000_WRITE_FLUSH();
++
++ if (hw->mac_type == e1000_82542_rev2_0)
++ e1000_leave_82542_rst(adapter);
++
++ kfree(mcarray);
++}
++
++/* Need to wait a few seconds after link up to get diagnostic information from
++ * the phy */
++
++static void e1000_update_phy_info(unsigned long data)
++{
++ struct e1000_adapter *adapter = (struct e1000_adapter *)data;
++ struct e1000_hw *hw = &adapter->hw;
++ e1000_phy_get_info(hw, &adapter->phy_info);
++}
++
++/**
++ * e1000_82547_tx_fifo_stall - Timer Call-back
++ * @data: pointer to adapter cast into an unsigned long
++ **/
++
++static void e1000_82547_tx_fifo_stall(unsigned long data)
++{
++ struct e1000_adapter *adapter = (struct e1000_adapter *)data;
++ struct e1000_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ u32 tctl;
++
++ if (atomic_read(&adapter->tx_fifo_stall)) {
++ if ((er32(TDT) == er32(TDH)) &&
++ (er32(TDFT) == er32(TDFH)) &&
++ (er32(TDFTS) == er32(TDFHS))) {
++ tctl = er32(TCTL);
++ ew32(TCTL, tctl & ~E1000_TCTL_EN);
++ ew32(TDFT, adapter->tx_head_addr);
++ ew32(TDFH, adapter->tx_head_addr);
++ ew32(TDFTS, adapter->tx_head_addr);
++ ew32(TDFHS, adapter->tx_head_addr);
++ ew32(TCTL, tctl);
++ E1000_WRITE_FLUSH();
++
++ adapter->tx_fifo_head = 0;
++ atomic_set(&adapter->tx_fifo_stall, 0);
++ netif_wake_queue(netdev);
++ } else if (!test_bit(__E1000_DOWN, &adapter->flags)) {
++ mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1);
++ }
++ }
++}
++
++bool e1000_has_link(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ bool link_active = false;
++
++ /* get_link_status is set on LSC (link status) interrupt or
++ * rx sequence error interrupt. get_link_status will stay
++ * false until the e1000_check_for_link establishes link
++ * for copper adapters ONLY
++ */
++ switch (hw->media_type) {
++ case e1000_media_type_copper:
++ if (hw->get_link_status) {
++ e1000_check_for_link(hw);
++ link_active = !hw->get_link_status;
++ } else {
++ link_active = true;
++ }
++ break;
++ case e1000_media_type_fiber:
++ e1000_check_for_link(hw);
++ link_active = !!(er32(STATUS) & E1000_STATUS_LU);
++ break;
++ case e1000_media_type_internal_serdes:
++ e1000_check_for_link(hw);
++ link_active = hw->serdes_has_link;
++ break;
++ default:
++ break;
++ }
++
++ return link_active;
++}
++
++/**
++ * e1000_watchdog - Timer Call-back
++ * @data: pointer to adapter cast into an unsigned long
++ **/
++static void e1000_watchdog(unsigned long data)
++{
++ struct e1000_adapter *adapter = (struct e1000_adapter *)data;
++ struct e1000_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ struct e1000_tx_ring *txdr = adapter->tx_ring;
++ u32 link, tctl;
++
++ link = e1000_has_link(adapter);
++ if ((netif_carrier_ok(netdev)) && link)
++ goto link_up;
++
++ if (link) {
++ if (!netif_carrier_ok(netdev)) {
++ u32 ctrl;
++ bool txb2b = true;
++ /* update snapshot of PHY registers on LSC */
++ e1000_get_speed_and_duplex(hw,
++ &adapter->link_speed,
++ &adapter->link_duplex);
++
++ ctrl = er32(CTRL);
++ pr_info("%s NIC Link is Up %d Mbps %s, "
++ "Flow Control: %s\n",
++ netdev->name,
++ adapter->link_speed,
++ adapter->link_duplex == FULL_DUPLEX ?
++ "Full Duplex" : "Half Duplex",
++ ((ctrl & E1000_CTRL_TFCE) && (ctrl &
++ E1000_CTRL_RFCE)) ? "RX/TX" : ((ctrl &
++ E1000_CTRL_RFCE) ? "RX" : ((ctrl &
++ E1000_CTRL_TFCE) ? "TX" : "None")));
++
++ /* adjust timeout factor according to speed/duplex */
++ adapter->tx_timeout_factor = 1;
++ switch (adapter->link_speed) {
++ case SPEED_10:
++ txb2b = false;
++ adapter->tx_timeout_factor = 16;
++ break;
++ case SPEED_100:
++ txb2b = false;
++ /* maybe add some timeout factor ? */
++ break;
++ }
++
++ /* enable transmits in the hardware */
++ tctl = er32(TCTL);
++ tctl |= E1000_TCTL_EN;
++ ew32(TCTL, tctl);
++
++ netif_carrier_on(netdev);
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ mod_timer(&adapter->phy_info_timer,
++ round_jiffies(jiffies + 2 * HZ));
++ adapter->smartspeed = 0;
++ }
++ } else {
++ if (netif_carrier_ok(netdev)) {
++ adapter->link_speed = 0;
++ adapter->link_duplex = 0;
++ pr_info("%s NIC Link is Down\n",
++ netdev->name);
++ netif_carrier_off(netdev);
++
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ mod_timer(&adapter->phy_info_timer,
++ round_jiffies(jiffies + 2 * HZ));
++ }
++
++ e1000_smartspeed(adapter);
++ }
++
++link_up:
++ e1000_update_stats(adapter);
++
++ hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
++ adapter->tpt_old = adapter->stats.tpt;
++ hw->collision_delta = adapter->stats.colc - adapter->colc_old;
++ adapter->colc_old = adapter->stats.colc;
++
++ adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
++ adapter->gorcl_old = adapter->stats.gorcl;
++ adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
++ adapter->gotcl_old = adapter->stats.gotcl;
++
++ e1000_update_adaptive(hw);
++
++ if (!netif_carrier_ok(netdev)) {
++ if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
++ /* We've lost link, so the controller stops DMA,
++ * but we've got queued Tx work that's never going
++ * to get done, so reset controller to flush Tx.
++ * (Do the reset outside of interrupt context). */
++ adapter->tx_timeout_count++;
++ schedule_work(&adapter->reset_task);
++ /* return immediately since reset is imminent */
++ return;
++ }
++ }
++
++ /* Simple mode for Interrupt Throttle Rate (ITR) */
++ if (hw->mac_type >= e1000_82540 && adapter->itr_setting == 4) {
++ /*
++ * Symmetric Tx/Rx gets a reduced ITR=2000;
++ * Total asymmetrical Tx or Rx gets ITR=8000;
++ * everyone else is between 2000-8000.
++ */
++ u32 goc = (adapter->gotcl + adapter->gorcl) / 10000;
++ u32 dif = (adapter->gotcl > adapter->gorcl ?
++ adapter->gotcl - adapter->gorcl :
++ adapter->gorcl - adapter->gotcl) / 10000;
++ u32 itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
++
++ ew32(ITR, 1000000000 / (itr * 256));
++ }
++
++ /* Cause software interrupt to ensure rx ring is cleaned */
++ ew32(ICS, E1000_ICS_RXDMT0);
++
++ /* Force detection of hung controller every watchdog period */
++ adapter->detect_tx_hung = true;
++
++ /* Reset the timer */
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ mod_timer(&adapter->watchdog_timer,
++ round_jiffies(jiffies + 2 * HZ));
++}
++
++enum latency_range {
++ lowest_latency = 0,
++ low_latency = 1,
++ bulk_latency = 2,
++ latency_invalid = 255
++};
++
++/**
++ * e1000_update_itr - update the dynamic ITR value based on statistics
++ * @adapter: pointer to adapter
++ * @itr_setting: current adapter->itr
++ * @packets: the number of packets during this measurement interval
++ * @bytes: the number of bytes during this measurement interval
++ *
++ * Stores a new ITR value based on packets and byte
++ * counts during the last interrupt. The advantage of per interrupt
++ * computation is faster updates and more accurate ITR for the current
++ * traffic pattern. Constants in this function were computed
++ * based on theoretical maximum wire speed and thresholds were set based
++ * on testing data as well as attempting to minimize response time
++ * while increasing bulk throughput.
++ * this functionality is controlled by the InterruptThrottleRate module
++ * parameter (see e1000_param.c)
++ **/
++static unsigned int e1000_update_itr(struct e1000_adapter *adapter,
++ u16 itr_setting, int packets, int bytes)
++{
++ unsigned int retval = itr_setting;
++ struct e1000_hw *hw = &adapter->hw;
++
++ if (unlikely(hw->mac_type < e1000_82540))
++ goto update_itr_done;
++
++ if (packets == 0)
++ goto update_itr_done;
++
++ switch (itr_setting) {
++ case lowest_latency:
++ /* jumbo frames get bulk treatment*/
++ if (bytes/packets > 8000)
++ retval = bulk_latency;
++ else if ((packets < 5) && (bytes > 512))
++ retval = low_latency;
++ break;
++ case low_latency: /* 50 usec aka 20000 ints/s */
++ if (bytes > 10000) {
++ /* jumbo frames need bulk latency setting */
++ if (bytes/packets > 8000)
++ retval = bulk_latency;
++ else if ((packets < 10) || ((bytes/packets) > 1200))
++ retval = bulk_latency;
++ else if ((packets > 35))
++ retval = lowest_latency;
++ } else if (bytes/packets > 2000)
++ retval = bulk_latency;
++ else if (packets <= 2 && bytes < 512)
++ retval = lowest_latency;
++ break;
++ case bulk_latency: /* 250 usec aka 4000 ints/s */
++ if (bytes > 25000) {
++ if (packets > 35)
++ retval = low_latency;
++ } else if (bytes < 6000) {
++ retval = low_latency;
++ }
++ break;
++ }
++
++update_itr_done:
++ return retval;
++}
++
++static void e1000_set_itr(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ u16 current_itr;
++ u32 new_itr = adapter->itr;
++
++ if (unlikely(hw->mac_type < e1000_82540))
++ return;
++
++ /* for non-gigabit speeds, just fix the interrupt rate at 4000 */
++ if (unlikely(adapter->link_speed != SPEED_1000)) {
++ current_itr = 0;
++ new_itr = 4000;
++ goto set_itr_now;
++ }
++
++ adapter->tx_itr = e1000_update_itr(adapter,
++ adapter->tx_itr,
++ adapter->total_tx_packets,
++ adapter->total_tx_bytes);
++ /* conservative mode (itr 3) eliminates the lowest_latency setting */
++ if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency)
++ adapter->tx_itr = low_latency;
++
++ adapter->rx_itr = e1000_update_itr(adapter,
++ adapter->rx_itr,
++ adapter->total_rx_packets,
++ adapter->total_rx_bytes);
++ /* conservative mode (itr 3) eliminates the lowest_latency setting */
++ if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency)
++ adapter->rx_itr = low_latency;
++
++ current_itr = max(adapter->rx_itr, adapter->tx_itr);
++
++ switch (current_itr) {
++ /* counts and packets in update_itr are dependent on these numbers */
++ case lowest_latency:
++ new_itr = 70000;
++ break;
++ case low_latency:
++ new_itr = 20000; /* aka hwitr = ~200 */
++ break;
++ case bulk_latency:
++ new_itr = 4000;
++ break;
++ default:
++ break;
++ }
++
++set_itr_now:
++ if (new_itr != adapter->itr) {
++ /* this attempts to bias the interrupt rate towards Bulk
++ * by adding intermediate steps when interrupt rate is
++ * increasing */
++ new_itr = new_itr > adapter->itr ?
++ min(adapter->itr + (new_itr >> 2), new_itr) :
++ new_itr;
++ adapter->itr = new_itr;
++ ew32(ITR, 1000000000 / (new_itr * 256));
++ }
++}
++
++#define E1000_TX_FLAGS_CSUM 0x00000001
++#define E1000_TX_FLAGS_VLAN 0x00000002
++#define E1000_TX_FLAGS_TSO 0x00000004
++#define E1000_TX_FLAGS_IPV4 0x00000008
++#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000
++#define E1000_TX_FLAGS_VLAN_SHIFT 16
++
++static int e1000_tso(struct e1000_adapter *adapter,
++ struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
++{
++ struct e1000_context_desc *context_desc;
++ struct e1000_buffer *buffer_info;
++ unsigned int i;
++ u32 cmd_length = 0;
++ u16 ipcse = 0, tucse, mss;
++ u8 ipcss, ipcso, tucss, tucso, hdr_len;
++ int err;
++
++ if (skb_is_gso(skb)) {
++ if (skb_header_cloned(skb)) {
++ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
++ if (err)
++ return err;
++ }
++
++ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
++ mss = skb_shinfo(skb)->gso_size;
++ if (skb->protocol == htons(ETH_P_IP)) {
++ struct iphdr *iph = ip_hdr(skb);
++ iph->tot_len = 0;
++ iph->check = 0;
++ tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
++ iph->daddr, 0,
++ IPPROTO_TCP,
++ 0);
++ cmd_length = E1000_TXD_CMD_IP;
++ ipcse = skb_transport_offset(skb) - 1;
++ } else if (skb->protocol == htons(ETH_P_IPV6)) {
++ ipv6_hdr(skb)->payload_len = 0;
++ tcp_hdr(skb)->check =
++ ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
++ &ipv6_hdr(skb)->daddr,
++ 0, IPPROTO_TCP, 0);
++ ipcse = 0;
++ }
++ ipcss = skb_network_offset(skb);
++ ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data;
++ tucss = skb_transport_offset(skb);
++ tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data;
++ tucse = 0;
++
++ cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
++ E1000_TXD_CMD_TCP | (skb->len - (hdr_len)));
++
++ i = tx_ring->next_to_use;
++ context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
++ buffer_info = &tx_ring->buffer_info[i];
++
++ context_desc->lower_setup.ip_fields.ipcss = ipcss;
++ context_desc->lower_setup.ip_fields.ipcso = ipcso;
++ context_desc->lower_setup.ip_fields.ipcse = cpu_to_le16(ipcse);
++ context_desc->upper_setup.tcp_fields.tucss = tucss;
++ context_desc->upper_setup.tcp_fields.tucso = tucso;
++ context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse);
++ context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss);
++ context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
++ context_desc->cmd_and_length = cpu_to_le32(cmd_length);
++
++ buffer_info->time_stamp = jiffies;
++ buffer_info->next_to_watch = i;
++
++ if (++i == tx_ring->count) i = 0;
++ tx_ring->next_to_use = i;
++
++ return true;
++ }
++ return false;
++}
++
++static bool e1000_tx_csum(struct e1000_adapter *adapter,
++ struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
++{
++ struct e1000_context_desc *context_desc;
++ struct e1000_buffer *buffer_info;
++ unsigned int i;
++ u8 css;
++ u32 cmd_len = E1000_TXD_CMD_DEXT;
++
++ if (skb->ip_summed != CHECKSUM_PARTIAL)
++ return false;
++
++ switch (skb->protocol) {
++ case cpu_to_be16(ETH_P_IP):
++ if (ip_hdr(skb)->protocol == IPPROTO_TCP)
++ cmd_len |= E1000_TXD_CMD_TCP;
++ break;
++ case cpu_to_be16(ETH_P_IPV6):
++ /* XXX not handling all IPV6 headers */
++ if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
++ cmd_len |= E1000_TXD_CMD_TCP;
++ break;
++ default:
++ if (unlikely(net_ratelimit()))
++ e_warn("checksum_partial proto=%x!\n", skb->protocol);
++ break;
++ }
++
++ css = skb_transport_offset(skb);
++
++ i = tx_ring->next_to_use;
++ buffer_info = &tx_ring->buffer_info[i];
++ context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
++
++ context_desc->lower_setup.ip_config = 0;
++ context_desc->upper_setup.tcp_fields.tucss = css;
++ context_desc->upper_setup.tcp_fields.tucso =
++ css + skb->csum_offset;
++ context_desc->upper_setup.tcp_fields.tucse = 0;
++ context_desc->tcp_seg_setup.data = 0;
++ context_desc->cmd_and_length = cpu_to_le32(cmd_len);
++
++ buffer_info->time_stamp = jiffies;
++ buffer_info->next_to_watch = i;
++
++ if (unlikely(++i == tx_ring->count)) i = 0;
++ tx_ring->next_to_use = i;
++
++ return true;
++}
++
++#define E1000_MAX_TXD_PWR 12
++#define E1000_MAX_DATA_PER_TXD (1<<E1000_MAX_TXD_PWR)
++
++static int e1000_tx_map(struct e1000_adapter *adapter,
++ struct e1000_tx_ring *tx_ring,
++ struct sk_buff *skb, unsigned int first,
++ unsigned int max_per_txd, unsigned int nr_frags,
++ unsigned int mss)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ struct pci_dev *pdev = adapter->pdev;
++ struct e1000_buffer *buffer_info;
++ unsigned int len = skb_headlen(skb);
++ unsigned int offset = 0, size, count = 0, i;
++ unsigned int f;
++
++ i = tx_ring->next_to_use;
++
++ while (len) {
++ buffer_info = &tx_ring->buffer_info[i];
++ size = min(len, max_per_txd);
++ /* Workaround for Controller erratum --
++ * descriptor for non-tso packet in a linear SKB that follows a
++ * tso gets written back prematurely before the data is fully
++ * DMA'd to the controller */
++ if (!skb->data_len && tx_ring->last_tx_tso &&
++ !skb_is_gso(skb)) {
++ tx_ring->last_tx_tso = 0;
++ size -= 4;
++ }
++
++ /* Workaround for premature desc write-backs
++ * in TSO mode. Append 4-byte sentinel desc */
++ if (unlikely(mss && !nr_frags && size == len && size > 8))
++ size -= 4;
++ /* work-around for errata 10 and it applies
++ * to all controllers in PCI-X mode
++ * The fix is to make sure that the first descriptor of a
++ * packet is smaller than 2048 - 16 - 16 (or 2016) bytes
++ */
++ if (unlikely((hw->bus_type == e1000_bus_type_pcix) &&
++ (size > 2015) && count == 0))
++ size = 2015;
++
++ /* Workaround for potential 82544 hang in PCI-X. Avoid
++ * terminating buffers within evenly-aligned dwords. */
++ if (unlikely(adapter->pcix_82544 &&
++ !((unsigned long)(skb->data + offset + size - 1) & 4) &&
++ size > 4))
++ size -= 4;
++
++ buffer_info->length = size;
++ /* set time_stamp *before* dma to help avoid a possible race */
++ buffer_info->time_stamp = jiffies;
++ buffer_info->mapped_as_page = false;
++ buffer_info->dma = dma_map_single(&pdev->dev,
++ skb->data + offset,
++ size, DMA_TO_DEVICE);
++ if (dma_mapping_error(&pdev->dev, buffer_info->dma))
++ goto dma_error;
++ buffer_info->next_to_watch = i;
++
++ len -= size;
++ offset += size;
++ count++;
++ if (len) {
++ i++;
++ if (unlikely(i == tx_ring->count))
++ i = 0;
++ }
++ }
++
++ for (f = 0; f < nr_frags; f++) {
++ struct skb_frag_struct *frag;
++
++ frag = &skb_shinfo(skb)->frags[f];
++ len = frag->size;
++ offset = frag->page_offset;
++
++ while (len) {
++ i++;
++ if (unlikely(i == tx_ring->count))
++ i = 0;
++
++ buffer_info = &tx_ring->buffer_info[i];
++ size = min(len, max_per_txd);
++ /* Workaround for premature desc write-backs
++ * in TSO mode. Append 4-byte sentinel desc */
++ if (unlikely(mss && f == (nr_frags-1) && size == len && size > 8))
++ size -= 4;
++ /* Workaround for potential 82544 hang in PCI-X.
++ * Avoid terminating buffers within evenly-aligned
++ * dwords. */
++ if (unlikely(adapter->pcix_82544 &&
++ !((unsigned long)(page_to_phys(frag->page) + offset
++ + size - 1) & 4) &&
++ size > 4))
++ size -= 4;
++
++ buffer_info->length = size;
++ buffer_info->time_stamp = jiffies;
++ buffer_info->mapped_as_page = true;
++ buffer_info->dma = dma_map_page(&pdev->dev, frag->page,
++ offset, size,
++ DMA_TO_DEVICE);
++ if (dma_mapping_error(&pdev->dev, buffer_info->dma))
++ goto dma_error;
++ buffer_info->next_to_watch = i;
++
++ len -= size;
++ offset += size;
++ count++;
++ }
++ }
++
++ tx_ring->buffer_info[i].skb = skb;
++ tx_ring->buffer_info[first].next_to_watch = i;
++
++ return count;
++
++dma_error:
++ dev_err(&pdev->dev, "TX DMA map failed\n");
++ buffer_info->dma = 0;
++ if (count)
++ count--;
++
++ while (count--) {
++ if (i==0)
++ i += tx_ring->count;
++ i--;
++ buffer_info = &tx_ring->buffer_info[i];
++ e1000_unmap_and_free_tx_resource(adapter, buffer_info);
++ }
++
++ return 0;
++}
++
++static void e1000_tx_queue(struct e1000_adapter *adapter,
++ struct e1000_tx_ring *tx_ring, int tx_flags,
++ int count)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ struct e1000_tx_desc *tx_desc = NULL;
++ struct e1000_buffer *buffer_info;
++ u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
++ unsigned int i;
++
++ if (likely(tx_flags & E1000_TX_FLAGS_TSO)) {
++ txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
++ E1000_TXD_CMD_TSE;
++ txd_upper |= E1000_TXD_POPTS_TXSM << 8;
++
++ if (likely(tx_flags & E1000_TX_FLAGS_IPV4))
++ txd_upper |= E1000_TXD_POPTS_IXSM << 8;
++ }
++
++ if (likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
++ txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
++ txd_upper |= E1000_TXD_POPTS_TXSM << 8;
++ }
++
++ if (unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
++ txd_lower |= E1000_TXD_CMD_VLE;
++ txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
++ }
++
++ i = tx_ring->next_to_use;
++
++ while (count--) {
++ buffer_info = &tx_ring->buffer_info[i];
++ tx_desc = E1000_TX_DESC(*tx_ring, i);
++ tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
++ tx_desc->lower.data =
++ cpu_to_le32(txd_lower | buffer_info->length);
++ tx_desc->upper.data = cpu_to_le32(txd_upper);
++ if (unlikely(++i == tx_ring->count)) i = 0;
++ }
++
++ tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
++
++ /* Force memory writes to complete before letting h/w
++ * know there are new descriptors to fetch. (Only
++ * applicable for weak-ordered memory model archs,
++ * such as IA-64). */
++ wmb();
++
++ tx_ring->next_to_use = i;
++ writel(i, hw->hw_addr + tx_ring->tdt);
++ /* we need this if more than one processor can write to our tail
++ * at a time, it syncronizes IO on IA64/Altix systems */
++ mmiowb();
++}
++
++/**
++ * 82547 workaround to avoid controller hang in half-duplex environment.
++ * The workaround is to avoid queuing a large packet that would span
++ * the internal Tx FIFO ring boundary by notifying the stack to resend
++ * the packet at a later time. This gives the Tx FIFO an opportunity to
++ * flush all packets. When that occurs, we reset the Tx FIFO pointers
++ * to the beginning of the Tx FIFO.
++ **/
++
++#define E1000_FIFO_HDR 0x10
++#define E1000_82547_PAD_LEN 0x3E0
++
++static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
++ struct sk_buff *skb)
++{
++ u32 fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
++ u32 skb_fifo_len = skb->len + E1000_FIFO_HDR;
++
++ skb_fifo_len = ALIGN(skb_fifo_len, E1000_FIFO_HDR);
++
++ if (adapter->link_duplex != HALF_DUPLEX)
++ goto no_fifo_stall_required;
++
++ if (atomic_read(&adapter->tx_fifo_stall))
++ return 1;
++
++ if (skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) {
++ atomic_set(&adapter->tx_fifo_stall, 1);
++ return 1;
++ }
++
++no_fifo_stall_required:
++ adapter->tx_fifo_head += skb_fifo_len;
++ if (adapter->tx_fifo_head >= adapter->tx_fifo_size)
++ adapter->tx_fifo_head -= adapter->tx_fifo_size;
++ return 0;
++}
++
++static int __e1000_maybe_stop_tx(struct net_device *netdev, int size)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_tx_ring *tx_ring = adapter->tx_ring;
++
++ netif_stop_queue(netdev);
++ /* Herbert's original patch had:
++ * smp_mb__after_netif_stop_queue();
++ * but since that doesn't exist yet, just open code it. */
++ smp_mb();
++
++ /* We need to check again in a case another CPU has just
++ * made room available. */
++ if (likely(E1000_DESC_UNUSED(tx_ring) < size))
++ return -EBUSY;
++
++ /* A reprieve! */
++ netif_start_queue(netdev);
++ ++adapter->restart_queue;
++ return 0;
++}
++
++static int e1000_maybe_stop_tx(struct net_device *netdev,
++ struct e1000_tx_ring *tx_ring, int size)
++{
++ if (likely(E1000_DESC_UNUSED(tx_ring) >= size))
++ return 0;
++ return __e1000_maybe_stop_tx(netdev, size);
++}
++
++#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 )
++static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
++ struct net_device *netdev)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++ struct e1000_tx_ring *tx_ring;
++ unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
++ unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
++ unsigned int tx_flags = 0;
++ unsigned int len = skb_headlen(skb);
++ unsigned int nr_frags;
++ unsigned int mss;
++ int count = 0;
++ int tso;
++ unsigned int f;
++
++ /* This goes back to the question of how to logically map a tx queue
++ * to a flow. Right now, performance is impacted slightly negatively
++ * if using multiple tx queues. If the stack breaks away from a
++ * single qdisc implementation, we can look at this again. */
++ tx_ring = adapter->tx_ring;
++
++ if (unlikely(skb->len <= 0)) {
++ dev_kfree_skb_any(skb);
++ return NETDEV_TX_OK;
++ }
++
++ mss = skb_shinfo(skb)->gso_size;
++ /* The controller does a simple calculation to
++ * make sure there is enough room in the FIFO before
++ * initiating the DMA for each buffer. The calc is:
++ * 4 = ceil(buffer len/mss). To make sure we don't
++ * overrun the FIFO, adjust the max buffer len if mss
++ * drops. */
++ if (mss) {
++ u8 hdr_len;
++ max_per_txd = min(mss << 2, max_per_txd);
++ max_txd_pwr = fls(max_per_txd) - 1;
++
++ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
++ if (skb->data_len && hdr_len == len) {
++ switch (hw->mac_type) {
++ unsigned int pull_size;
++ case e1000_82544:
++ /* Make sure we have room to chop off 4 bytes,
++ * and that the end alignment will work out to
++ * this hardware's requirements
++ * NOTE: this is a TSO only workaround
++ * if end byte alignment not correct move us
++ * into the next dword */
++ if ((unsigned long)(skb_tail_pointer(skb) - 1) & 4)
++ break;
++ /* fall through */
++ pull_size = min((unsigned int)4, skb->data_len);
++ if (!__pskb_pull_tail(skb, pull_size)) {
++ e_err("__pskb_pull_tail failed.\n");
++ dev_kfree_skb_any(skb);
++ return NETDEV_TX_OK;
++ }
++ len = skb_headlen(skb);
++ break;
++ default:
++ /* do nothing */
++ break;
++ }
++ }
++ }
++
++ /* reserve a descriptor for the offload context */
++ if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL))
++ count++;
++ count++;
++
++ /* Controller Erratum workaround */
++ if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb))
++ count++;
++
++ count += TXD_USE_COUNT(len, max_txd_pwr);
++
++ if (adapter->pcix_82544)
++ count++;
++
++ /* work-around for errata 10 and it applies to all controllers
++ * in PCI-X mode, so add one more descriptor to the count
++ */
++ if (unlikely((hw->bus_type == e1000_bus_type_pcix) &&
++ (len > 2015)))
++ count++;
++
++ nr_frags = skb_shinfo(skb)->nr_frags;
++ for (f = 0; f < nr_frags; f++)
++ count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
++ max_txd_pwr);
++ if (adapter->pcix_82544)
++ count += nr_frags;
++
++ /* need: count + 2 desc gap to keep tail from touching
++ * head, otherwise try next time */
++ if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2)))
++ return NETDEV_TX_BUSY;
++
++ if (unlikely(hw->mac_type == e1000_82547)) {
++ if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
++ netif_stop_queue(netdev);
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ mod_timer(&adapter->tx_fifo_stall_timer,
++ jiffies + 1);
++ return NETDEV_TX_BUSY;
++ }
++ }
++
++ if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
++ tx_flags |= E1000_TX_FLAGS_VLAN;
++ tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
++ }
++
++ first = tx_ring->next_to_use;
++
++ tso = e1000_tso(adapter, tx_ring, skb);
++ if (tso < 0) {
++ dev_kfree_skb_any(skb);
++ return NETDEV_TX_OK;
++ }
++
++ if (likely(tso)) {
++ if (likely(hw->mac_type != e1000_82544))
++ tx_ring->last_tx_tso = 1;
++ tx_flags |= E1000_TX_FLAGS_TSO;
++ } else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
++ tx_flags |= E1000_TX_FLAGS_CSUM;
++
++ if (likely(skb->protocol == htons(ETH_P_IP)))
++ tx_flags |= E1000_TX_FLAGS_IPV4;
++
++ count = e1000_tx_map(adapter, tx_ring, skb, first, max_per_txd,
++ nr_frags, mss);
++
++ if (count) {
++ e1000_tx_queue(adapter, tx_ring, tx_flags, count);
++ /* Make sure there is space in the ring for the next send. */
++ e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2);
++
++ } else {
++ dev_kfree_skb_any(skb);
++ tx_ring->buffer_info[first].time_stamp = 0;
++ tx_ring->next_to_use = first;
++ }
++
++ return NETDEV_TX_OK;
++}
++
++/**
++ * e1000_tx_timeout - Respond to a Tx Hang
++ * @netdev: network interface device structure
++ **/
++
++static void e1000_tx_timeout(struct net_device *netdev)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++
++ /* Do the reset outside of interrupt context */
++ adapter->tx_timeout_count++;
++ schedule_work(&adapter->reset_task);
++}
++
++static void e1000_reset_task(struct work_struct *work)
++{
++ struct e1000_adapter *adapter =
++ container_of(work, struct e1000_adapter, reset_task);
++
++ e1000_reinit_locked(adapter);
++}
++
++/**
++ * e1000_get_stats - Get System Network Statistics
++ * @netdev: network interface device structure
++ *
++ * Returns the address of the device statistics structure.
++ * The statistics are actually updated from the timer callback.
++ **/
++
++static struct net_device_stats *e1000_get_stats(struct net_device *netdev)
++{
++ /* only return the current stats */
++ return &netdev->stats;
++}
++
++/**
++ * e1000_change_mtu - Change the Maximum Transfer Unit
++ * @netdev: network interface device structure
++ * @new_mtu: new value for maximum frame size
++ *
++ * Returns 0 on success, negative on failure
++ **/
++
++static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++ int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
++
++ if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
++ (max_frame > MAX_JUMBO_FRAME_SIZE)) {
++ e_err("Invalid MTU setting\n");
++ return -EINVAL;
++ }
++
++ /* Adapter-specific max frame size limits. */
++ switch (hw->mac_type) {
++ case e1000_undefined ... e1000_82542_rev2_1:
++ if (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
++ e_err("Jumbo Frames not supported.\n");
++ return -EINVAL;
++ }
++ break;
++ default:
++ /* Capable of supporting up to MAX_JUMBO_FRAME_SIZE limit. */
++ break;
++ }
++
++ while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
++ msleep(1);
++ /* e1000_down has a dependency on max_frame_size */
++ hw->max_frame_size = max_frame;
++ if (netif_running(netdev))
++ e1000_down(adapter);
++
++ /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
++ * means we reserve 2 more, this pushes us to allocate from the next
++ * larger slab size.
++ * i.e. RXBUFFER_2048 --> size-4096 slab
++ * however with the new *_jumbo_rx* routines, jumbo receives will use
++ * fragmented skbs */
++
++ if (max_frame <= E1000_RXBUFFER_2048)
++ adapter->rx_buffer_len = E1000_RXBUFFER_2048;
++ else
++#if (PAGE_SIZE >= E1000_RXBUFFER_16384)
++ adapter->rx_buffer_len = E1000_RXBUFFER_16384;
++#elif (PAGE_SIZE >= E1000_RXBUFFER_4096)
++ adapter->rx_buffer_len = PAGE_SIZE;
++#endif
++
++ /* adjust allocation if LPE protects us, and we aren't using SBP */
++ if (!hw->tbi_compatibility_on &&
++ ((max_frame == (ETH_FRAME_LEN + ETH_FCS_LEN)) ||
++ (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
++ adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
++
++ pr_info("%s changing MTU from %d to %d\n",
++ netdev->name, netdev->mtu, new_mtu);
++ netdev->mtu = new_mtu;
++
++ if (netif_running(netdev))
++ e1000_up(adapter);
++ else
++ e1000_reset(adapter);
++
++ clear_bit(__E1000_RESETTING, &adapter->flags);
++
++ return 0;
++}
++
++/**
++ * e1000_update_stats - Update the board statistics counters
++ * @adapter: board private structure
++ **/
++
++void e1000_update_stats(struct e1000_adapter *adapter)
++{
++ struct net_device *netdev = adapter->netdev;
++ struct e1000_hw *hw = &adapter->hw;
++ struct pci_dev *pdev = adapter->pdev;
++ unsigned long flags;
++ u16 phy_tmp;
++
++#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
++
++ /*
++ * Prevent stats update while adapter is being reset, or if the pci
++ * connection is down.
++ */
++ if (adapter->link_speed == 0)
++ return;
++ if (pci_channel_offline(pdev))
++ return;
++
++ spin_lock_irqsave(&adapter->stats_lock, flags);
++
++ /* these counters are modified from e1000_tbi_adjust_stats,
++ * called from the interrupt context, so they must only
++ * be written while holding adapter->stats_lock
++ */
++
++ adapter->stats.crcerrs += er32(CRCERRS);
++ adapter->stats.gprc += er32(GPRC);
++ adapter->stats.gorcl += er32(GORCL);
++ adapter->stats.gorch += er32(GORCH);
++ adapter->stats.bprc += er32(BPRC);
++ adapter->stats.mprc += er32(MPRC);
++ adapter->stats.roc += er32(ROC);
++
++ adapter->stats.prc64 += er32(PRC64);
++ adapter->stats.prc127 += er32(PRC127);
++ adapter->stats.prc255 += er32(PRC255);
++ adapter->stats.prc511 += er32(PRC511);
++ adapter->stats.prc1023 += er32(PRC1023);
++ adapter->stats.prc1522 += er32(PRC1522);
++
++ adapter->stats.symerrs += er32(SYMERRS);
++ adapter->stats.mpc += er32(MPC);
++ adapter->stats.scc += er32(SCC);
++ adapter->stats.ecol += er32(ECOL);
++ adapter->stats.mcc += er32(MCC);
++ adapter->stats.latecol += er32(LATECOL);
++ adapter->stats.dc += er32(DC);
++ adapter->stats.sec += er32(SEC);
++ adapter->stats.rlec += er32(RLEC);
++ adapter->stats.xonrxc += er32(XONRXC);
++ adapter->stats.xontxc += er32(XONTXC);
++ adapter->stats.xoffrxc += er32(XOFFRXC);
++ adapter->stats.xofftxc += er32(XOFFTXC);
++ adapter->stats.fcruc += er32(FCRUC);
++ adapter->stats.gptc += er32(GPTC);
++ adapter->stats.gotcl += er32(GOTCL);
++ adapter->stats.gotch += er32(GOTCH);
++ adapter->stats.rnbc += er32(RNBC);
++ adapter->stats.ruc += er32(RUC);
++ adapter->stats.rfc += er32(RFC);
++ adapter->stats.rjc += er32(RJC);
++ adapter->stats.torl += er32(TORL);
++ adapter->stats.torh += er32(TORH);
++ adapter->stats.totl += er32(TOTL);
++ adapter->stats.toth += er32(TOTH);
++ adapter->stats.tpr += er32(TPR);
++
++ adapter->stats.ptc64 += er32(PTC64);
++ adapter->stats.ptc127 += er32(PTC127);
++ adapter->stats.ptc255 += er32(PTC255);
++ adapter->stats.ptc511 += er32(PTC511);
++ adapter->stats.ptc1023 += er32(PTC1023);
++ adapter->stats.ptc1522 += er32(PTC1522);
++
++ adapter->stats.mptc += er32(MPTC);
++ adapter->stats.bptc += er32(BPTC);
++
++ /* used for adaptive IFS */
++
++ hw->tx_packet_delta = er32(TPT);
++ adapter->stats.tpt += hw->tx_packet_delta;
++ hw->collision_delta = er32(COLC);
++ adapter->stats.colc += hw->collision_delta;
++
++ if (hw->mac_type >= e1000_82543) {
++ adapter->stats.algnerrc += er32(ALGNERRC);
++ adapter->stats.rxerrc += er32(RXERRC);
++ adapter->stats.tncrs += er32(TNCRS);
++ adapter->stats.cexterr += er32(CEXTERR);
++ adapter->stats.tsctc += er32(TSCTC);
++ adapter->stats.tsctfc += er32(TSCTFC);
++ }
++
++ /* Fill out the OS statistics structure */
++ netdev->stats.multicast = adapter->stats.mprc;
++ netdev->stats.collisions = adapter->stats.colc;
++
++ /* Rx Errors */
++
++ /* RLEC on some newer hardware can be incorrect so build
++ * our own version based on RUC and ROC */
++ netdev->stats.rx_errors = adapter->stats.rxerrc +
++ adapter->stats.crcerrs + adapter->stats.algnerrc +
++ adapter->stats.ruc + adapter->stats.roc +
++ adapter->stats.cexterr;
++ adapter->stats.rlerrc = adapter->stats.ruc + adapter->stats.roc;
++ netdev->stats.rx_length_errors = adapter->stats.rlerrc;
++ netdev->stats.rx_crc_errors = adapter->stats.crcerrs;
++ netdev->stats.rx_frame_errors = adapter->stats.algnerrc;
++ netdev->stats.rx_missed_errors = adapter->stats.mpc;
++
++ /* Tx Errors */
++ adapter->stats.txerrc = adapter->stats.ecol + adapter->stats.latecol;
++ netdev->stats.tx_errors = adapter->stats.txerrc;
++ netdev->stats.tx_aborted_errors = adapter->stats.ecol;
++ netdev->stats.tx_window_errors = adapter->stats.latecol;
++ netdev->stats.tx_carrier_errors = adapter->stats.tncrs;
++ if (hw->bad_tx_carr_stats_fd &&
++ adapter->link_duplex == FULL_DUPLEX) {
++ netdev->stats.tx_carrier_errors = 0;
++ adapter->stats.tncrs = 0;
++ }
++
++ /* Tx Dropped needs to be maintained elsewhere */
++
++ /* Phy Stats */
++ if (hw->media_type == e1000_media_type_copper) {
++ if ((adapter->link_speed == SPEED_1000) &&
++ (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) {
++ phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
++ adapter->phy_stats.idle_errors += phy_tmp;
++ }
++
++ if ((hw->mac_type <= e1000_82546) &&
++ (hw->phy_type == e1000_phy_m88) &&
++ !e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
++ adapter->phy_stats.receive_errors += phy_tmp;
++ }
++
++ /* Management Stats */
++ if (hw->has_smbus) {
++ adapter->stats.mgptc += er32(MGTPTC);
++ adapter->stats.mgprc += er32(MGTPRC);
++ adapter->stats.mgpdc += er32(MGTPDC);
++ }
++
++ spin_unlock_irqrestore(&adapter->stats_lock, flags);
++}
++
++/**
++ * e1000_intr - Interrupt Handler
++ * @irq: interrupt number
++ * @data: pointer to a network interface device structure
++ **/
++
++static irqreturn_t e1000_intr(int irq, void *data)
++{
++ struct net_device *netdev = data;
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++ u32 icr = er32(ICR);
++
++ if (unlikely((!icr) || test_bit(__E1000_DOWN, &adapter->flags)))
++ return IRQ_NONE; /* Not our interrupt */
++
++ if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
++ hw->get_link_status = 1;
++ /* guard against interrupt when we're going down */
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ mod_timer(&adapter->watchdog_timer, jiffies + 1);
++ }
++
++ /* disable interrupts, without the synchronize_irq bit */
++ ew32(IMC, ~0);
++ E1000_WRITE_FLUSH();
++
++ if (likely(napi_schedule_prep(&adapter->napi))) {
++ adapter->total_tx_bytes = 0;
++ adapter->total_tx_packets = 0;
++ adapter->total_rx_bytes = 0;
++ adapter->total_rx_packets = 0;
++ __napi_schedule(&adapter->napi);
++ } else {
++ /* this really should not happen! if it does it is basically a
++ * bug, but not a hard error, so enable ints and continue */
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ e1000_irq_enable(adapter);
++ }
++
++ return IRQ_HANDLED;
++}
++
++/**
++ * e1000_clean - NAPI Rx polling callback
++ * @adapter: board private structure
++ **/
++static int e1000_clean(struct napi_struct *napi, int budget)
++{
++ struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, napi);
++ int tx_clean_complete = 0, work_done = 0;
++
++ tx_clean_complete = e1000_clean_tx_irq(adapter, &adapter->tx_ring[0]);
++
++ adapter->clean_rx(adapter, &adapter->rx_ring[0], &work_done, budget);
++
++ if (!tx_clean_complete)
++ work_done = budget;
++
++ /* If budget not fully consumed, exit the polling mode */
++ if (work_done < budget) {
++ if (likely(adapter->itr_setting & 3))
++ e1000_set_itr(adapter);
++ napi_complete(napi);
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ e1000_irq_enable(adapter);
++ }
++
++ return work_done;
++}
++
++/**
++ * e1000_clean_tx_irq - Reclaim resources after transmit completes
++ * @adapter: board private structure
++ **/
++static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
++ struct e1000_tx_ring *tx_ring)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ struct e1000_tx_desc *tx_desc, *eop_desc;
++ struct e1000_buffer *buffer_info;
++ unsigned int i, eop;
++ unsigned int count = 0;
++ unsigned int total_tx_bytes=0, total_tx_packets=0;
++
++ i = tx_ring->next_to_clean;
++ eop = tx_ring->buffer_info[i].next_to_watch;
++ eop_desc = E1000_TX_DESC(*tx_ring, eop);
++
++ while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
++ (count < tx_ring->count)) {
++ bool cleaned = false;
++ rmb(); /* read buffer_info after eop_desc */
++ for ( ; !cleaned; count++) {
++ tx_desc = E1000_TX_DESC(*tx_ring, i);
++ buffer_info = &tx_ring->buffer_info[i];
++ cleaned = (i == eop);
++
++ if (cleaned) {
++ struct sk_buff *skb = buffer_info->skb;
++ unsigned int segs, bytecount;
++ segs = skb_shinfo(skb)->gso_segs ?: 1;
++ /* multiply data chunks by size of headers */
++ bytecount = ((segs - 1) * skb_headlen(skb)) +
++ skb->len;
++ total_tx_packets += segs;
++ total_tx_bytes += bytecount;
++ }
++ e1000_unmap_and_free_tx_resource(adapter, buffer_info);
++ tx_desc->upper.data = 0;
++
++ if (unlikely(++i == tx_ring->count)) i = 0;
++ }
++
++ eop = tx_ring->buffer_info[i].next_to_watch;
++ eop_desc = E1000_TX_DESC(*tx_ring, eop);
++ }
++
++ tx_ring->next_to_clean = i;
++
++#define TX_WAKE_THRESHOLD 32
++ if (unlikely(count && netif_carrier_ok(netdev) &&
++ E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) {
++ /* Make sure that anybody stopping the queue after this
++ * sees the new next_to_clean.
++ */
++ smp_mb();
++
++ if (netif_queue_stopped(netdev) &&
++ !(test_bit(__E1000_DOWN, &adapter->flags))) {
++ netif_wake_queue(netdev);
++ ++adapter->restart_queue;
++ }
++ }
++
++ if (adapter->detect_tx_hung) {
++ /* Detect a transmit hang in hardware, this serializes the
++ * check with the clearing of time_stamp and movement of i */
++ adapter->detect_tx_hung = false;
++ if (tx_ring->buffer_info[eop].time_stamp &&
++ time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
++ (adapter->tx_timeout_factor * HZ)) &&
++ !(er32(STATUS) & E1000_STATUS_TXOFF)) {
++
++ /* detected Tx unit hang */
++ e_err("Detected Tx Unit Hang\n"
++ " Tx Queue <%lu>\n"
++ " TDH <%x>\n"
++ " TDT <%x>\n"
++ " next_to_use <%x>\n"
++ " next_to_clean <%x>\n"
++ "buffer_info[next_to_clean]\n"
++ " time_stamp <%lx>\n"
++ " next_to_watch <%x>\n"
++ " jiffies <%lx>\n"
++ " next_to_watch.status <%x>\n",
++ (unsigned long)((tx_ring - adapter->tx_ring) /
++ sizeof(struct e1000_tx_ring)),
++ readl(hw->hw_addr + tx_ring->tdh),
++ readl(hw->hw_addr + tx_ring->tdt),
++ tx_ring->next_to_use,
++ tx_ring->next_to_clean,
++ tx_ring->buffer_info[eop].time_stamp,
++ eop,
++ jiffies,
++ eop_desc->upper.fields.status);
++ netif_stop_queue(netdev);
++ }
++ }
++ adapter->total_tx_bytes += total_tx_bytes;
++ adapter->total_tx_packets += total_tx_packets;
++ netdev->stats.tx_bytes += total_tx_bytes;
++ netdev->stats.tx_packets += total_tx_packets;
++ return (count < tx_ring->count);
++}
++
++/**
++ * e1000_rx_checksum - Receive Checksum Offload for 82543
++ * @adapter: board private structure
++ * @status_err: receive descriptor status and error fields
++ * @csum: receive descriptor csum field
++ * @sk_buff: socket buffer with received data
++ **/
++
++static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err,
++ u32 csum, struct sk_buff *skb)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ u16 status = (u16)status_err;
++ u8 errors = (u8)(status_err >> 24);
++ skb->ip_summed = CHECKSUM_NONE;
++
++ /* 82543 or newer only */
++ if (unlikely(hw->mac_type < e1000_82543)) return;
++ /* Ignore Checksum bit is set */
++ if (unlikely(status & E1000_RXD_STAT_IXSM)) return;
++ /* TCP/UDP checksum error bit is set */
++ if (unlikely(errors & E1000_RXD_ERR_TCPE)) {
++ /* let the stack verify checksum errors */
++ adapter->hw_csum_err++;
++ return;
++ }
++ /* TCP/UDP Checksum has not been calculated */
++ if (!(status & E1000_RXD_STAT_TCPCS))
++ return;
++
++ /* It must be a TCP or UDP packet with a valid checksum */
++ if (likely(status & E1000_RXD_STAT_TCPCS)) {
++ /* TCP checksum is good */
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ }
++ adapter->hw_csum_good++;
++}
++
++/**
++ * e1000_consume_page - helper function
++ **/
++static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb,
++ u16 length)
++{
++ bi->page = NULL;
++ skb->len += length;
++ skb->data_len += length;
++ skb->truesize += length;
++}
++
++/**
++ * e1000_receive_skb - helper function to handle rx indications
++ * @adapter: board private structure
++ * @status: descriptor status field as written by hardware
++ * @vlan: descriptor vlan field as written by hardware (no le/be conversion)
++ * @skb: pointer to sk_buff to be indicated to stack
++ */
++static void e1000_receive_skb(struct e1000_adapter *adapter, u8 status,
++ __le16 vlan, struct sk_buff *skb)
++{
++ if (unlikely(adapter->vlgrp && (status & E1000_RXD_STAT_VP))) {
++ vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
++ le16_to_cpu(vlan) &
++ E1000_RXD_SPC_VLAN_MASK);
++ } else {
++ netif_receive_skb(skb);
++ }
++}
++
++/**
++ * e1000_clean_jumbo_rx_irq - Send received data up the network stack; legacy
++ * @adapter: board private structure
++ * @rx_ring: ring to clean
++ * @work_done: amount of napi work completed this call
++ * @work_to_do: max amount of work allowed for this call to do
++ *
++ * the return value indicates whether actual cleaning was done, there
++ * is no guarantee that everything was cleaned
++ */
++static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring,
++ int *work_done, int work_to_do)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ struct pci_dev *pdev = adapter->pdev;
++ struct e1000_rx_desc *rx_desc, *next_rxd;
++ struct e1000_buffer *buffer_info, *next_buffer;
++ unsigned long irq_flags;
++ u32 length;
++ unsigned int i;
++ int cleaned_count = 0;
++ bool cleaned = false;
++ unsigned int total_rx_bytes=0, total_rx_packets=0;
++
++ i = rx_ring->next_to_clean;
++ rx_desc = E1000_RX_DESC(*rx_ring, i);
++ buffer_info = &rx_ring->buffer_info[i];
++
++ while (rx_desc->status & E1000_RXD_STAT_DD) {
++ struct sk_buff *skb;
++ u8 status;
++
++ if (*work_done >= work_to_do)
++ break;
++ (*work_done)++;
++ rmb(); /* read descriptor and rx_buffer_info after status DD */
++
++ status = rx_desc->status;
++ skb = buffer_info->skb;
++ buffer_info->skb = NULL;
++
++ if (++i == rx_ring->count) i = 0;
++ next_rxd = E1000_RX_DESC(*rx_ring, i);
++ prefetch(next_rxd);
++
++ next_buffer = &rx_ring->buffer_info[i];
++
++ cleaned = true;
++ cleaned_count++;
++ dma_unmap_page(&pdev->dev, buffer_info->dma,
++ buffer_info->length, DMA_FROM_DEVICE);
++ buffer_info->dma = 0;
++
++ length = le16_to_cpu(rx_desc->length);
++
++ /* errors is only valid for DD + EOP descriptors */
++ if (unlikely((status & E1000_RXD_STAT_EOP) &&
++ (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK))) {
++ u8 last_byte = *(skb->data + length - 1);
++ if (TBI_ACCEPT(hw, status, rx_desc->errors, length,
++ last_byte)) {
++ spin_lock_irqsave(&adapter->stats_lock,
++ irq_flags);
++ e1000_tbi_adjust_stats(hw, &adapter->stats,
++ length, skb->data);
++ spin_unlock_irqrestore(&adapter->stats_lock,
++ irq_flags);
++ length--;
++ } else {
++ /* recycle both page and skb */
++ buffer_info->skb = skb;
++ /* an error means any chain goes out the window
++ * too */
++ if (rx_ring->rx_skb_top)
++ dev_kfree_skb(rx_ring->rx_skb_top);
++ rx_ring->rx_skb_top = NULL;
++ goto next_desc;
++ }
++ }
++
++#define rxtop rx_ring->rx_skb_top
++ if (!(status & E1000_RXD_STAT_EOP)) {
++ /* this descriptor is only the beginning (or middle) */
++ if (!rxtop) {
++ /* this is the beginning of a chain */
++ rxtop = skb;
++ skb_fill_page_desc(rxtop, 0, buffer_info->page,
++ 0, length);
++ } else {
++ /* this is the middle of a chain */
++ skb_fill_page_desc(rxtop,
++ skb_shinfo(rxtop)->nr_frags,
++ buffer_info->page, 0, length);
++ /* re-use the skb, only consumed the page */
++ buffer_info->skb = skb;
++ }
++ e1000_consume_page(buffer_info, rxtop, length);
++ goto next_desc;
++ } else {
++ if (rxtop) {
++ /* end of the chain */
++ skb_fill_page_desc(rxtop,
++ skb_shinfo(rxtop)->nr_frags,
++ buffer_info->page, 0, length);
++ /* re-use the current skb, we only consumed the
++ * page */
++ buffer_info->skb = skb;
++ skb = rxtop;
++ rxtop = NULL;
++ e1000_consume_page(buffer_info, skb, length);
++ } else {
++ /* no chain, got EOP, this buf is the packet
++ * copybreak to save the put_page/alloc_page */
++ if (length <= copybreak &&
++ skb_tailroom(skb) >= length) {
++ u8 *vaddr;
++ vaddr = kmap_atomic(buffer_info->page,
++ KM_SKB_DATA_SOFTIRQ);
++ memcpy(skb_tail_pointer(skb), vaddr, length);
++ kunmap_atomic(vaddr,
++ KM_SKB_DATA_SOFTIRQ);
++ /* re-use the page, so don't erase
++ * buffer_info->page */
++ skb_put(skb, length);
++ } else {
++ skb_fill_page_desc(skb, 0,
++ buffer_info->page, 0,
++ length);
++ e1000_consume_page(buffer_info, skb,
++ length);
++ }
++ }
++ }
++
++ /* Receive Checksum Offload XXX recompute due to CRC strip? */
++ e1000_rx_checksum(adapter,
++ (u32)(status) |
++ ((u32)(rx_desc->errors) << 24),
++ le16_to_cpu(rx_desc->csum), skb);
++
++ pskb_trim(skb, skb->len - 4);
++
++ /* probably a little skewed due to removing CRC */
++ total_rx_bytes += skb->len;
++ total_rx_packets++;
++
++ /* eth type trans needs skb->data to point to something */
++ if (!pskb_may_pull(skb, ETH_HLEN)) {
++ e_err("pskb_may_pull failed.\n");
++ dev_kfree_skb(skb);
++ goto next_desc;
++ }
++
++ skb->protocol = eth_type_trans(skb, netdev);
++
++ e1000_receive_skb(adapter, status, rx_desc->special, skb);
++
++next_desc:
++ rx_desc->status = 0;
++
++ /* return some buffers to hardware, one at a time is too slow */
++ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
++ cleaned_count = 0;
++ }
++
++ /* use prefetched values */
++ rx_desc = next_rxd;
++ buffer_info = next_buffer;
++ }
++ rx_ring->next_to_clean = i;
++
++ cleaned_count = E1000_DESC_UNUSED(rx_ring);
++ if (cleaned_count)
++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
++
++ adapter->total_rx_packets += total_rx_packets;
++ adapter->total_rx_bytes += total_rx_bytes;
++ netdev->stats.rx_bytes += total_rx_bytes;
++ netdev->stats.rx_packets += total_rx_packets;
++ return cleaned;
++}
++
++/*
++ * this should improve performance for small packets with large amounts
++ * of reassembly being done in the stack
++ */
++static void e1000_check_copybreak(struct net_device *netdev,
++ struct e1000_buffer *buffer_info,
++ u32 length, struct sk_buff **skb)
++{
++ struct sk_buff *new_skb;
++
++ if (length > copybreak)
++ return;
++
++ new_skb = netdev_alloc_skb_ip_align(netdev, length);
++ if (!new_skb)
++ return;
++
++ skb_copy_to_linear_data_offset(new_skb, -NET_IP_ALIGN,
++ (*skb)->data - NET_IP_ALIGN,
++ length + NET_IP_ALIGN);
++ /* save the skb in buffer_info as good */
++ buffer_info->skb = *skb;
++ *skb = new_skb;
++}
++
++/**
++ * e1000_clean_rx_irq - Send received data up the network stack; legacy
++ * @adapter: board private structure
++ * @rx_ring: ring to clean
++ * @work_done: amount of napi work completed this call
++ * @work_to_do: max amount of work allowed for this call to do
++ */
++static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring,
++ int *work_done, int work_to_do)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ struct pci_dev *pdev = adapter->pdev;
++ struct e1000_rx_desc *rx_desc, *next_rxd;
++ struct e1000_buffer *buffer_info, *next_buffer;
++ unsigned long flags;
++ u32 length;
++ unsigned int i;
++ int cleaned_count = 0;
++ bool cleaned = false;
++ unsigned int total_rx_bytes=0, total_rx_packets=0;
++
++ i = rx_ring->next_to_clean;
++ rx_desc = E1000_RX_DESC(*rx_ring, i);
++ buffer_info = &rx_ring->buffer_info[i];
++
++ while (rx_desc->status & E1000_RXD_STAT_DD) {
++ struct sk_buff *skb;
++ u8 status;
++
++ if (*work_done >= work_to_do)
++ break;
++ (*work_done)++;
++ rmb(); /* read descriptor and rx_buffer_info after status DD */
++
++ status = rx_desc->status;
++ skb = buffer_info->skb;
++ buffer_info->skb = NULL;
++
++ prefetch(skb->data - NET_IP_ALIGN);
++
++ if (++i == rx_ring->count) i = 0;
++ next_rxd = E1000_RX_DESC(*rx_ring, i);
++ prefetch(next_rxd);
++
++ next_buffer = &rx_ring->buffer_info[i];
++
++ cleaned = true;
++ cleaned_count++;
++ dma_unmap_single(&pdev->dev, buffer_info->dma,
++ buffer_info->length, DMA_FROM_DEVICE);
++ buffer_info->dma = 0;
++
++ length = le16_to_cpu(rx_desc->length);
++ /* !EOP means multiple descriptors were used to store a single
++ * packet, if thats the case we need to toss it. In fact, we
++ * to toss every packet with the EOP bit clear and the next
++ * frame that _does_ have the EOP bit set, as it is by
++ * definition only a frame fragment
++ */
++ if (unlikely(!(status & E1000_RXD_STAT_EOP)))
++ adapter->discarding = true;
++
++ if (adapter->discarding) {
++ /* All receives must fit into a single buffer */
++ e_info("Receive packet consumed multiple buffers\n");
++ /* recycle */
++ buffer_info->skb = skb;
++ if (status & E1000_RXD_STAT_EOP)
++ adapter->discarding = false;
++ goto next_desc;
++ }
++
++ if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
++ u8 last_byte = *(skb->data + length - 1);
++ if (TBI_ACCEPT(hw, status, rx_desc->errors, length,
++ last_byte)) {
++ spin_lock_irqsave(&adapter->stats_lock, flags);
++ e1000_tbi_adjust_stats(hw, &adapter->stats,
++ length, skb->data);
++ spin_unlock_irqrestore(&adapter->stats_lock,
++ flags);
++ length--;
++ } else {
++ /* recycle */
++ buffer_info->skb = skb;
++ goto next_desc;
++ }
++ }
++
++ /* adjust length to remove Ethernet CRC, this must be
++ * done after the TBI_ACCEPT workaround above */
++ length -= 4;
++
++ /* probably a little skewed due to removing CRC */
++ total_rx_bytes += length;
++ total_rx_packets++;
++
++ e1000_check_copybreak(netdev, buffer_info, length, &skb);
++
++ skb_put(skb, length);
++
++ /* Receive Checksum Offload */
++ e1000_rx_checksum(adapter,
++ (u32)(status) |
++ ((u32)(rx_desc->errors) << 24),
++ le16_to_cpu(rx_desc->csum), skb);
++
++ skb->protocol = eth_type_trans(skb, netdev);
++
++ e1000_receive_skb(adapter, status, rx_desc->special, skb);
++
++next_desc:
++ rx_desc->status = 0;
++
++ /* return some buffers to hardware, one at a time is too slow */
++ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
++ cleaned_count = 0;
++ }
++
++ /* use prefetched values */
++ rx_desc = next_rxd;
++ buffer_info = next_buffer;
++ }
++ rx_ring->next_to_clean = i;
++
++ cleaned_count = E1000_DESC_UNUSED(rx_ring);
++ if (cleaned_count)
++ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
++
++ adapter->total_rx_packets += total_rx_packets;
++ adapter->total_rx_bytes += total_rx_bytes;
++ netdev->stats.rx_bytes += total_rx_bytes;
++ netdev->stats.rx_packets += total_rx_packets;
++ return cleaned;
++}
++
++/**
++ * e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers
++ * @adapter: address of board private structure
++ * @rx_ring: pointer to receive ring structure
++ * @cleaned_count: number of buffers to allocate this pass
++ **/
++
++static void
++e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring, int cleaned_count)
++{
++ struct net_device *netdev = adapter->netdev;
++ struct pci_dev *pdev = adapter->pdev;
++ struct e1000_rx_desc *rx_desc;
++ struct e1000_buffer *buffer_info;
++ struct sk_buff *skb;
++ unsigned int i;
++ unsigned int bufsz = 256 - 16 /*for skb_reserve */ ;
++
++ i = rx_ring->next_to_use;
++ buffer_info = &rx_ring->buffer_info[i];
++
++ while (cleaned_count--) {
++ skb = buffer_info->skb;
++ if (skb) {
++ skb_trim(skb, 0);
++ goto check_page;
++ }
++
++ skb = netdev_alloc_skb_ip_align(netdev, bufsz);
++ if (unlikely(!skb)) {
++ /* Better luck next round */
++ adapter->alloc_rx_buff_failed++;
++ break;
++ }
++
++ /* Fix for errata 23, can't cross 64kB boundary */
++ if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
++ struct sk_buff *oldskb = skb;
++ e_err("skb align check failed: %u bytes at %p\n",
++ bufsz, skb->data);
++ /* Try again, without freeing the previous */
++ skb = netdev_alloc_skb_ip_align(netdev, bufsz);
++ /* Failed allocation, critical failure */
++ if (!skb) {
++ dev_kfree_skb(oldskb);
++ adapter->alloc_rx_buff_failed++;
++ break;
++ }
++
++ if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
++ /* give up */
++ dev_kfree_skb(skb);
++ dev_kfree_skb(oldskb);
++ break; /* while (cleaned_count--) */
++ }
++
++ /* Use new allocation */
++ dev_kfree_skb(oldskb);
++ }
++ buffer_info->skb = skb;
++ buffer_info->length = adapter->rx_buffer_len;
++check_page:
++ /* allocate a new page if necessary */
++ if (!buffer_info->page) {
++ buffer_info->page = alloc_page(GFP_ATOMIC);
++ if (unlikely(!buffer_info->page)) {
++ adapter->alloc_rx_buff_failed++;
++ break;
++ }
++ }
++
++ if (!buffer_info->dma) {
++ buffer_info->dma = dma_map_page(&pdev->dev,
++ buffer_info->page, 0,
++ buffer_info->length,
++ DMA_FROM_DEVICE);
++ if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
++ put_page(buffer_info->page);
++ dev_kfree_skb(skb);
++ buffer_info->page = NULL;
++ buffer_info->skb = NULL;
++ buffer_info->dma = 0;
++ adapter->alloc_rx_buff_failed++;
++ break; /* while !buffer_info->skb */
++ }
++ }
++
++ rx_desc = E1000_RX_DESC(*rx_ring, i);
++ rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
++
++ if (unlikely(++i == rx_ring->count))
++ i = 0;
++ buffer_info = &rx_ring->buffer_info[i];
++ }
++
++ if (likely(rx_ring->next_to_use != i)) {
++ rx_ring->next_to_use = i;
++ if (unlikely(i-- == 0))
++ i = (rx_ring->count - 1);
++
++ /* Force memory writes to complete before letting h/w
++ * know there are new descriptors to fetch. (Only
++ * applicable for weak-ordered memory model archs,
++ * such as IA-64). */
++ wmb();
++ writel(i, adapter->hw.hw_addr + rx_ring->rdt);
++ }
++}
++
++/**
++ * e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended
++ * @adapter: address of board private structure
++ **/
++
++static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
++ struct e1000_rx_ring *rx_ring,
++ int cleaned_count)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ struct net_device *netdev = adapter->netdev;
++ struct pci_dev *pdev = adapter->pdev;
++ struct e1000_rx_desc *rx_desc;
++ struct e1000_buffer *buffer_info;
++ struct sk_buff *skb;
++ unsigned int i;
++ unsigned int bufsz = adapter->rx_buffer_len;
++
++ i = rx_ring->next_to_use;
++ buffer_info = &rx_ring->buffer_info[i];
++
++ while (cleaned_count--) {
++ skb = buffer_info->skb;
++ if (skb) {
++ skb_trim(skb, 0);
++ goto map_skb;
++ }
++
++ skb = netdev_alloc_skb_ip_align(netdev, bufsz);
++ if (unlikely(!skb)) {
++ /* Better luck next round */
++ adapter->alloc_rx_buff_failed++;
++ break;
++ }
++
++ /* Fix for errata 23, can't cross 64kB boundary */
++ if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
++ struct sk_buff *oldskb = skb;
++ e_err("skb align check failed: %u bytes at %p\n",
++ bufsz, skb->data);
++ /* Try again, without freeing the previous */
++ skb = netdev_alloc_skb_ip_align(netdev, bufsz);
++ /* Failed allocation, critical failure */
++ if (!skb) {
++ dev_kfree_skb(oldskb);
++ adapter->alloc_rx_buff_failed++;
++ break;
++ }
++
++ if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
++ /* give up */
++ dev_kfree_skb(skb);
++ dev_kfree_skb(oldskb);
++ adapter->alloc_rx_buff_failed++;
++ break; /* while !buffer_info->skb */
++ }
++
++ /* Use new allocation */
++ dev_kfree_skb(oldskb);
++ }
++ buffer_info->skb = skb;
++ buffer_info->length = adapter->rx_buffer_len;
++map_skb:
++ buffer_info->dma = dma_map_single(&pdev->dev,
++ skb->data,
++ buffer_info->length,
++ DMA_FROM_DEVICE);
++ if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
++ dev_kfree_skb(skb);
++ buffer_info->skb = NULL;
++ buffer_info->dma = 0;
++ adapter->alloc_rx_buff_failed++;
++ break; /* while !buffer_info->skb */
++ }
++
++ /*
++ * XXX if it was allocated cleanly it will never map to a
++ * boundary crossing
++ */
++
++ /* Fix for errata 23, can't cross 64kB boundary */
++ if (!e1000_check_64k_bound(adapter,
++ (void *)(unsigned long)buffer_info->dma,
++ adapter->rx_buffer_len)) {
++ e_err("dma align check failed: %u bytes at %p\n",
++ adapter->rx_buffer_len,
++ (void *)(unsigned long)buffer_info->dma);
++ dev_kfree_skb(skb);
++ buffer_info->skb = NULL;
++
++ dma_unmap_single(&pdev->dev, buffer_info->dma,
++ adapter->rx_buffer_len,
++ DMA_FROM_DEVICE);
++ buffer_info->dma = 0;
++
++ adapter->alloc_rx_buff_failed++;
++ break; /* while !buffer_info->skb */
++ }
++ rx_desc = E1000_RX_DESC(*rx_ring, i);
++ rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
++
++ if (unlikely(++i == rx_ring->count))
++ i = 0;
++ buffer_info = &rx_ring->buffer_info[i];
++ }
++
++ if (likely(rx_ring->next_to_use != i)) {
++ rx_ring->next_to_use = i;
++ if (unlikely(i-- == 0))
++ i = (rx_ring->count - 1);
++
++ /* Force memory writes to complete before letting h/w
++ * know there are new descriptors to fetch. (Only
++ * applicable for weak-ordered memory model archs,
++ * such as IA-64). */
++ wmb();
++ writel(i, hw->hw_addr + rx_ring->rdt);
++ }
++}
++
++/**
++ * e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers.
++ * @adapter:
++ **/
++
++static void e1000_smartspeed(struct e1000_adapter *adapter)
++{
++ struct e1000_hw *hw = &adapter->hw;
++ u16 phy_status;
++ u16 phy_ctrl;
++
++ if ((hw->phy_type != e1000_phy_igp) || !hw->autoneg ||
++ !(hw->autoneg_advertised & ADVERTISE_1000_FULL))
++ return;
++
++ if (adapter->smartspeed == 0) {
++ /* If Master/Slave config fault is asserted twice,
++ * we assume back-to-back */
++ e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status);
++ if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
++ e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status);
++ if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
++ e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl);
++ if (phy_ctrl & CR_1000T_MS_ENABLE) {
++ phy_ctrl &= ~CR_1000T_MS_ENABLE;
++ e1000_write_phy_reg(hw, PHY_1000T_CTRL,
++ phy_ctrl);
++ adapter->smartspeed++;
++ if (!e1000_phy_setup_autoneg(hw) &&
++ !e1000_read_phy_reg(hw, PHY_CTRL,
++ &phy_ctrl)) {
++ phy_ctrl |= (MII_CR_AUTO_NEG_EN |
++ MII_CR_RESTART_AUTO_NEG);
++ e1000_write_phy_reg(hw, PHY_CTRL,
++ phy_ctrl);
++ }
++ }
++ return;
++ } else if (adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
++ /* If still no link, perhaps using 2/3 pair cable */
++ e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl);
++ phy_ctrl |= CR_1000T_MS_ENABLE;
++ e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_ctrl);
++ if (!e1000_phy_setup_autoneg(hw) &&
++ !e1000_read_phy_reg(hw, PHY_CTRL, &phy_ctrl)) {
++ phy_ctrl |= (MII_CR_AUTO_NEG_EN |
++ MII_CR_RESTART_AUTO_NEG);
++ e1000_write_phy_reg(hw, PHY_CTRL, phy_ctrl);
++ }
++ }
++ /* Restart process after E1000_SMARTSPEED_MAX iterations */
++ if (adapter->smartspeed++ == E1000_SMARTSPEED_MAX)
++ adapter->smartspeed = 0;
++}
++
++/**
++ * e1000_ioctl -
++ * @netdev:
++ * @ifreq:
++ * @cmd:
++ **/
++
++static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
++{
++ switch (cmd) {
++ case SIOCGMIIPHY:
++ case SIOCGMIIREG:
++ case SIOCSMIIREG:
++ return e1000_mii_ioctl(netdev, ifr, cmd);
++ default:
++ return -EOPNOTSUPP;
++ }
++}
++
++/**
++ * e1000_mii_ioctl -
++ * @netdev:
++ * @ifreq:
++ * @cmd:
++ **/
++
++static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
++ int cmd)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++ struct mii_ioctl_data *data = if_mii(ifr);
++ int retval;
++ u16 mii_reg;
++ u16 spddplx;
++ unsigned long flags;
++
++ if (hw->media_type != e1000_media_type_copper)
++ return -EOPNOTSUPP;
++
++ switch (cmd) {
++ case SIOCGMIIPHY:
++ data->phy_id = hw->phy_addr;
++ break;
++ case SIOCGMIIREG:
++ spin_lock_irqsave(&adapter->stats_lock, flags);
++ if (e1000_read_phy_reg(hw, data->reg_num & 0x1F,
++ &data->val_out)) {
++ spin_unlock_irqrestore(&adapter->stats_lock, flags);
++ return -EIO;
++ }
++ spin_unlock_irqrestore(&adapter->stats_lock, flags);
++ break;
++ case SIOCSMIIREG:
++ if (data->reg_num & ~(0x1F))
++ return -EFAULT;
++ mii_reg = data->val_in;
++ spin_lock_irqsave(&adapter->stats_lock, flags);
++ if (e1000_write_phy_reg(hw, data->reg_num,
++ mii_reg)) {
++ spin_unlock_irqrestore(&adapter->stats_lock, flags);
++ return -EIO;
++ }
++ spin_unlock_irqrestore(&adapter->stats_lock, flags);
++ if (hw->media_type == e1000_media_type_copper) {
++ switch (data->reg_num) {
++ case PHY_CTRL:
++ if (mii_reg & MII_CR_POWER_DOWN)
++ break;
++ if (mii_reg & MII_CR_AUTO_NEG_EN) {
++ hw->autoneg = 1;
++ hw->autoneg_advertised = 0x2F;
++ } else {
++ if (mii_reg & 0x40)
++ spddplx = SPEED_1000;
++ else if (mii_reg & 0x2000)
++ spddplx = SPEED_100;
++ else
++ spddplx = SPEED_10;
++ spddplx += (mii_reg & 0x100)
++ ? DUPLEX_FULL :
++ DUPLEX_HALF;
++ retval = e1000_set_spd_dplx(adapter,
++ spddplx);
++ if (retval)
++ return retval;
++ }
++ if (netif_running(adapter->netdev))
++ e1000_reinit_locked(adapter);
++ else
++ e1000_reset(adapter);
++ break;
++ case M88E1000_PHY_SPEC_CTRL:
++ case M88E1000_EXT_PHY_SPEC_CTRL:
++ if (e1000_phy_reset(hw))
++ return -EIO;
++ break;
++ }
++ } else {
++ switch (data->reg_num) {
++ case PHY_CTRL:
++ if (mii_reg & MII_CR_POWER_DOWN)
++ break;
++ if (netif_running(adapter->netdev))
++ e1000_reinit_locked(adapter);
++ else
++ e1000_reset(adapter);
++ break;
++ }
++ }
++ break;
++ default:
++ return -EOPNOTSUPP;
++ }
++ return E1000_SUCCESS;
++}
++
++void e1000_pci_set_mwi(struct e1000_hw *hw)
++{
++ struct e1000_adapter *adapter = hw->back;
++ int ret_val = pci_set_mwi(adapter->pdev);
++
++ if (ret_val)
++ e_err("Error in setting MWI\n");
++}
++
++void e1000_pci_clear_mwi(struct e1000_hw *hw)
++{
++ struct e1000_adapter *adapter = hw->back;
++
++ pci_clear_mwi(adapter->pdev);
++}
++
++int e1000_pcix_get_mmrbc(struct e1000_hw *hw)
++{
++ struct e1000_adapter *adapter = hw->back;
++ return pcix_get_mmrbc(adapter->pdev);
++}
++
++void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc)
++{
++ struct e1000_adapter *adapter = hw->back;
++ pcix_set_mmrbc(adapter->pdev, mmrbc);
++}
++
++void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value)
++{
++ outl(value, port);
++}
++
++static void e1000_vlan_rx_register(struct net_device *netdev,
++ struct vlan_group *grp)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++ u32 ctrl, rctl;
++
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ e1000_irq_disable(adapter);
++ adapter->vlgrp = grp;
++
++ if (grp) {
++ /* enable VLAN tag insert/strip */
++ ctrl = er32(CTRL);
++ ctrl |= E1000_CTRL_VME;
++ ew32(CTRL, ctrl);
++
++ /* enable VLAN receive filtering */
++ rctl = er32(RCTL);
++ rctl &= ~E1000_RCTL_CFIEN;
++ if (!(netdev->flags & IFF_PROMISC))
++ rctl |= E1000_RCTL_VFE;
++ ew32(RCTL, rctl);
++ e1000_update_mng_vlan(adapter);
++ } else {
++ /* disable VLAN tag insert/strip */
++ ctrl = er32(CTRL);
++ ctrl &= ~E1000_CTRL_VME;
++ ew32(CTRL, ctrl);
++
++ /* disable VLAN receive filtering */
++ rctl = er32(RCTL);
++ rctl &= ~E1000_RCTL_VFE;
++ ew32(RCTL, rctl);
++
++ if (adapter->mng_vlan_id != (u16)E1000_MNG_VLAN_NONE) {
++ e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
++ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
++ }
++ }
++
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ e1000_irq_enable(adapter);
++}
++
++static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++ u32 vfta, index;
++
++ if ((hw->mng_cookie.status &
++ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
++ (vid == adapter->mng_vlan_id))
++ return;
++ /* add VID to filter table */
++ index = (vid >> 5) & 0x7F;
++ vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
++ vfta |= (1 << (vid & 0x1F));
++ e1000_write_vfta(hw, index, vfta);
++}
++
++static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++ u32 vfta, index;
++
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ e1000_irq_disable(adapter);
++ vlan_group_set_device(adapter->vlgrp, vid, NULL);
++ if (!test_bit(__E1000_DOWN, &adapter->flags))
++ e1000_irq_enable(adapter);
++
++ /* remove VID from filter table */
++ index = (vid >> 5) & 0x7F;
++ vfta = E1000_READ_REG_ARRAY(hw, VFTA, index);
++ vfta &= ~(1 << (vid & 0x1F));
++ e1000_write_vfta(hw, index, vfta);
++}
++
++static void e1000_restore_vlan(struct e1000_adapter *adapter)
++{
++ e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp);
++
++ if (adapter->vlgrp) {
++ u16 vid;
++ for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
++ if (!vlan_group_get_device(adapter->vlgrp, vid))
++ continue;
++ e1000_vlan_rx_add_vid(adapter->netdev, vid);
++ }
++ }
++}
++
++int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
++{
++ struct e1000_hw *hw = &adapter->hw;
++
++ hw->autoneg = 0;
++
++ /* Fiber NICs only allow 1000 gbps Full duplex */
++ if ((hw->media_type == e1000_media_type_fiber) &&
++ spddplx != (SPEED_1000 + DUPLEX_FULL)) {
++ e_err("Unsupported Speed/Duplex configuration\n");
++ return -EINVAL;
++ }
++
++ switch (spddplx) {
++ case SPEED_10 + DUPLEX_HALF:
++ hw->forced_speed_duplex = e1000_10_half;
++ break;
++ case SPEED_10 + DUPLEX_FULL:
++ hw->forced_speed_duplex = e1000_10_full;
++ break;
++ case SPEED_100 + DUPLEX_HALF:
++ hw->forced_speed_duplex = e1000_100_half;
++ break;
++ case SPEED_100 + DUPLEX_FULL:
++ hw->forced_speed_duplex = e1000_100_full;
++ break;
++ case SPEED_1000 + DUPLEX_FULL:
++ hw->autoneg = 1;
++ hw->autoneg_advertised = ADVERTISE_1000_FULL;
++ break;
++ case SPEED_1000 + DUPLEX_HALF: /* not supported */
++ default:
++ e_err("Unsupported Speed/Duplex configuration\n");
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
++{
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++ u32 ctrl, ctrl_ext, rctl, status;
++ u32 wufc = adapter->wol;
++#ifdef CONFIG_PM
++ int retval = 0;
++#endif
++
++ netif_device_detach(netdev);
++
++ if (netif_running(netdev)) {
++ WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
++ e1000_down(adapter);
++ }
++
++#ifdef CONFIG_PM
++ retval = pci_save_state(pdev);
++ if (retval)
++ return retval;
++#endif
++
++ status = er32(STATUS);
++ if (status & E1000_STATUS_LU)
++ wufc &= ~E1000_WUFC_LNKC;
++
++ if (wufc) {
++ e1000_setup_rctl(adapter);
++ e1000_set_rx_mode(netdev);
++
++ /* turn on all-multi mode if wake on multicast is enabled */
++ if (wufc & E1000_WUFC_MC) {
++ rctl = er32(RCTL);
++ rctl |= E1000_RCTL_MPE;
++ ew32(RCTL, rctl);
++ }
++
++ if (hw->mac_type >= e1000_82540) {
++ ctrl = er32(CTRL);
++ /* advertise wake from D3Cold */
++ #define E1000_CTRL_ADVD3WUC 0x00100000
++ /* phy power management enable */
++ #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000
++ ctrl |= E1000_CTRL_ADVD3WUC |
++ E1000_CTRL_EN_PHY_PWR_MGMT;
++ ew32(CTRL, ctrl);
++ }
++
++ if (hw->media_type == e1000_media_type_fiber ||
++ hw->media_type == e1000_media_type_internal_serdes) {
++ /* keep the laser running in D3 */
++ ctrl_ext = er32(CTRL_EXT);
++ ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
++ ew32(CTRL_EXT, ctrl_ext);
++ }
++
++ ew32(WUC, E1000_WUC_PME_EN);
++ ew32(WUFC, wufc);
++ } else {
++ ew32(WUC, 0);
++ ew32(WUFC, 0);
++ }
++
++ e1000_release_manageability(adapter);
++
++ *enable_wake = !!wufc;
++
++ /* make sure adapter isn't asleep if manageability is enabled */
++ if (adapter->en_mng_pt)
++ *enable_wake = true;
++
++ if (netif_running(netdev))
++ e1000_free_irq(adapter);
++
++ pci_disable_device(pdev);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++ int retval;
++ bool wake;
++
++ retval = __e1000_shutdown(pdev, &wake);
++ if (retval)
++ return retval;
++
++ if (wake) {
++ pci_prepare_to_sleep(pdev);
++ } else {
++ pci_wake_from_d3(pdev, false);
++ pci_set_power_state(pdev, PCI_D3hot);
++ }
++
++ return 0;
++}
++
++static int e1000_resume(struct pci_dev *pdev)
++{
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++ u32 err;
++
++ pci_set_power_state(pdev, PCI_D0);
++ pci_restore_state(pdev);
++ pci_save_state(pdev);
++
++ if (adapter->need_ioport)
++ err = pci_enable_device(pdev);
++ else
++ err = pci_enable_device_mem(pdev);
++ if (err) {
++ pr_err("Cannot enable PCI device from suspend\n");
++ return err;
++ }
++ pci_set_master(pdev);
++
++ pci_enable_wake(pdev, PCI_D3hot, 0);
++ pci_enable_wake(pdev, PCI_D3cold, 0);
++
++ if (netif_running(netdev)) {
++ err = e1000_request_irq(adapter);
++ if (err)
++ return err;
++ }
++
++ e1000_power_up_phy(adapter);
++ e1000_reset(adapter);
++ ew32(WUS, ~0);
++
++ e1000_init_manageability(adapter);
++
++ if (netif_running(netdev))
++ e1000_up(adapter);
++
++ netif_device_attach(netdev);
++
++ return 0;
++}
++#endif
++
++static void e1000_shutdown(struct pci_dev *pdev)
++{
++ bool wake;
++
++ __e1000_shutdown(pdev, &wake);
++
++ if (system_state == SYSTEM_POWER_OFF) {
++ pci_wake_from_d3(pdev, wake);
++ pci_set_power_state(pdev, PCI_D3hot);
++ }
++}
++
++#ifdef CONFIG_NET_POLL_CONTROLLER
++/*
++ * Polling 'interrupt' - used by things like netconsole to send skbs
++ * without having to re-enable interrupts. It's not called while
++ * the interrupt routine is executing.
++ */
++static void e1000_netpoll(struct net_device *netdev)
++{
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++
++ disable_irq(adapter->pdev->irq);
++ e1000_intr(adapter->pdev->irq, netdev);
++ enable_irq(adapter->pdev->irq);
++}
++#endif
++
++/**
++ * e1000_io_error_detected - called when PCI error is detected
++ * @pdev: Pointer to PCI device
++ * @state: The current pci connection state
++ *
++ * This function is called after a PCI bus error affecting
++ * this device has been detected.
++ */
++static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
++ pci_channel_state_t state)
++{
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++
++ netif_device_detach(netdev);
++
++ if (state == pci_channel_io_perm_failure)
++ return PCI_ERS_RESULT_DISCONNECT;
++
++ if (netif_running(netdev))
++ e1000_down(adapter);
++ pci_disable_device(pdev);
++
++ /* Request a slot slot reset. */
++ return PCI_ERS_RESULT_NEED_RESET;
++}
++
++/**
++ * e1000_io_slot_reset - called after the pci bus has been reset.
++ * @pdev: Pointer to PCI device
++ *
++ * Restart the card from scratch, as if from a cold-boot. Implementation
++ * resembles the first-half of the e1000_resume routine.
++ */
++static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
++{
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++ struct e1000_hw *hw = &adapter->hw;
++ int err;
++
++ if (adapter->need_ioport)
++ err = pci_enable_device(pdev);
++ else
++ err = pci_enable_device_mem(pdev);
++ if (err) {
++ pr_err("Cannot re-enable PCI device after reset.\n");
++ return PCI_ERS_RESULT_DISCONNECT;
++ }
++ pci_set_master(pdev);
++
++ pci_enable_wake(pdev, PCI_D3hot, 0);
++ pci_enable_wake(pdev, PCI_D3cold, 0);
++
++ e1000_reset(adapter);
++ ew32(WUS, ~0);
++
++ return PCI_ERS_RESULT_RECOVERED;
++}
++
++/**
++ * e1000_io_resume - called when traffic can start flowing again.
++ * @pdev: Pointer to PCI device
++ *
++ * This callback is called when the error recovery driver tells us that
++ * its OK to resume normal operation. Implementation resembles the
++ * second-half of the e1000_resume routine.
++ */
++static void e1000_io_resume(struct pci_dev *pdev)
++{
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct e1000_adapter *adapter = netdev_priv(netdev);
++
++ e1000_init_manageability(adapter);
++
++ if (netif_running(netdev)) {
++ if (e1000_up(adapter)) {
++ pr_info("can't bring device back up after reset\n");
++ return;
++ }
++ }
++
++ netif_device_attach(netdev);
++}
++
++/* e1000_main.c */
+diff -rupN linux-2.6.35.11/drivers/net/fast_bridge.c linux-2.6.35.11-ts7500/drivers/net/fast_bridge.c
+--- linux-2.6.35.11/drivers/net/fast_bridge.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/fast_bridge.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,184 @@
++#include <linux/stddef.h>
++//#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <asm/byteorder.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/errno.h>
++#include <linux/ioport.h>
++#include <linux/pci.h>
++#include <linux/kernel.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <net/sock.h>
++#include <linux/rtnetlink.h>
++#include <linux/delay.h>
++#include <linux/timer.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/interrupt.h>
++#include <linux/string.h>
++#include <linux/pagemap.h>
++#include <linux/proc_fs.h>
++#include <asm/bitops.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <linux/capability.h>
++#include <linux/in.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/udp.h>
++#include <net/pkt_sched.h>
++#include <linux/list.h>
++#include <linux/reboot.h>
++#ifdef NETIF_F_TSO
++#include <net/checksum.h>
++#endif
++#ifdef SIOCGMIIPHY
++#include <linux/mii.h>
++#endif
++#ifdef SIOCETHTOOL
++#include <linux/ethtool.h>
++#endif
++#ifdef NETIF_F_HW_VLAN_TX
++#include <linux/if_vlan.h>
++#endif
++
++static struct net_device *fast_bridge_dev1;
++static struct net_device *fast_bridge_dev2;
++static int fast_bridge_dev1_ready;
++static int fast_bridge_dev2_ready;
++
++static struct proc_dir_entry *fast_bridge_proc_entry;
++int fast_bridge_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data);
++int fast_bridge_write_proc(struct file *file, const char *buffer, unsigned long count, void *data);
++
++#ifdef CONFIG_CPU_ISPAD_ENABLE
++__attribute__((section(".ispad"))) \
++int fast_bridge_forward_skb(struct sk_buff *skb)
++#else
++int fast_bridge_forward_skb(struct sk_buff *skb)
++#endif
++{
++#if 0
++ skb->h.raw = skb->nh.raw = skb->data;
++ skb->mac_len = skb->nh.raw - skb->mac.raw;
++#endif
++
++ if (!fast_bridge_dev1_ready || !fast_bridge_dev2_ready) {
++#if 0
++ kfree_skb(skb);
++#endif
++ return -1;
++ }
++
++ if (skb->dev != fast_bridge_dev1 && skb->dev != fast_bridge_dev2) {
++ return -1;
++ }
++
++ if (skb->dev == fast_bridge_dev1) {
++ skb->dev = fast_bridge_dev2;
++ } else if (skb->dev == fast_bridge_dev2) {
++ skb->dev = fast_bridge_dev1;
++ }
++ skb->ip_summed = CHECKSUM_NONE;
++ skb_push(skb, ETH_HLEN);
++#if 1
++ dev_queue_xmit(skb);
++#else
++ // not in 2.6.34!!!
++ skb->dev->hard_start_xmit(skb, skb->dev);
++#endif
++
++ return 0;
++}
++
++int fast_bridge_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
++{
++ return 0;
++}
++
++int fast_bridge_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
++{
++ char *str;
++ char *dev1;
++ char *dev2;
++
++ if (count > 0) {
++ str = (char *)buffer;
++ dev1 = strsep(&str, "\t \n");
++ if (!dev1) goto out;
++ dev2 = strsep(&str, "\t \n");
++ if (!dev2) goto out;
++ /* scott.nic
++ fast_bridge_dev1 = dev_get_by_name(dev1);
++ */
++ fast_bridge_dev1 = dev_get_by_name(&init_net, dev1);
++ if (!fast_bridge_dev1) goto out;
++
++ /* scott.nic
++ fast_bridge_dev2 = dev_get_by_name(dev2);
++ */
++ fast_bridge_dev2 = dev_get_by_name(&init_net, dev2);
++ if (!fast_bridge_dev2) {
++ dev_put(fast_bridge_dev1);
++ goto out;
++ }
++ /* scott.nic
++ rtnl_shlock();
++ */
++ if (!(fast_bridge_dev1->flags & IFF_UP)) {
++ dev_open(fast_bridge_dev1);
++ }
++ if (!(fast_bridge_dev2->flags & IFF_UP)) {
++ dev_open(fast_bridge_dev2);
++ }
++ if (!(fast_bridge_dev1->flags & IFF_PROMISC)) {
++ dev_set_promiscuity(fast_bridge_dev1, 1);
++ }
++ if (!(fast_bridge_dev2->flags & IFF_PROMISC)) {
++ dev_set_promiscuity(fast_bridge_dev2, 1);
++ }
++ fast_bridge_dev1_ready = 1;
++ fast_bridge_dev2_ready = 1;
++ /* scott.nic
++ rtnl_shunlock();
++ */
++ }
++
++ return count;
++
++out:
++ return -EFAULT;
++}
++
++static void fast_bridge_proc_init(void)
++{
++ fast_bridge_proc_entry = create_proc_entry("fast_bridge", S_IFREG | S_IRUGO | S_IWUSR, NULL);
++ if (fast_bridge_proc_entry) {
++ fast_bridge_proc_entry->read_proc = fast_bridge_read_proc;
++ fast_bridge_proc_entry->write_proc = fast_bridge_write_proc;
++ fast_bridge_proc_entry->data = NULL;
++ }
++}
++
++static int __init fast_bridge_init_module(void)
++{
++ fast_bridge_proc_init();
++ return 0;
++}
++
++static void __exit fast_bridge_exit_module(void)
++{
++
++}
++
++module_init(fast_bridge_init_module);
++module_exit(fast_bridge_exit_module);
++
++MODULE_AUTHOR("KC Huang");
++MODULE_DESCRIPTION("FAST SIMPLE BRIDGE");
++MODULE_LICENSE("GPL");
++
+diff -rupN linux-2.6.35.11/drivers/net/Kconfig linux-2.6.35.11-ts7500/drivers/net/Kconfig
+--- linux-2.6.35.11/drivers/net/Kconfig 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/Kconfig 2011-03-14 11:18:24.000000000 -0400
+@@ -2005,6 +2005,10 @@ menuconfig NETDEV_1000
+
+ if NETDEV_1000
+
++config FAST_BRIDGE
++ depends on NET
++ bool "Simple Fast Bridge driver support"
++
+ config ACENIC
+ tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support"
+ depends on PCI
+@@ -2840,6 +2844,10 @@ source "drivers/net/benet/Kconfig"
+
+ endif # NETDEV_10000
+
++source "drivers/net/str9100/Kconfig"
++
++source "drivers/net/str8100/Kconfig"
++
+ source "drivers/net/tokenring/Kconfig"
+
+ source "drivers/net/wireless/Kconfig"
+diff -rupN linux-2.6.35.11/drivers/net/Kconfig.orig linux-2.6.35.11-ts7500/drivers/net/Kconfig.orig
+--- linux-2.6.35.11/drivers/net/Kconfig.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/Kconfig.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,3314 @@
++#
++# Network device configuration
++#
++
++menuconfig NETDEVICES
++ default y if UML
++ depends on NET
++ bool "Network device support"
++ ---help---
++ You can say N here if you don't intend to connect your Linux box to
++ any other computer at all.
++
++ You'll have to say Y if your computer contains a network card that
++ you want to use under Linux. If you are going to run SLIP or PPP over
++ telephone line or null modem cable you need say Y here. Connecting
++ two machines with parallel ports using PLIP needs this, as well as
++ AX.25/KISS for sending Internet traffic over amateur radio links.
++
++ See also "The Linux Network Administrator's Guide" by Olaf Kirch and
++ Terry Dawson. Available at <http://www.tldp.org/guides.html>.
++
++ If unsure, say Y.
++
++# All the following symbols are dependent on NETDEVICES - do not repeat
++# that for each of the symbols.
++if NETDEVICES
++
++config IFB
++ tristate "Intermediate Functional Block support"
++ depends on NET_CLS_ACT
++ ---help---
++ This is an intermediate driver that allows sharing of
++ resources.
++ To compile this driver as a module, choose M here: the module
++ will be called ifb. If you want to use more than one ifb
++ device at a time, you need to compile this driver as a module.
++ Instead of 'ifb', the devices will then be called 'ifb0',
++ 'ifb1' etc.
++ Look at the iproute2 documentation directory for usage etc
++
++config DUMMY
++ tristate "Dummy net driver support"
++ ---help---
++ This is essentially a bit-bucket device (i.e. traffic you send to
++ this device is consigned into oblivion) with a configurable IP
++ address. It is most commonly used in order to make your currently
++ inactive SLIP address seem like a real address for local programs.
++ If you use SLIP or PPP, you might want to say Y here. Since this
++ thing often comes in handy, the default is Y. It won't enlarge your
++ kernel either. What a deal. Read about it in the Network
++ Administrator's Guide, available from
++ <http://www.tldp.org/docs.html#guide>.
++
++ To compile this driver as a module, choose M here: the module
++ will be called dummy. If you want to use more than one dummy
++ device at a time, you need to compile this driver as a module.
++ Instead of 'dummy', the devices will then be called 'dummy0',
++ 'dummy1' etc.
++
++config BONDING
++ tristate "Bonding driver support"
++ depends on INET
++ depends on IPV6 || IPV6=n
++ ---help---
++ Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet
++ Channels together. This is called 'Etherchannel' by Cisco,
++ 'Trunking' by Sun, 802.3ad by the IEEE, and 'Bonding' in Linux.
++
++ The driver supports multiple bonding modes to allow for both high
++ performance and high availability operation.
++
++ Refer to <file:Documentation/networking/bonding.txt> for more
++ information.
++
++ To compile this driver as a module, choose M here: the module
++ will be called bonding.
++
++config MACVLAN
++ tristate "MAC-VLAN support (EXPERIMENTAL)"
++ depends on EXPERIMENTAL
++ ---help---
++ This allows one to create virtual interfaces that map packets to
++ or from specific MAC addresses to a particular interface.
++
++ Macvlan devices can be added using the "ip" command from the
++ iproute2 package starting with the iproute2-2.6.23 release:
++
++ "ip link add link <real dev> [ address MAC ] [ NAME ] type macvlan"
++
++ To compile this driver as a module, choose M here: the module
++ will be called macvlan.
++
++config MACVTAP
++ tristate "MAC-VLAN based tap driver (EXPERIMENTAL)"
++ depends on MACVLAN
++ help
++ This adds a specialized tap character device driver that is based
++ on the MAC-VLAN network interface, called macvtap. A macvtap device
++ can be added in the same way as a macvlan device, using 'type
++ macvlan', and then be accessed through the tap user space interface.
++
++ To compile this driver as a module, choose M here: the module
++ will be called macvtap.
++
++config EQUALIZER
++ tristate "EQL (serial line load balancing) support"
++ ---help---
++ If you have two serial connections to some other computer (this
++ usually requires two modems and two telephone lines) and you use
++ SLIP (the protocol for sending Internet traffic over telephone
++ lines) or PPP (a better SLIP) on them, you can make them behave like
++ one double speed connection using this driver. Naturally, this has
++ to be supported at the other end as well, either with a similar EQL
++ Linux driver or with a Livingston Portmaster 2e.
++
++ Say Y if you want this and read
++ <file:Documentation/networking/eql.txt>. You may also want to read
++ section 6.2 of the NET-3-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here: the module
++ will be called eql. If unsure, say N.
++
++config TUN
++ tristate "Universal TUN/TAP device driver support"
++ select CRC32
++ ---help---
++ TUN/TAP provides packet reception and transmission for user space
++ programs. It can be viewed as a simple Point-to-Point or Ethernet
++ device, which instead of receiving packets from a physical media,
++ receives them from user space program and instead of sending packets
++ via physical media writes them to the user space program.
++
++ When a program opens /dev/net/tun, driver creates and registers
++ corresponding net device tunX or tapX. After a program closed above
++ devices, driver will automatically delete tunXX or tapXX device and
++ all routes corresponding to it.
++
++ Please read <file:Documentation/networking/tuntap.txt> for more
++ information.
++
++ To compile this driver as a module, choose M here: the module
++ will be called tun.
++
++ If you don't know what to use this for, you don't need it.
++
++config VETH
++ tristate "Virtual ethernet pair device"
++ ---help---
++ This device is a local ethernet tunnel. Devices are created in pairs.
++ When one end receives the packet it appears on its pair and vice
++ versa.
++
++config NET_SB1000
++ tristate "General Instruments Surfboard 1000"
++ depends on PNP
++ ---help---
++ This is a driver for the General Instrument (also known as
++ NextLevel) SURFboard 1000 internal
++ cable modem. This is an ISA card which is used by a number of cable
++ TV companies to provide cable modem access. It's a one-way
++ downstream-only cable modem, meaning that your upstream net link is
++ provided by your regular phone modem.
++
++ At present this driver only compiles as a module, so say M here if
++ you have this card. The module will be called sb1000. Then read
++ <file:Documentation/networking/README.sb1000> for information on how
++ to use this module, as it needs special ppp scripts for establishing
++ a connection. Further documentation and the necessary scripts can be
++ found at:
++
++ <http://www.jacksonville.net/~fventuri/>
++ <http://home.adelphia.net/~siglercm/sb1000.html>
++ <http://linuxpower.cx/~cable/>
++
++ If you don't have this card, of course say N.
++
++source "drivers/net/arcnet/Kconfig"
++
++source "drivers/net/phy/Kconfig"
++
++#
++# Ethernet
++#
++
++menuconfig NET_ETHERNET
++ bool "Ethernet (10 or 100Mbit)"
++ depends on !UML
++ ---help---
++ Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common
++ type of Local Area Network (LAN) in universities and companies.
++
++ Common varieties of Ethernet are: 10BASE-2 or Thinnet (10 Mbps over
++ coaxial cable, linking computers in a chain), 10BASE-T or twisted
++ pair (10 Mbps over twisted pair cable, linking computers to central
++ hubs), 10BASE-F (10 Mbps over optical fiber links, using hubs),
++ 100BASE-TX (100 Mbps over two twisted pair cables, using hubs),
++ 100BASE-T4 (100 Mbps over 4 standard voice-grade twisted pair
++ cables, using hubs), 100BASE-FX (100 Mbps over optical fiber links)
++ [the 100BASE varieties are also known as Fast Ethernet], and Gigabit
++ Ethernet (1 Gbps over optical fiber or short copper links).
++
++ If your Linux machine will be connected to an Ethernet and you have
++ an Ethernet network interface card (NIC) installed in your computer,
++ say Y here and read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>. You will then also have
++ to say Y to the driver for your particular NIC.
++
++ Note that the answer to this question won't directly affect the
++ kernel: saying N will just cause the configurator to skip all
++ the questions about Ethernet network cards. If unsure, say N.
++
++if NET_ETHERNET
++
++config MII
++ tristate "Generic Media Independent Interface device support"
++ help
++ Most ethernet controllers have MII transceiver either as an external
++ or internal device. It is safe to say Y or M here even if your
++ ethernet card lack MII.
++
++config MACB
++ tristate "Atmel MACB support"
++ depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 || ARCH_AT91SAM9G20 || ARCH_AT91SAM9G45 || ARCH_AT91CAP9
++ select PHYLIB
++ help
++ The Atmel MACB ethernet interface is found on many AT32 and AT91
++ parts. Say Y to include support for the MACB chip.
++
++ To compile this driver as a module, choose M here: the module
++ will be called macb.
++
++source "drivers/net/arm/Kconfig"
++
++config AX88796
++ tristate "ASIX AX88796 NE2000 clone support"
++ depends on ARM || MIPS || SUPERH
++ select CRC32
++ select MII
++ help
++ AX88796 driver, using platform bus to provide
++ chip detection and resources
++
++config AX88796_93CX6
++ bool "ASIX AX88796 external 93CX6 eeprom support"
++ depends on AX88796
++ select EEPROM_93CX6
++ help
++ Select this if your platform comes with an external 93CX6 eeprom.
++
++config MACE
++ tristate "MACE (Power Mac ethernet) support"
++ depends on PPC_PMAC && PPC32
++ select CRC32
++ help
++ Power Macintoshes and clones with Ethernet built-in on the
++ motherboard will usually use a MACE (Medium Access Control for
++ Ethernet) interface. Say Y to include support for the MACE chip.
++
++ To compile this driver as a module, choose M here: the module
++ will be called mace.
++
++config MACE_AAUI_PORT
++ bool "Use AAUI port instead of TP by default"
++ depends on MACE
++ help
++ Some Apple machines (notably the Apple Network Server) which use the
++ MACE ethernet chip have an Apple AUI port (small 15-pin connector),
++ instead of an 8-pin RJ45 connector for twisted-pair ethernet. Say
++ Y here if you have such a machine. If unsure, say N.
++ The driver will default to AAUI on ANS anyway, and if you use it as
++ a module, you can provide the port_aaui=0|1 to force the driver.
++
++config BMAC
++ tristate "BMAC (G3 ethernet) support"
++ depends on PPC_PMAC && PPC32
++ select CRC32
++ help
++ Say Y for support of BMAC Ethernet interfaces. These are used on G3
++ computers.
++
++ To compile this driver as a module, choose M here: the module
++ will be called bmac.
++
++config ARIADNE
++ tristate "Ariadne support"
++ depends on ZORRO
++ help
++ If you have a Village Tronic Ariadne Ethernet adapter, say Y.
++ Otherwise, say N.
++
++ To compile this driver as a module, choose M here: the module
++ will be called ariadne.
++
++config A2065
++ tristate "A2065 support"
++ depends on ZORRO
++ select CRC32
++ help
++ If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise,
++ say N.
++
++ To compile this driver as a module, choose M here: the module
++ will be called a2065.
++
++config HYDRA
++ tristate "Hydra support"
++ depends on ZORRO
++ select CRC32
++ help
++ If you have a Hydra Ethernet adapter, say Y. Otherwise, say N.
++
++ To compile this driver as a module, choose M here: the module
++ will be called hydra.
++
++config ZORRO8390
++ tristate "Zorro NS8390-based Ethernet support"
++ depends on ZORRO
++ select CRC32
++ help
++ This driver is for Zorro Ethernet cards using an NS8390-compatible
++ chipset, like the Village Tronic Ariadne II and the Individual
++ Computers X-Surf Ethernet cards. If you have such a card, say Y.
++ Otherwise, say N.
++
++ To compile this driver as a module, choose M here: the module
++ will be called zorro8390.
++
++config APNE
++ tristate "PCMCIA NE2000 support"
++ depends on AMIGA_PCMCIA
++ select CRC32
++ help
++ If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise,
++ say N.
++
++ To compile this driver as a module, choose M here: the module
++ will be called apne.
++
++config MAC8390
++ bool "Macintosh NS 8390 based ethernet cards"
++ depends on MAC
++ select CRC32
++ help
++ If you want to include a driver to support Nubus or LC-PDS
++ Ethernet cards using an NS8390 chipset or its equivalent, say Y
++ and read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++config MAC89x0
++ tristate "Macintosh CS89x0 based ethernet cards"
++ depends on MAC
++ ---help---
++ Support for CS89x0 chipset based Ethernet cards. If you have a
++ Nubus or LC-PDS network (Ethernet) card of this type, say Y and
++ read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. This module will
++ be called mac89x0.
++
++config MACSONIC
++ tristate "Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)"
++ depends on MAC
++ ---help---
++ Support for NatSemi SONIC based Ethernet devices. This includes
++ the onboard Ethernet in many Quadras as well as some LC-PDS,
++ a few Nubus and all known Comm Slot Ethernet cards. If you have
++ one of these say Y and read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. This module will
++ be called macsonic.
++
++config MACMACE
++ bool "Macintosh (AV) onboard MACE ethernet"
++ depends on MAC
++ select CRC32
++ help
++ Support for the onboard AMD 79C940 MACE Ethernet controller used in
++ the 660AV and 840AV Macintosh. If you have one of these Macintoshes
++ say Y and read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++config MVME147_NET
++ tristate "MVME147 (Lance) Ethernet support"
++ depends on MVME147
++ select CRC32
++ help
++ Support for the on-board Ethernet interface on the Motorola MVME147
++ single-board computer. Say Y here to include the
++ driver for this chip in your kernel.
++ To compile this driver as a module, choose M here.
++
++config MVME16x_NET
++ tristate "MVME16x Ethernet support"
++ depends on MVME16x
++ help
++ This is the driver for the Ethernet interface on the Motorola
++ MVME162, 166, 167, 172 and 177 boards. Say Y here to include the
++ driver for this chip in your kernel.
++ To compile this driver as a module, choose M here.
++
++config BVME6000_NET
++ tristate "BVME6000 Ethernet support"
++ depends on BVME6000
++ help
++ This is the driver for the Ethernet interface on BVME4000 and
++ BVME6000 VME boards. Say Y here to include the driver for this chip
++ in your kernel.
++ To compile this driver as a module, choose M here.
++
++config ATARILANCE
++ tristate "Atari Lance support"
++ depends on ATARI
++ help
++ Say Y to include support for several Atari Ethernet adapters based
++ on the AMD Lance chipset: RieblCard (with or without battery), or
++ PAMCard VME (also the version by Rhotron, with different addresses).
++
++config SUN3LANCE
++ tristate "Sun3/Sun3x on-board LANCE support"
++ depends on SUN3 || SUN3X
++ help
++ Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80)
++ featured an AMD Lance 10Mbit Ethernet controller on board; say Y
++ here to compile in the Linux driver for this and enable Ethernet.
++ General Linux information on the Sun 3 and 3x series (now
++ discontinued) is at
++ <http://www.angelfire.com/ca2/tech68k/sun3.html>.
++
++ If you're not building a kernel for a Sun 3, say N.
++
++config SUN3_82586
++ bool "Sun3 on-board Intel 82586 support"
++ depends on SUN3
++ help
++ This driver enables support for the on-board Intel 82586 based
++ Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards. Note
++ that this driver does not support 82586-based adapters on additional
++ VME boards.
++
++config HPLANCE
++ bool "HP on-board LANCE support"
++ depends on DIO
++ select CRC32
++ help
++ If you want to use the builtin "LANCE" Ethernet controller on an
++ HP300 machine, say Y here.
++
++config LASI_82596
++ tristate "Lasi ethernet"
++ depends on GSC
++ help
++ Say Y here to support the builtin Intel 82596 ethernet controller
++ found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet.
++
++config SNI_82596
++ tristate "SNI RM ethernet"
++ depends on NET_ETHERNET && SNI_RM
++ help
++ Say Y here to support the on-board Intel 82596 ethernet controller
++ built into SNI RM machines.
++
++config KORINA
++ tristate "Korina (IDT RC32434) Ethernet support"
++ depends on NET_ETHERNET && MIKROTIK_RB532
++ help
++ If you have a Mikrotik RouterBoard 500 or IDT RC32434
++ based system say Y. Otherwise say N.
++
++config MIPS_JAZZ_SONIC
++ tristate "MIPS JAZZ onboard SONIC Ethernet support"
++ depends on MACH_JAZZ
++ help
++ This is the driver for the onboard card of MIPS Magnum 4000,
++ Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
++
++config XTENSA_XT2000_SONIC
++ tristate "Xtensa XT2000 onboard SONIC Ethernet support"
++ depends on XTENSA_PLATFORM_XT2000
++ help
++ This is the driver for the onboard card of the Xtensa XT2000 board.
++
++config MIPS_AU1X00_ENET
++ tristate "MIPS AU1000 Ethernet support"
++ depends on SOC_AU1X00
++ select PHYLIB
++ select CRC32
++ help
++ If you have an Alchemy Semi AU1X00 based system
++ say Y. Otherwise, say N.
++
++config SGI_IOC3_ETH
++ bool "SGI IOC3 Ethernet"
++ depends on PCI && SGI_IP27
++ select CRC32
++ select MII
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++config MIPS_SIM_NET
++ tristate "MIPS simulator Network device"
++ depends on MIPS_SIM
++ help
++ The MIPSNET device is a simple Ethernet network device which is
++ emulated by the MIPS Simulator.
++ If you are not using a MIPSsim or are unsure, say N.
++
++config SGI_O2MACE_ETH
++ tristate "SGI O2 MACE Fast Ethernet support"
++ depends on SGI_IP32=y
++
++config STNIC
++ tristate "National DP83902AV support"
++ depends on SUPERH
++ select CRC32
++ help
++ Support for cards based on the National Semiconductor DP83902AV
++ ST-NIC Serial Network Interface Controller for Twisted Pair. This
++ is a 10Mbit/sec Ethernet controller. Product overview and specs at
++ <http://www.national.com/pf/DP/DP83902A.html>.
++
++ If unsure, say N.
++
++config SH_ETH
++ tristate "Renesas SuperH Ethernet support"
++ depends on SUPERH && \
++ (CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \
++ CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \
++ CPU_SUBTYPE_SH7724)
++ select CRC32
++ select MII
++ select MDIO_BITBANG
++ select PHYLIB
++ help
++ Renesas SuperH Ethernet device driver.
++ This driver support SH7710, SH7712, SH7763, SH7619, and SH7724.
++
++config SUNLANCE
++ tristate "Sun LANCE support"
++ depends on SBUS
++ select CRC32
++ help
++ This driver supports the "le" interface present on all 32-bit Sparc
++ systems, on some older Ultra systems and as an Sbus option. These
++ cards are based on the AMD Lance chipset, which is better known
++ via the NE2100 cards.
++
++ To compile this driver as a module, choose M here: the module
++ will be called sunlance.
++
++config HAPPYMEAL
++ tristate "Sun Happy Meal 10/100baseT support"
++ depends on SBUS || PCI
++ select CRC32
++ help
++ This driver supports the "hme" interface present on most Ultra
++ systems and as an option on older Sbus systems. This driver supports
++ both PCI and Sbus devices. This driver also supports the "qfe" quad
++ 100baseT device available in both PCI and Sbus configurations.
++
++ To compile this driver as a module, choose M here: the module
++ will be called sunhme.
++
++config SUNBMAC
++ tristate "Sun BigMAC 10/100baseT support (EXPERIMENTAL)"
++ depends on SBUS && EXPERIMENTAL
++ select CRC32
++ help
++ This driver supports the "be" interface available as an Sbus option.
++ This is Sun's older 100baseT Ethernet device.
++
++ To compile this driver as a module, choose M here: the module
++ will be called sunbmac.
++
++config SUNQE
++ tristate "Sun QuadEthernet support"
++ depends on SBUS
++ select CRC32
++ help
++ This driver supports the "qe" 10baseT Ethernet device, available as
++ an Sbus option. Note that this is not the same as Quad FastEthernet
++ "qfe" which is supported by the Happy Meal driver instead.
++
++ To compile this driver as a module, choose M here: the module
++ will be called sunqe.
++
++config SUNGEM
++ tristate "Sun GEM support"
++ depends on PCI
++ select CRC32
++ help
++ Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also
++ <http://www.sun.com/products-n-solutions/hardware/docs/pdf/806-3985-10.pdf>.
++
++config CASSINI
++ tristate "Sun Cassini support"
++ depends on PCI
++ select CRC32
++ help
++ Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
++ <http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf>
++
++config SUNVNET
++ tristate "Sun Virtual Network support"
++ depends on SUN_LDOMS
++ help
++ Support for virtual network devices under Sun Logical Domains.
++
++config NET_VENDOR_3COM
++ bool "3COM cards"
++ depends on ISA || EISA || MCA || PCI
++ help
++ If you have a network (Ethernet) card belonging to this class, say Y
++ and read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ Note that the answer to this question doesn't directly affect the
++ kernel: saying N will just cause the configurator to skip all
++ the questions about 3COM cards. If you say Y, you will be asked for
++ your specific card in the following questions.
++
++config EL1
++ tristate "3c501 \"EtherLink\" support"
++ depends on NET_VENDOR_3COM && ISA
++ ---help---
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>. Also, consider buying a
++ new card, since the 3c501 is slow, broken, and obsolete: you will
++ have problems. Some people suggest to ping ("man ping") a nearby
++ machine every minute ("man cron") when using this card.
++
++ To compile this driver as a module, choose M here. The module
++ will be called 3c501.
++
++config EL2
++ tristate "3c503 \"EtherLink II\" support"
++ depends on NET_VENDOR_3COM && ISA
++ select CRC32
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called 3c503.
++
++config ELPLUS
++ tristate "3c505 \"EtherLink Plus\" support"
++ depends on NET_VENDOR_3COM && ISA && ISA_DMA_API
++ ---help---
++ Information about this network (Ethernet) card can be found in
++ <file:Documentation/networking/3c505.txt>. If you have a card of
++ this type, say Y and read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called 3c505.
++
++config EL16
++ tristate "3c507 \"EtherLink 16\" support (EXPERIMENTAL)"
++ depends on NET_VENDOR_3COM && ISA && EXPERIMENTAL
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called 3c507.
++
++config EL3
++ tristate "3c509/3c529 (MCA)/3c579 \"EtherLink III\" support"
++ depends on NET_VENDOR_3COM && (ISA || EISA || MCA)
++ ---help---
++ If you have a network (Ethernet) card belonging to the 3Com
++ EtherLinkIII series, say Y and read the Ethernet-HOWTO, available
++ from <http://www.tldp.org/docs.html#howto>.
++
++ If your card is not working you may need to use the DOS
++ setup disk to disable Plug & Play mode, and to select the default
++ media type.
++
++ To compile this driver as a module, choose M here. The module
++ will be called 3c509.
++
++config 3C515
++ tristate "3c515 ISA \"Fast EtherLink\""
++ depends on NET_VENDOR_3COM && (ISA || EISA) && ISA_DMA_API
++ help
++ If you have a 3Com ISA EtherLink XL "Corkscrew" 3c515 Fast Ethernet
++ network card, say Y and read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called 3c515.
++
++config ELMC
++ tristate "3c523 \"EtherLink/MC\" support"
++ depends on NET_VENDOR_3COM && MCA_LEGACY
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called 3c523.
++
++config ELMC_II
++ tristate "3c527 \"EtherLink/MC 32\" support (EXPERIMENTAL)"
++ depends on NET_VENDOR_3COM && MCA && MCA_LEGACY
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called 3c527.
++
++config VORTEX
++ tristate "3c590/3c900 series (592/595/597) \"Vortex/Boomerang\" support"
++ depends on NET_VENDOR_3COM && (PCI || EISA)
++ select MII
++ ---help---
++ This option enables driver support for a large number of 10Mbps and
++ 10/100Mbps EISA, PCI and PCMCIA 3Com network cards:
++
++ "Vortex" (Fast EtherLink 3c590/3c592/3c595/3c597) EISA and PCI
++ "Boomerang" (EtherLink XL 3c900 or 3c905) PCI
++ "Cyclone" (3c540/3c900/3c905/3c980/3c575/3c656) PCI and Cardbus
++ "Tornado" (3c905) PCI
++ "Hurricane" (3c555/3cSOHO) PCI
++
++ If you have such a card, say Y and read the Ethernet-HOWTO,
++ available from <http://www.tldp.org/docs.html#howto>. More
++ specific information is in
++ <file:Documentation/networking/vortex.txt> and in the comments at
++ the beginning of <file:drivers/net/3c59x.c>.
++
++ To compile this support as a module, choose M here.
++
++config TYPHOON
++ tristate "3cr990 series \"Typhoon\" support"
++ depends on NET_VENDOR_3COM && PCI
++ select CRC32
++ ---help---
++ This option enables driver support for the 3cr990 series of cards:
++
++ 3C990-TX, 3CR990-TX-95, 3CR990-TX-97, 3CR990-FX-95, 3CR990-FX-97,
++ 3CR990SVR, 3CR990SVR95, 3CR990SVR97, 3CR990-FX-95 Server,
++ 3CR990-FX-97 Server, 3C990B-TX-M, 3C990BSVR
++
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called typhoon.
++
++config LANCE
++ tristate "AMD LANCE and PCnet (AT1500 and NE2100) support"
++ depends on ISA && ISA_DMA_API
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>. Some LinkSys cards are
++ of this type.
++
++ To compile this driver as a module, choose M here: the module
++ will be called lance. This is recommended.
++
++config NET_VENDOR_SMC
++ bool "Western Digital/SMC cards"
++ depends on ISA || MCA || EISA || MAC
++ help
++ If you have a network (Ethernet) card belonging to this class, say Y
++ and read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ Note that the answer to this question doesn't directly affect the
++ kernel: saying N will just cause the configurator to skip all
++ the questions about Western Digital cards. If you say Y, you will be
++ asked for your specific card in the following questions.
++
++config WD80x3
++ tristate "WD80*3 support"
++ depends on NET_VENDOR_SMC && ISA
++ select CRC32
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called wd.
++
++config ULTRAMCA
++ tristate "SMC Ultra MCA support"
++ depends on NET_VENDOR_SMC && MCA
++ select CRC32
++ help
++ If you have a network (Ethernet) card of this type and are running
++ an MCA based system (PS/2), say Y and read the Ethernet-HOWTO,
++ available from <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called smc-mca.
++
++config ULTRA
++ tristate "SMC Ultra support"
++ depends on NET_VENDOR_SMC && ISA
++ select CRC32
++ ---help---
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ Important: There have been many reports that, with some motherboards
++ mixing an SMC Ultra and an Adaptec AHA154x SCSI card (or compatible,
++ such as some BusLogic models) causes corruption problems with many
++ operating systems. The Linux smc-ultra driver has a work-around for
++ this but keep it in mind if you have such a SCSI card and have
++ problems.
++
++ To compile this driver as a module, choose M here. The module
++ will be called smc-ultra.
++
++config ULTRA32
++ tristate "SMC Ultra32 EISA support"
++ depends on NET_VENDOR_SMC && EISA
++ select CRC32
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called smc-ultra32.
++
++config BFIN_MAC
++ tristate "Blackfin on-chip MAC support"
++ depends on NET_ETHERNET && (BF516 || BF518 || BF526 || BF527 || BF536 || BF537)
++ select CRC32
++ select MII
++ select PHYLIB
++ select BFIN_MAC_USE_L1 if DMA_UNCACHED_NONE
++ help
++ This is the driver for Blackfin on-chip mac device. Say Y if you want it
++ compiled into the kernel. This driver is also available as a module
++ ( = code which can be inserted in and removed from the running kernel
++ whenever you want). The module will be called bfin_mac.
++
++config BFIN_MAC_USE_L1
++ bool "Use L1 memory for rx/tx packets"
++ depends on BFIN_MAC && (BF527 || BF537)
++ default y
++ help
++ To get maximum network performance, you should use L1 memory as rx/tx buffers.
++ Say N here if you want to reserve L1 memory for other uses.
++
++config BFIN_TX_DESC_NUM
++ int "Number of transmit buffer packets"
++ depends on BFIN_MAC
++ range 6 10 if BFIN_MAC_USE_L1
++ range 10 100
++ default "10"
++ help
++ Set the number of buffer packets used in driver.
++
++config BFIN_RX_DESC_NUM
++ int "Number of receive buffer packets"
++ depends on BFIN_MAC
++ range 20 100 if BFIN_MAC_USE_L1
++ range 20 800
++ default "20"
++ help
++ Set the number of buffer packets used in driver.
++
++config BFIN_MAC_RMII
++ bool "RMII PHY Interface"
++ depends on BFIN_MAC
++ default y if BFIN527_EZKIT
++ default n if BFIN537_STAMP
++ help
++ Use Reduced PHY MII Interface
++
++config BFIN_MAC_USE_HWSTAMP
++ bool "Use IEEE 1588 hwstamp"
++ depends on BFIN_MAC && BF518
++ default y
++ help
++ To support the IEEE 1588 Precision Time Protocol (PTP), select y here
++
++config SMC9194
++ tristate "SMC 9194 support"
++ depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN)
++ select CRC32
++ ---help---
++ This is support for the SMC9xxx based Ethernet cards. Choose this
++ option if you have a DELL laptop with the docking station, or
++ another SMC9192/9194 based chipset. Say Y if you want it compiled
++ into the kernel, and read the file
++ <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
++ available from <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called smc9194.
++
++config SMC91X
++ tristate "SMC 91C9x/91C1xxx support"
++ select CRC32
++ select MII
++ depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || \
++ MIPS || BLACKFIN || MN10300 || COLDFIRE
++ help
++ This is a driver for SMC's 91x series of Ethernet chipsets,
++ including the SMC91C94 and the SMC91C111. Say Y if you want it
++ compiled into the kernel, and read the file
++ <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
++ available from <http://www.linuxdoc.org/docs.html#howto>.
++
++ This driver is also available as a module ( = code which can be
++ inserted in and removed from the running kernel whenever you want).
++ The module will be called smc91x. If you want to compile it as a
++ module, say M here and read <file:Documentation/kbuild/modules.txt>.
++
++config NET_NETX
++ tristate "NetX Ethernet support"
++ select MII
++ depends on ARCH_NETX
++ help
++ This is support for the Hilscher netX builtin Ethernet ports
++
++ To compile this driver as a module, choose M here. The module
++ will be called netx-eth.
++
++config TI_DAVINCI_EMAC
++ tristate "TI DaVinci EMAC Support"
++ depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
++ select PHYLIB
++ help
++ This driver supports TI's DaVinci Ethernet .
++
++ To compile this driver as a module, choose M here: the module
++ will be called davinci_emac_driver. This is recommended.
++
++config DM9000
++ tristate "DM9000 support"
++ depends on ARM || BLACKFIN || MIPS
++ select CRC32
++ select MII
++ ---help---
++ Support for DM9000 chipset.
++
++ To compile this driver as a module, choose M here. The module
++ will be called dm9000.
++
++config DM9000_DEBUGLEVEL
++ int "DM9000 maximum debug level"
++ depends on DM9000
++ default 4
++ help
++ The maximum level of debugging code compiled into the DM9000
++ driver.
++
++config DM9000_FORCE_SIMPLE_PHY_POLL
++ bool "Force simple NSR based PHY polling"
++ depends on DM9000
++ ---help---
++ This configuration forces the DM9000 to use the NSR's LinkStatus
++ bit to determine if the link is up or down instead of the more
++ costly MII PHY reads. Note, this will not work if the chip is
++ operating with an external PHY.
++
++config ENC28J60
++ tristate "ENC28J60 support"
++ depends on EXPERIMENTAL && SPI && NET_ETHERNET
++ select CRC32
++ ---help---
++ Support for the Microchip EN28J60 ethernet chip.
++
++ To compile this driver as a module, choose M here. The module will be
++ called enc28j60.
++
++config ENC28J60_WRITEVERIFY
++ bool "Enable write verify"
++ depends on ENC28J60
++ ---help---
++ Enable the verify after the buffer write useful for debugging purpose.
++ If unsure, say N.
++
++config ETHOC
++ tristate "OpenCores 10/100 Mbps Ethernet MAC support"
++ depends on NET_ETHERNET && HAS_IOMEM && HAS_DMA
++ select MII
++ select PHYLIB
++ select CRC32
++ select BITREVERSE
++ help
++ Say Y here if you want to use the OpenCores 10/100 Mbps Ethernet MAC.
++
++config GRETH
++ tristate "Aeroflex Gaisler GRETH Ethernet MAC support"
++ depends on SPARC
++ select PHYLIB
++ select CRC32
++ help
++ Say Y here if you want to use the Aeroflex Gaisler GRETH Ethernet MAC.
++
++config SMC911X
++ tristate "SMSC LAN911[5678] support"
++ select CRC32
++ select MII
++ depends on ARM || SUPERH
++ help
++ This is a driver for SMSC's LAN911x series of Ethernet chipsets
++ including the new LAN9115, LAN9116, LAN9117, and LAN9118.
++ Say Y if you want it compiled into the kernel,
++ and read the Ethernet-HOWTO, available from
++ <http://www.linuxdoc.org/docs.html#howto>.
++
++ This driver is also available as a module. The module will be
++ called smc911x. If you want to compile it as a module, say M
++ here and read <file:Documentation/kbuild/modules.txt>
++
++config SMSC911X
++ tristate "SMSC LAN911x/LAN921x families embedded ethernet support"
++ depends on ARM || SUPERH || BLACKFIN || MIPS
++ select CRC32
++ select MII
++ select PHYLIB
++ ---help---
++ Say Y here if you want support for SMSC LAN911x and LAN921x families
++ of ethernet controllers.
++
++ To compile this driver as a module, choose M here and read
++ <file:Documentation/networking/net-modules.txt>. The module
++ will be called smsc911x.
++
++config NET_VENDOR_RACAL
++ bool "Racal-Interlan (Micom) NI cards"
++ depends on ISA
++ help
++ If you have a network (Ethernet) card belonging to this class, such
++ as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO,
++ available from <http://www.tldp.org/docs.html#howto>.
++
++ Note that the answer to this question doesn't directly affect the
++ kernel: saying N will just cause the configurator to skip all
++ the questions about NI cards. If you say Y, you will be asked for
++ your specific card in the following questions.
++
++config NI5010
++ tristate "NI5010 support (EXPERIMENTAL)"
++ depends on NET_VENDOR_RACAL && ISA && EXPERIMENTAL && BROKEN_ON_SMP
++ ---help---
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>. Note that this is still
++ experimental code.
++
++ To compile this driver as a module, choose M here. The module
++ will be called ni5010.
++
++config NI52
++ tristate "NI5210 support"
++ depends on NET_VENDOR_RACAL && ISA
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called ni52.
++
++config NI65
++ tristate "NI6510 support"
++ depends on NET_VENDOR_RACAL && ISA && ISA_DMA_API
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called ni65.
++
++config DNET
++ tristate "Dave ethernet support (DNET)"
++ depends on NET_ETHERNET && HAS_IOMEM
++ select PHYLIB
++ help
++ The Dave ethernet interface (DNET) is found on Qong Board FPGA.
++ Say Y to include support for the DNET chip.
++
++ To compile this driver as a module, choose M here: the module
++ will be called dnet.
++
++source "drivers/net/tulip/Kconfig"
++
++config AT1700
++ tristate "AT1700/1720 support (EXPERIMENTAL)"
++ depends on (ISA || MCA_LEGACY) && EXPERIMENTAL
++ select CRC32
++ ---help---
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called at1700.
++
++config DEPCA
++ tristate "DEPCA, DE10x, DE200, DE201, DE202, DE422 support"
++ depends on ISA || EISA || MCA
++ select CRC32
++ ---help---
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto> as well as
++ <file:drivers/net/depca.c>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called depca.
++
++config HP100
++ tristate "HP 10/100VG PCLAN (ISA, EISA, PCI) support"
++ depends on ISA || EISA || PCI
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called hp100.
++
++config NET_ISA
++ bool "Other ISA cards"
++ depends on ISA
++ ---help---
++ If your network (Ethernet) card hasn't been mentioned yet and its
++ bus system (that's the way the cards talks to the other components
++ of your computer) is ISA (as opposed to EISA, VLB or PCI), say Y.
++ Make sure you know the name of your card. Read the Ethernet-HOWTO,
++ available from <http://www.tldp.org/docs.html#howto>.
++
++ If unsure, say Y.
++
++ Note that the answer to this question doesn't directly affect the
++ kernel: saying N will just cause the configurator to skip all
++ the remaining ISA network card questions. If you say Y, you will be
++ asked for your specific card in the following questions.
++
++config E2100
++ tristate "Cabletron E21xx support"
++ depends on NET_ISA
++ select CRC32
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called e2100.
++
++config EWRK3
++ tristate "EtherWORKS 3 (DE203, DE204, DE205) support"
++ depends on NET_ISA
++ select CRC32
++ ---help---
++ This driver supports the DE203, DE204 and DE205 network (Ethernet)
++ cards. If this is for you, say Y and read
++ <file:Documentation/networking/ewrk3.txt> in the kernel source as
++ well as the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called ewrk3.
++
++config EEXPRESS
++ tristate "EtherExpress 16 support"
++ depends on NET_ISA
++ ---help---
++ If you have an EtherExpress16 network (Ethernet) card, say Y and
++ read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>. Note that the Intel
++ EtherExpress16 card used to be regarded as a very poor choice
++ because the driver was very unreliable. We now have a new driver
++ that should do better.
++
++ To compile this driver as a module, choose M here. The module
++ will be called eexpress.
++
++config EEXPRESS_PRO
++ tristate "EtherExpressPro support/EtherExpress 10 (i82595) support"
++ depends on NET_ISA
++ ---help---
++ If you have a network (Ethernet) card of this type, say Y. This
++ driver supports Intel i82595{FX,TX} based boards. Note however
++ that the EtherExpress PRO/100 Ethernet card has its own separate
++ driver. Please read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called eepro.
++
++config HPLAN_PLUS
++ tristate "HP PCLAN+ (27247B and 27252A) support"
++ depends on NET_ISA
++ select CRC32
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called hp-plus.
++
++config HPLAN
++ tristate "HP PCLAN (27245 and other 27xxx series) support"
++ depends on NET_ISA
++ select CRC32
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called hp.
++
++config LP486E
++ tristate "LP486E on board Ethernet"
++ depends on NET_ISA
++ help
++ Say Y here to support the 82596-based on-board Ethernet controller
++ for the Panther motherboard, which is one of the two shipped in the
++ Intel Professional Workstation.
++
++config ETH16I
++ tristate "ICL EtherTeam 16i/32 support"
++ depends on NET_ISA
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called eth16i.
++
++config NE2000
++ tristate "NE2000/NE1000 support"
++ depends on NET_ISA || (Q40 && m) || M32R || MACH_TX49XX
++ select CRC32
++ ---help---
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>. Many Ethernet cards
++ without a specific driver are compatible with NE2000.
++
++ If you have a PCI NE2000 card however, say N here and Y to "PCI
++ NE2000 and clone support" under "EISA, VLB, PCI and on board
++ controllers" below. If you have a NE2000 card and are running on
++ an MCA system (a bus system used on some IBM PS/2 computers and
++ laptops), say N here and Y to "NE/2 (ne2000 MCA version) support",
++ below.
++
++ To compile this driver as a module, choose M here. The module
++ will be called ne.
++
++config ZNET
++ tristate "Zenith Z-Note support (EXPERIMENTAL)"
++ depends on NET_ISA && EXPERIMENTAL && ISA_DMA_API
++ help
++ The Zenith Z-Note notebook computer has a built-in network
++ (Ethernet) card, and this is the Linux driver for it. Note that the
++ IBM Thinkpad 300 is compatible with the Z-Note and is also supported
++ by this driver. Read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++config SEEQ8005
++ tristate "SEEQ8005 support (EXPERIMENTAL)"
++ depends on NET_ISA && EXPERIMENTAL
++ help
++ This is a driver for the SEEQ 8005 network (Ethernet) card. If this
++ is for you, read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called seeq8005.
++
++config NE2_MCA
++ tristate "NE/2 (ne2000 MCA version) support"
++ depends on MCA_LEGACY
++ select CRC32
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called ne2.
++
++config IBMLANA
++ tristate "IBM LAN Adapter/A support"
++ depends on MCA
++ ---help---
++ This is a Micro Channel Ethernet adapter. You need to set
++ CONFIG_MCA to use this driver. It is both available as an in-kernel
++ driver and as a module.
++
++ To compile this driver as a module, choose M here. The only
++ currently supported card is the IBM LAN Adapter/A for Ethernet. It
++ will both support 16K and 32K memory windows, however a 32K window
++ gives a better security against packet losses. Usage of multiple
++ boards with this driver should be possible, but has not been tested
++ up to now due to lack of hardware.
++
++config IBMVETH
++ tristate "IBM LAN Virtual Ethernet support"
++ depends on PPC_PSERIES
++ ---help---
++ This driver supports virtual ethernet adapters on newer IBM iSeries
++ and pSeries systems.
++
++ To compile this driver as a module, choose M here. The module will
++ be called ibmveth.
++
++source "drivers/net/ibm_newemac/Kconfig"
++
++config NET_PCI
++ bool "EISA, VLB, PCI and on board controllers"
++ depends on ISA || EISA || PCI
++ help
++ This is another class of network cards which attach directly to the
++ bus. If you have one of those, say Y and read the Ethernet-HOWTO,
++ available from <http://www.tldp.org/docs.html#howto>.
++
++ Note that the answer to this question doesn't directly affect the
++ kernel: saying N will just cause the configurator to skip all
++ the questions about this class of network cards. If you say Y, you
++ will be asked for your specific card in the following questions. If
++ you are unsure, say Y.
++
++config PCNET32
++ tristate "AMD PCnet32 PCI support"
++ depends on NET_PCI && PCI
++ select CRC32
++ select MII
++ help
++ If you have a PCnet32 or PCnetPCI based network (Ethernet) card,
++ answer Y here and read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called pcnet32.
++
++config AMD8111_ETH
++ tristate "AMD 8111 (new PCI lance) support"
++ depends on NET_PCI && PCI
++ select CRC32
++ select MII
++ help
++ If you have an AMD 8111-based PCI lance ethernet card,
++ answer Y here and read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called amd8111e.
++
++config ADAPTEC_STARFIRE
++ tristate "Adaptec Starfire/DuraLAN support"
++ depends on NET_PCI && PCI
++ select CRC32
++ select MII
++ help
++ Say Y here if you have an Adaptec Starfire (or DuraLAN) PCI network
++ adapter. The DuraLAN chip is used on the 64 bit PCI boards from
++ Adaptec e.g. the ANA-6922A. The older 32 bit boards use the tulip
++ driver.
++
++ To compile this driver as a module, choose M here: the module
++ will be called starfire. This is recommended.
++
++config AC3200
++ tristate "Ansel Communications EISA 3200 support (EXPERIMENTAL)"
++ depends on NET_PCI && (ISA || EISA) && EXPERIMENTAL
++ select CRC32
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called ac3200.
++
++config KSZ884X_PCI
++ tristate "Micrel KSZ8841/2 PCI"
++ depends on NET_PCI && PCI
++ select MII
++ select CRC32
++ help
++ This PCI driver is for Micrel KSZ8841/KSZ8842 PCI Ethernet chip.
++
++ To compile this driver as a module, choose M here. The module
++ will be called ksz884x.
++
++config APRICOT
++ tristate "Apricot Xen-II on board Ethernet"
++ depends on NET_PCI && ISA
++ help
++ If you have a network (Ethernet) controller of this type, say Y and
++ read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called apricot.
++
++config B44
++ tristate "Broadcom 440x/47xx ethernet support"
++ depends on SSB_POSSIBLE && HAS_DMA
++ select SSB
++ select MII
++ help
++ If you have a network (Ethernet) controller of this type, say Y
++ or M and read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called b44.
++
++# Auto-select SSB PCI-HOST support, if possible
++config B44_PCI_AUTOSELECT
++ bool
++ depends on B44 && SSB_PCIHOST_POSSIBLE
++ select SSB_PCIHOST
++ default y
++
++# Auto-select SSB PCICORE driver, if possible
++config B44_PCICORE_AUTOSELECT
++ bool
++ depends on B44 && SSB_DRIVER_PCICORE_POSSIBLE
++ select SSB_DRIVER_PCICORE
++ default y
++
++config B44_PCI
++ bool
++ depends on B44_PCI_AUTOSELECT && B44_PCICORE_AUTOSELECT
++ default y
++
++config FORCEDETH
++ tristate "nForce Ethernet support"
++ depends on NET_PCI && PCI
++ help
++ If you have a network (Ethernet) controller of this type, say Y and
++ read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called forcedeth.
++
++config CS89x0
++ tristate "CS89x0 support"
++ depends on NET_ETHERNET && (ISA || EISA || MACH_IXDP2351 \
++ || ARCH_IXDP2X01 || ARCH_PNX010X || MACH_MX31ADS)
++ ---help---
++ Support for CS89x0 chipset based Ethernet cards. If you have a
++ network (Ethernet) card of this type, say Y and read the
++ Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto> as well as
++ <file:Documentation/networking/cs89x0.txt>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called cs89x0.
++
++config CS89x0_NONISA_IRQ
++ def_bool y
++ depends on CS89x0 != n
++ depends on MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X || MACH_MX31ADS
++
++config TC35815
++ tristate "TOSHIBA TC35815 Ethernet support"
++ depends on NET_PCI && PCI && MIPS
++ select PHYLIB
++
++config E100
++ tristate "Intel(R) PRO/100+ support"
++ depends on NET_PCI && PCI
++ select MII
++ ---help---
++ This driver supports Intel(R) PRO/100 family of adapters.
++ To verify that your adapter is supported, find the board ID number
++ on the adapter. Look for a label that has a barcode and a number
++ in the format 123456-001 (six digits hyphen three digits).
++
++ Use the above information and the Adapter & Driver ID Guide at:
++
++ <http://support.intel.com/support/network/adapter/pro100/21397.htm>
++
++ to identify the adapter.
++
++ For the latest Intel PRO/100 network driver for Linux, see:
++
++ <http://appsr.intel.com/scripts-df/support_intel.asp>
++
++ More specific information on configuring the driver is in
++ <file:Documentation/networking/e100.txt>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called e100.
++
++config LNE390
++ tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)"
++ depends on NET_PCI && EISA && EXPERIMENTAL
++ select CRC32
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called lne390.
++
++config FEALNX
++ tristate "Myson MTD-8xx PCI Ethernet support"
++ depends on NET_PCI && PCI
++ select CRC32
++ select MII
++ help
++ Say Y here to support the Mysom MTD-800 family of PCI-based Ethernet
++ cards. Specifications and data at
++ <http://www.myson.com.hk/mtd/datasheet/>.
++
++config NATSEMI
++ tristate "National Semiconductor DP8381x series PCI Ethernet support"
++ depends on NET_PCI && PCI
++ select CRC32
++ help
++ This driver is for the National Semiconductor DP83810 series,
++ which is used in cards from PureData, NetGear, Linksys
++ and others, including the 83815 chip.
++ More specific information and updates are available from
++ <http://www.scyld.com/network/natsemi.html>.
++
++config NE2K_PCI
++ tristate "PCI NE2000 and clones support (see help)"
++ depends on NET_PCI && PCI
++ select CRC32
++ ---help---
++ This driver is for NE2000 compatible PCI cards. It will not work
++ with ISA NE2000 cards (they have their own driver, "NE2000/NE1000
++ support" below). If you have a PCI NE2000 network (Ethernet) card,
++ say Y and read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ This driver also works for the following NE2000 clone cards:
++ RealTek RTL-8029 Winbond 89C940 Compex RL2000 KTI ET32P2
++ NetVin NV5000SC Via 86C926 SureCom NE34 Winbond
++ Holtek HT80232 Holtek HT80229
++
++ To compile this driver as a module, choose M here. The module
++ will be called ne2k-pci.
++
++config NE3210
++ tristate "Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)"
++ depends on NET_PCI && EISA && EXPERIMENTAL
++ select CRC32
++ ---help---
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>. Note that this driver
++ will NOT WORK for NE3200 cards as they are completely different.
++
++ To compile this driver as a module, choose M here. The module
++ will be called ne3210.
++
++config ES3210
++ tristate "Racal-Interlan EISA ES3210 support (EXPERIMENTAL)"
++ depends on NET_PCI && EISA && EXPERIMENTAL
++ select CRC32
++ help
++ If you have a network (Ethernet) card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called es3210.
++
++config 8139CP
++ tristate "RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support (EXPERIMENTAL)"
++ depends on NET_PCI && PCI && EXPERIMENTAL
++ select CRC32
++ select MII
++ help
++ This is a driver for the Fast Ethernet PCI network cards based on
++ the RTL8139C+ chips. If you have one of those, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here: the module
++ will be called 8139cp. This is recommended.
++
++config 8139TOO
++ tristate "RealTek RTL-8129/8130/8139 PCI Fast Ethernet Adapter support"
++ depends on NET_PCI && PCI
++ select CRC32
++ select MII
++ ---help---
++ This is a driver for the Fast Ethernet PCI network cards based on
++ the RTL 8129/8130/8139 chips. If you have one of those, say Y and
++ read the Ethernet-HOWTO <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here: the module
++ will be called 8139too. This is recommended.
++
++config 8139TOO_PIO
++ bool "Use PIO instead of MMIO"
++ default y
++ depends on 8139TOO
++ help
++ This instructs the driver to use programmed I/O ports (PIO) instead
++ of PCI shared memory (MMIO). This can possibly solve some problems
++ in case your mainboard has memory consistency issues. If unsure,
++ say N.
++
++config 8139TOO_TUNE_TWISTER
++ bool "Support for uncommon RTL-8139 rev. K (automatic channel equalization)"
++ depends on 8139TOO
++ help
++ This implements a function which might come in handy in case you
++ are using low quality on long cabling. It is required for RealTek
++ RTL-8139 revision K boards, and totally unused otherwise. It tries
++ to match the transceiver to the cable characteristics. This is
++ experimental since hardly documented by the manufacturer.
++ If unsure, say Y.
++
++config 8139TOO_8129
++ bool "Support for older RTL-8129/8130 boards"
++ depends on 8139TOO
++ help
++ This enables support for the older and uncommon RTL-8129 and
++ RTL-8130 chips, which support MII via an external transceiver,
++ instead of an internal one. Disabling this option will save some
++ memory by making the code size smaller. If unsure, say Y.
++
++config 8139_OLD_RX_RESET
++ bool "Use older RX-reset method"
++ depends on 8139TOO
++ help
++ The 8139too driver was recently updated to contain a more rapid
++ reset sequence, in the face of severe receive errors. This "new"
++ RX-reset method should be adequate for all boards. But if you
++ experience problems, you can enable this option to restore the
++ old RX-reset behavior. If unsure, say N.
++
++config R6040
++ tristate "RDC R6040 Fast Ethernet Adapter support"
++ depends on NET_PCI && PCI
++ select CRC32
++ select MII
++ help
++ This is a driver for the R6040 Fast Ethernet MACs found in the
++ the RDC R-321x System-on-chips.
++
++ To compile this driver as a module, choose M here: the module
++ will be called r6040. This is recommended.
++
++config SIS900
++ tristate "SiS 900/7016 PCI Fast Ethernet Adapter support"
++ depends on NET_PCI && PCI
++ select CRC32
++ select MII
++ ---help---
++ This is a driver for the Fast Ethernet PCI network cards based on
++ the SiS 900 and SiS 7016 chips. The SiS 900 core is also embedded in
++ SiS 630 and SiS 540 chipsets.
++
++ This driver also supports AMD 79C901 HomePNA so that you can use
++ your phone line as a network cable.
++
++ To compile this driver as a module, choose M here: the module
++ will be called sis900. This is recommended.
++
++config EPIC100
++ tristate "SMC EtherPower II"
++ depends on NET_PCI && PCI
++ select CRC32
++ select MII
++ help
++ This driver is for the SMC EtherPower II 9432 PCI Ethernet NIC,
++ which is based on the SMC83c17x (EPIC/100).
++ More specific information and updates are available from
++ <http://www.scyld.com/network/epic100.html>.
++
++config SMSC9420
++ tristate "SMSC LAN9420 PCI ethernet adapter support"
++ depends on NET_PCI && PCI
++ select CRC32
++ select PHYLIB
++ select SMSC_PHY
++ help
++ This is a driver for SMSC's LAN9420 PCI ethernet adapter.
++ Say Y if you want it compiled into the kernel,
++ and read the Ethernet-HOWTO, available from
++ <http://www.linuxdoc.org/docs.html#howto>.
++
++ This driver is also available as a module. The module will be
++ called smsc9420. If you want to compile it as a module, say M
++ here and read <file:Documentation/kbuild/modules.txt>
++
++config SUNDANCE
++ tristate "Sundance Alta support"
++ depends on NET_PCI && PCI
++ select CRC32
++ select MII
++ help
++ This driver is for the Sundance "Alta" chip.
++ More specific information and updates are available from
++ <http://www.scyld.com/network/sundance.html>.
++
++config SUNDANCE_MMIO
++ bool "Use MMIO instead of PIO"
++ depends on SUNDANCE
++ help
++ Enable memory-mapped I/O for interaction with Sundance NIC registers.
++ Do NOT enable this by default, PIO (enabled when MMIO is disabled)
++ is known to solve bugs on certain chips.
++
++ If unsure, say N.
++
++config TLAN
++ tristate "TI ThunderLAN support"
++ depends on NET_PCI && (PCI || EISA)
++ ---help---
++ If you have a PCI Ethernet network card based on the ThunderLAN chip
++ which is supported by this driver, say Y and read the
++ Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ Devices currently supported by this driver are Compaq Netelligent,
++ Compaq NetFlex and Olicom cards. Please read the file
++ <file:Documentation/networking/tlan.txt> for more details.
++
++ To compile this driver as a module, choose M here. The module
++ will be called tlan.
++
++ Please email feedback to <torben.mathiasen at compaq.com>.
++
++config KS8842
++ tristate "Micrel KSZ8842"
++ depends on HAS_IOMEM
++ help
++ This platform driver is for Micrel KSZ8842 / KS8842
++ 2-port ethernet switch chip (managed, VLAN, QoS).
++
++config KS8851
++ tristate "Micrel KS8851 SPI"
++ depends on SPI
++ select MII
++ select CRC32
++ help
++ SPI driver for Micrel KS8851 SPI attached network chip.
++
++config KS8851_MLL
++ tristate "Micrel KS8851 MLL"
++ depends on HAS_IOMEM
++ select MII
++ help
++ This platform driver is for Micrel KS8851 Address/data bus
++ multiplexed network chip.
++
++config VIA_RHINE
++ tristate "VIA Rhine support"
++ depends on NET_PCI && PCI
++ select CRC32
++ select MII
++ help
++ If you have a VIA "Rhine" based network card (Rhine-I (VT86C100A),
++ Rhine-II (VT6102), or Rhine-III (VT6105)), say Y here. Rhine-type
++ Ethernet functions can also be found integrated on South Bridges
++ (e.g. VT8235).
++
++ To compile this driver as a module, choose M here. The module
++ will be called via-rhine.
++
++config VIA_RHINE_MMIO
++ bool "Use MMIO instead of PIO"
++ depends on VIA_RHINE
++ help
++ This instructs the driver to use PCI shared memory (MMIO) instead of
++ programmed I/O ports (PIO). Enabling this gives an improvement in
++ processing time in parts of the driver.
++
++ If unsure, say Y.
++
++config SC92031
++ tristate "Silan SC92031 PCI Fast Ethernet Adapter driver (EXPERIMENTAL)"
++ depends on NET_PCI && PCI && EXPERIMENTAL
++ select CRC32
++ ---help---
++ This is a driver for the Fast Ethernet PCI network cards based on
++ the Silan SC92031 chip (sometimes also called Rsltek 8139D). If you
++ have one of these, say Y here.
++
++ To compile this driver as a module, choose M here: the module
++ will be called sc92031. This is recommended.
++
++config CPMAC
++ tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)"
++ depends on NET_ETHERNET && EXPERIMENTAL && AR7
++ select PHYLIB
++ help
++ TI AR7 CPMAC Ethernet support
++
++config NET_POCKET
++ bool "Pocket and portable adapters"
++ depends on PARPORT
++ ---help---
++ Cute little network (Ethernet) devices which attach to the parallel
++ port ("pocket adapters"), commonly used with laptops. If you have
++ one of those, say Y and read the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ If you want to plug a network (or some other) card into the PCMCIA
++ (or PC-card) slot of your laptop instead (PCMCIA is the standard for
++ credit card size extension cards used by all modern laptops), you
++ need the pcmcia-cs package (location contained in the file
++ <file:Documentation/Changes>) and you can say N here.
++
++ Laptop users should read the Linux Laptop home page at
++ <http://www.linux-on-laptops.com/> or
++ Tuxmobil - Linux on Mobile Computers at <http://www.tuxmobil.org/>.
++
++ Note that the answer to this question doesn't directly affect the
++ kernel: saying N will just cause the configurator to skip all
++ the questions about this class of network devices. If you say Y, you
++ will be asked for your specific device in the following questions.
++
++config ATP
++ tristate "AT-LAN-TEC/RealTek pocket adapter support"
++ depends on NET_POCKET && PARPORT && X86
++ select CRC32
++ ---help---
++ This is a network (Ethernet) device which attaches to your parallel
++ port. Read <file:drivers/net/atp.c> as well as the Ethernet-HOWTO,
++ available from <http://www.tldp.org/docs.html#howto>, if you
++ want to use this. If you intend to use this driver, you should have
++ said N to the "Parallel printer support", because the two drivers
++ don't like each other.
++
++ To compile this driver as a module, choose M here: the module
++ will be called atp.
++
++config DE600
++ tristate "D-Link DE600 pocket adapter support"
++ depends on NET_POCKET && PARPORT
++ ---help---
++ This is a network (Ethernet) device which attaches to your parallel
++ port. Read <file:Documentation/networking/DLINK.txt> as well as the
++ Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>, if you want to use
++ this. It is possible to have several devices share a single parallel
++ port and it is safe to compile the corresponding drivers into the
++ kernel.
++
++ To compile this driver as a module, choose M here: the module
++ will be called de600.
++
++config DE620
++ tristate "D-Link DE620 pocket adapter support"
++ depends on NET_POCKET && PARPORT
++ ---help---
++ This is a network (Ethernet) device which attaches to your parallel
++ port. Read <file:Documentation/networking/DLINK.txt> as well as the
++ Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>, if you want to use
++ this. It is possible to have several devices share a single parallel
++ port and it is safe to compile the corresponding drivers into the
++ kernel.
++
++ To compile this driver as a module, choose M here: the module
++ will be called de620.
++
++config SGISEEQ
++ tristate "SGI Seeq ethernet controller support"
++ depends on SGI_HAS_SEEQ
++ help
++ Say Y here if you have an Seeq based Ethernet network card. This is
++ used in many Silicon Graphics machines.
++
++config DECLANCE
++ tristate "DEC LANCE ethernet controller support"
++ depends on MACH_DECSTATION
++ select CRC32
++ help
++ This driver is for the series of Ethernet controllers produced by
++ DEC (now Compaq) based on the AMD Lance chipset, including the
++ DEPCA series. (This chipset is better known via the NE2100 cards.)
++
++config 68360_ENET
++ bool "Motorola 68360 ethernet controller"
++ depends on M68360
++ help
++ Say Y here if you want to use the built-in ethernet controller of
++ the Motorola 68360 processor.
++
++config FEC
++ bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
++ depends on M523x || M527x || M5272 || M528x || M520x || M532x || \
++ MACH_MX27 || ARCH_MX35 || ARCH_MX25 || ARCH_MX5
++ select PHYLIB
++ help
++ Say Y here if you want to use the built-in 10/100 Fast ethernet
++ controller on some Motorola ColdFire and Freescale i.MX processors.
++
++config FEC2
++ bool "Second FEC ethernet controller (on some ColdFire CPUs)"
++ depends on FEC
++ help
++ Say Y here if you want to use the second built-in 10/100 Fast
++ ethernet controller on some Motorola ColdFire processors.
++
++config FEC_MPC52xx
++ tristate "MPC52xx FEC driver"
++ depends on PPC_MPC52xx && PPC_BESTCOMM
++ select CRC32
++ select PHYLIB
++ select PPC_BESTCOMM_FEC
++ ---help---
++ This option enables support for the MPC5200's on-chip
++ Fast Ethernet Controller
++ If compiled as module, it will be called fec_mpc52xx.
++
++config FEC_MPC52xx_MDIO
++ bool "MPC52xx FEC MDIO bus driver"
++ depends on FEC_MPC52xx
++ default y
++ ---help---
++ The MPC5200's FEC can connect to the Ethernet either with
++ an external MII PHY chip or 10 Mbps 7-wire interface
++ (Motorola? industry standard).
++ If your board uses an external PHY connected to FEC, enable this.
++ If not sure, enable.
++ If compiled as module, it will be called fec_mpc52xx_phy.
++
++config NE_H8300
++ tristate "NE2000 compatible support for H8/300"
++ depends on H8300
++ help
++ Say Y here if you want to use the NE2000 compatible
++ controller on the Renesas H8/300 processor.
++
++config ATL2
++ tristate "Atheros L2 Fast Ethernet support"
++ depends on PCI
++ select CRC32
++ select MII
++ help
++ This driver supports the Atheros L2 fast ethernet adapter.
++
++ To compile this driver as a module, choose M here. The module
++ will be called atl2.
++
++config XILINX_EMACLITE
++ tristate "Xilinx 10/100 Ethernet Lite support"
++ depends on PPC32 || MICROBLAZE
++ select PHYLIB
++ help
++ This driver supports the 10/100 Ethernet Lite from Xilinx.
++
++config BCM63XX_ENET
++ tristate "Broadcom 63xx internal mac support"
++ depends on BCM63XX
++ select MII
++ select PHYLIB
++ help
++ This driver supports the ethernet MACs in the Broadcom 63xx
++ MIPS chipset family (BCM63XX).
++
++source "drivers/net/fs_enet/Kconfig"
++
++source "drivers/net/octeon/Kconfig"
++
++endif # NET_ETHERNET
++
++#
++# Gigabit Ethernet
++#
++
++menuconfig NETDEV_1000
++ bool "Ethernet (1000 Mbit)"
++ depends on !UML
++ default y
++ ---help---
++ Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common
++ type of Local Area Network (LAN) in universities and companies.
++
++ Say Y here to get to see options for Gigabit Ethernet drivers.
++ This option alone does not add any kernel code.
++ Note that drivers supporting both 100 and 1000 MBit may be listed
++ under "Ethernet (10 or 100MBit)" instead.
++
++ If you say N, all options in this submenu will be skipped and disabled.
++
++if NETDEV_1000
++
++config ACENIC
++ tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support"
++ depends on PCI
++ ---help---
++ Say Y here if you have an Alteon AceNIC, 3Com 3C985(B), NetGear
++ GA620, SGI Gigabit or Farallon PN9000-SX PCI Gigabit Ethernet
++ adapter. The driver allows for using the Jumbo Frame option (9000
++ bytes/frame) however it requires that your switches can handle this
++ as well. To enable Jumbo Frames, add `mtu 9000' to your ifconfig
++ line.
++
++ To compile this driver as a module, choose M here: the
++ module will be called acenic.
++
++config ACENIC_OMIT_TIGON_I
++ bool "Omit support for old Tigon I based AceNICs"
++ depends on ACENIC
++ help
++ Say Y here if you only have Tigon II based AceNICs and want to leave
++ out support for the older Tigon I based cards which are no longer
++ being sold (ie. the original Alteon AceNIC and 3Com 3C985 (non B
++ version)). This will reduce the size of the driver object by
++ app. 100KB. If you are not sure whether your card is a Tigon I or a
++ Tigon II, say N here.
++
++ The safe and default value for this is N.
++
++config DL2K
++ tristate "DL2000/TC902x-based Gigabit Ethernet support"
++ depends on PCI
++ select CRC32
++ help
++ This driver supports DL2000/TC902x-based Gigabit ethernet cards,
++ which includes
++ D-Link DGE-550T Gigabit Ethernet Adapter.
++ D-Link DL2000-based Gigabit Ethernet Adapter.
++ Sundance/Tamarack TC902x Gigabit Ethernet Adapter.
++
++ To compile this driver as a module, choose M here: the
++ module will be called dl2k.
++
++config E1000
++ tristate "Intel(R) PRO/1000 Gigabit Ethernet support"
++ depends on PCI
++ ---help---
++ This driver supports Intel(R) PRO/1000 gigabit ethernet family of
++ adapters. For more information on how to identify your adapter, go
++ to the Adapter & Driver ID Guide at:
++
++ <http://support.intel.com/support/network/adapter/pro100/21397.htm>
++
++ For general information and support, go to the Intel support
++ website at:
++
++ <http://support.intel.com>
++
++ More specific information on configuring the driver is in
++ <file:Documentation/networking/e1000.txt>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called e1000.
++
++config E1000E
++ tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
++ depends on PCI && (!SPARC32 || BROKEN)
++ ---help---
++ This driver supports the PCI-Express Intel(R) PRO/1000 gigabit
++ ethernet family of adapters. For PCI or PCI-X e1000 adapters,
++ use the regular e1000 driver For more information on how to
++ identify your adapter, go to the Adapter & Driver ID Guide at:
++
++ <http://support.intel.com/support/network/adapter/pro100/21397.htm>
++
++ For general information and support, go to the Intel support
++ website at:
++
++ <http://support.intel.com>
++
++ To compile this driver as a module, choose M here. The module
++ will be called e1000e.
++
++config IP1000
++ tristate "IP1000 Gigabit Ethernet support"
++ depends on PCI && EXPERIMENTAL
++ select MII
++ ---help---
++ This driver supports IP1000 gigabit Ethernet cards.
++
++ To compile this driver as a module, choose M here: the module
++ will be called ipg. This is recommended.
++
++config IGB
++ tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
++ depends on PCI
++ ---help---
++ This driver supports Intel(R) 82575/82576 gigabit ethernet family of
++ adapters. For more information on how to identify your adapter, go
++ to the Adapter & Driver ID Guide at:
++
++ <http://support.intel.com/support/network/adapter/pro100/21397.htm>
++
++ For general information and support, go to the Intel support
++ website at:
++
++ <http://support.intel.com>
++
++ More specific information on configuring the driver is in
++ <file:Documentation/networking/e1000.txt>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called igb.
++
++config IGB_DCA
++ bool "Direct Cache Access (DCA) Support"
++ default y
++ depends on IGB && DCA && !(IGB=y && DCA=m)
++ ---help---
++ Say Y here if you want to use Direct Cache Access (DCA) in the
++ driver. DCA is a method for warming the CPU cache before data
++ is used, with the intent of lessening the impact of cache misses.
++
++config IGBVF
++ tristate "Intel(R) 82576 Virtual Function Ethernet support"
++ depends on PCI
++ ---help---
++ This driver supports Intel(R) 82576 virtual functions. For more
++ information on how to identify your adapter, go to the Adapter &
++ Driver ID Guide at:
++
++ <http://support.intel.com/support/network/adapter/pro100/21397.htm>
++
++ For general information and support, go to the Intel support
++ website at:
++
++ <http://support.intel.com>
++
++ More specific information on configuring the driver is in
++ <file:Documentation/networking/e1000.txt>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called igbvf.
++
++source "drivers/net/ixp2000/Kconfig"
++
++config MYRI_SBUS
++ tristate "MyriCOM Gigabit Ethernet support"
++ depends on SBUS
++ help
++ This driver supports MyriCOM Sbus gigabit Ethernet cards.
++
++ To compile this driver as a module, choose M here: the module
++ will be called myri_sbus. This is recommended.
++
++config NS83820
++ tristate "National Semiconductor DP83820 support"
++ depends on PCI
++ help
++ This is a driver for the National Semiconductor DP83820 series
++ of gigabit ethernet MACs. Cards using this chipset include
++ the D-Link DGE-500T, PureData's PDP8023Z-TG, SMC's SMC9462TX,
++ SOHO-GA2000T, SOHO-GA2500T. The driver supports the use of
++ zero copy.
++
++config HAMACHI
++ tristate "Packet Engines Hamachi GNIC-II support"
++ depends on PCI
++ select MII
++ help
++ If you have a Gigabit Ethernet card of this type, say Y and read
++ the Ethernet-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>.
++
++ To compile this driver as a module, choose M here. The module will be
++ called hamachi.
++
++config YELLOWFIN
++ tristate "Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)"
++ depends on PCI && EXPERIMENTAL
++ select CRC32
++ ---help---
++ Say Y here if you have a Packet Engines G-NIC PCI Gigabit Ethernet
++ adapter or the SYM53C885 Ethernet controller. The Gigabit adapter is
++ used by the Beowulf Linux cluster project. See
++ <http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html> for more
++ information about this driver in particular and Beowulf in general.
++
++ To compile this driver as a module, choose M here: the module
++ will be called yellowfin. This is recommended.
++
++config R8169
++ tristate "Realtek 8169 gigabit ethernet support"
++ depends on PCI
++ select CRC32
++ select MII
++ ---help---
++ Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter.
++
++ To compile this driver as a module, choose M here: the module
++ will be called r8169. This is recommended.
++
++config R8169_VLAN
++ bool "VLAN support"
++ depends on R8169 && VLAN_8021Q
++ ---help---
++ Say Y here for the r8169 driver to support the functions required
++ by the kernel 802.1Q code.
++
++ If in doubt, say Y.
++
++config SB1250_MAC
++ tristate "SB1250 Gigabit Ethernet support"
++ depends on SIBYTE_SB1xxx_SOC
++ select PHYLIB
++ ---help---
++ This driver supports Gigabit Ethernet interfaces based on the
++ Broadcom SiByte family of System-On-a-Chip parts. They include
++ the BCM1120, BCM1125, BCM1125H, BCM1250, BCM1255, BCM1280, BCM1455
++ and BCM1480 chips.
++
++ To compile this driver as a module, choose M here: the module
++ will be called sb1250-mac.
++
++config SIS190
++ tristate "SiS190/SiS191 gigabit ethernet support"
++ depends on PCI
++ select CRC32
++ select MII
++ ---help---
++ Say Y here if you have a SiS 190 PCI Fast Ethernet adapter or
++ a SiS 191 PCI Gigabit Ethernet adapter. Both are expected to
++ appear in lan on motherboard designs which are based on SiS 965
++ and SiS 966 south bridge.
++
++ To compile this driver as a module, choose M here: the module
++ will be called sis190. This is recommended.
++
++config SKGE
++ tristate "New SysKonnect GigaEthernet support"
++ depends on PCI
++ select CRC32
++ ---help---
++ This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
++ and related Gigabit Ethernet adapters. It is a new smaller driver
++ with better performance and more complete ethtool support.
++
++ It does not support the link failover and network management
++ features that "portable" vendor supplied sk98lin driver does.
++
++ This driver supports adapters based on the original Yukon chipset:
++ Marvell 88E8001, Belkin F5D5005, CNet GigaCard, DLink DGE-530T,
++ Linksys EG1032/EG1064, 3Com 3C940/3C940B, SysKonnect SK-9871/9872.
++
++ It does not support the newer Yukon2 chipset: a separate driver,
++ sky2, is provided for Yukon2-based adapters.
++
++ To compile this driver as a module, choose M here: the module
++ will be called skge. This is recommended.
++
++config SKGE_DEBUG
++ bool "Debugging interface"
++ depends on SKGE && DEBUG_FS
++ help
++ This option adds the ability to dump driver state for debugging.
++ The file /sys/kernel/debug/skge/ethX displays the state of the internal
++ transmit and receive rings.
++
++ If unsure, say N.
++
++config SKY2
++ tristate "SysKonnect Yukon2 support"
++ depends on PCI
++ select CRC32
++ ---help---
++ This driver supports Gigabit Ethernet adapters based on the
++ Marvell Yukon 2 chipset:
++ Marvell 88E8021/88E8022/88E8035/88E8036/88E8038/88E8050/88E8052/
++ 88E8053/88E8055/88E8061/88E8062, SysKonnect SK-9E21D/SK-9S21
++
++ There is companion driver for the older Marvell Yukon and
++ Genesis based adapters: skge.
++
++ To compile this driver as a module, choose M here: the module
++ will be called sky2. This is recommended.
++
++config SKY2_DEBUG
++ bool "Debugging interface"
++ depends on SKY2 && DEBUG_FS
++ help
++ This option adds the ability to dump driver state for debugging.
++ The file /sys/kernel/debug/sky2/ethX displays the state of the internal
++ transmit and receive rings.
++
++ If unsure, say N.
++
++config VIA_VELOCITY
++ tristate "VIA Velocity support"
++ depends on PCI
++ select CRC32
++ select CRC_CCITT
++ select MII
++ help
++ If you have a VIA "Velocity" based network card say Y here.
++
++ To compile this driver as a module, choose M here. The module
++ will be called via-velocity.
++
++config TIGON3
++ tristate "Broadcom Tigon3 support"
++ depends on PCI
++ select PHYLIB
++ help
++ This driver supports Broadcom Tigon3 based gigabit Ethernet cards.
++
++ To compile this driver as a module, choose M here: the module
++ will be called tg3. This is recommended.
++
++config BNX2
++ tristate "Broadcom NetXtremeII support"
++ depends on PCI
++ select CRC32
++ select FW_LOADER
++ help
++ This driver supports Broadcom NetXtremeII gigabit Ethernet cards.
++
++ To compile this driver as a module, choose M here: the module
++ will be called bnx2. This is recommended.
++
++config CNIC
++ tristate "Broadcom CNIC support"
++ depends on PCI
++ select BNX2
++ select UIO
++ help
++ This driver supports offload features of Broadcom NetXtremeII
++ gigabit Ethernet cards.
++
++ To compile this driver as a module, choose M here: the module
++ will be called cnic. This is recommended.
++
++config SPIDER_NET
++ tristate "Spider Gigabit Ethernet driver"
++ depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB)
++ select FW_LOADER
++ help
++ This driver supports the Gigabit Ethernet chips present on the
++ Cell Processor-Based Blades from IBM.
++
++config TSI108_ETH
++ tristate "Tundra TSI108 gigabit Ethernet support"
++ depends on TSI108_BRIDGE
++ help
++ This driver supports Tundra TSI108 gigabit Ethernet ports.
++ To compile this driver as a module, choose M here: the module
++ will be called tsi108_eth.
++
++config GELIC_NET
++ tristate "PS3 Gigabit Ethernet driver"
++ depends on PPC_PS3
++ select PS3_SYS_MANAGER
++ help
++ This driver supports the network device on the PS3 game
++ console. This driver has built-in support for Ethernet.
++
++ To compile this driver as a module, choose M here: the
++ module will be called ps3_gelic.
++
++config GELIC_WIRELESS
++ bool "PS3 Wireless support"
++ depends on WLAN
++ depends on GELIC_NET
++ select WIRELESS_EXT
++ help
++ This option adds the support for the wireless feature of PS3.
++ If you have the wireless-less model of PS3 or have no plan to
++ use wireless feature, disabling this option saves memory. As
++ the driver automatically distinguishes the models, you can
++ safely enable this option even if you have a wireless-less model.
++
++config FSL_PQ_MDIO
++ tristate "Freescale PQ MDIO"
++ depends on FSL_SOC
++ select PHYLIB
++ help
++ This driver supports the MDIO bus used by the gianfar and UCC drivers.
++
++config GIANFAR
++ tristate "Gianfar Ethernet"
++ depends on FSL_SOC
++ select FSL_PQ_MDIO
++ select PHYLIB
++ select CRC32
++ help
++ This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx,
++ and MPC86xx family of chips, and the FEC on the 8540.
++
++config UCC_GETH
++ tristate "Freescale QE Gigabit Ethernet"
++ depends on QUICC_ENGINE
++ select FSL_PQ_MDIO
++ select PHYLIB
++ help
++ This driver supports the Gigabit Ethernet mode of the QUICC Engine,
++ which is available on some Freescale SOCs.
++
++config UGETH_TX_ON_DEMAND
++ bool "Transmit on Demand support"
++ depends on UCC_GETH
++
++config MV643XX_ETH
++ tristate "Marvell Discovery (643XX) and Orion ethernet support"
++ depends on MV64X60 || PPC32 || PLAT_ORION
++ select INET_LRO
++ select PHYLIB
++ help
++ This driver supports the gigabit ethernet MACs in the
++ Marvell Discovery PPC/MIPS chipset family (MV643XX) and
++ in the Marvell Orion ARM SoC family.
++
++ Some boards that use the Discovery chipset are the Momenco
++ Ocelot C and Jaguar ATX and Pegasos II.
++
++config XILINX_LL_TEMAC
++ tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver"
++ depends on PPC || MICROBLAZE
++ select PHYLIB
++ help
++ This driver supports the Xilinx 10/100/1000 LocalLink TEMAC
++ core used in Xilinx Spartan and Virtex FPGAs
++
++config QLA3XXX
++ tristate "QLogic QLA3XXX Network Driver Support"
++ depends on PCI
++ help
++ This driver supports QLogic ISP3XXX gigabit Ethernet cards.
++
++ To compile this driver as a module, choose M here: the module
++ will be called qla3xxx.
++
++config ATL1
++ tristate "Atheros/Attansic L1 Gigabit Ethernet support"
++ depends on PCI
++ select CRC32
++ select MII
++ help
++ This driver supports the Atheros/Attansic L1 gigabit ethernet
++ adapter.
++
++ To compile this driver as a module, choose M here. The module
++ will be called atl1.
++
++config ATL1E
++ tristate "Atheros L1E Gigabit Ethernet support (EXPERIMENTAL)"
++ depends on PCI && EXPERIMENTAL
++ select CRC32
++ select MII
++ help
++ This driver supports the Atheros L1E gigabit ethernet adapter.
++
++ To compile this driver as a module, choose M here. The module
++ will be called atl1e.
++
++config ATL1C
++ tristate "Atheros L1C Gigabit Ethernet support (EXPERIMENTAL)"
++ depends on PCI && EXPERIMENTAL
++ select CRC32
++ select MII
++ help
++ This driver supports the Atheros L1C gigabit ethernet adapter.
++
++ To compile this driver as a module, choose M here. The module
++ will be called atl1c.
++
++config JME
++ tristate "JMicron(R) PCI-Express Gigabit Ethernet support"
++ depends on PCI
++ select CRC32
++ select MII
++ ---help---
++ This driver supports the PCI-Express gigabit ethernet adapters
++ based on JMicron JMC250 chipset.
++
++ To compile this driver as a module, choose M here. The module
++ will be called jme.
++
++config S6GMAC
++ tristate "S6105 GMAC ethernet support"
++ depends on XTENSA_VARIANT_S6000
++ select PHYLIB
++ help
++ This driver supports the on chip ethernet device on the
++ S6105 xtensa processor.
++
++ To compile this driver as a module, choose M here. The module
++ will be called s6gmac.
++
++source "drivers/net/stmmac/Kconfig"
++
++endif # NETDEV_1000
++
++#
++# 10 Gigabit Ethernet
++#
++
++menuconfig NETDEV_10000
++ bool "Ethernet (10000 Mbit)"
++ depends on !UML
++ default y
++ ---help---
++ Say Y here to get to see options for 10 Gigabit Ethernet drivers.
++ This option alone does not add any kernel code.
++
++ If you say N, all options in this submenu will be skipped and disabled.
++
++if NETDEV_10000
++
++config MDIO
++ tristate
++
++config CHELSIO_T1
++ tristate "Chelsio 10Gb Ethernet support"
++ depends on PCI
++ select CRC32
++ select MDIO
++ help
++ This driver supports Chelsio gigabit and 10-gigabit
++ Ethernet cards. More information about adapter features and
++ performance tuning is in <file:Documentation/networking/cxgb.txt>.
++
++ For general information about Chelsio and our products, visit
++ our website at <http://www.chelsio.com>.
++
++ For customer support, please visit our customer support page at
++ <http://www.chelsio.com/support.htm>.
++
++ Please send feedback to <linux-bugs at chelsio.com>.
++
++ To compile this driver as a module, choose M here: the module
++ will be called cxgb.
++
++config CHELSIO_T1_1G
++ bool "Chelsio gigabit Ethernet support"
++ depends on CHELSIO_T1
++ help
++ Enables support for Chelsio's gigabit Ethernet PCI cards. If you
++ are using only 10G cards say 'N' here.
++
++config CHELSIO_T3_DEPENDS
++ tristate
++ depends on PCI && INET
++ default y
++
++config CHELSIO_T3
++ tristate "Chelsio Communications T3 10Gb Ethernet support"
++ depends on CHELSIO_T3_DEPENDS
++ select FW_LOADER
++ select MDIO
++ help
++ This driver supports Chelsio T3-based gigabit and 10Gb Ethernet
++ adapters.
++
++ For general information about Chelsio and our products, visit
++ our website at <http://www.chelsio.com>.
++
++ For customer support, please visit our customer support page at
++ <http://www.chelsio.com/support.htm>.
++
++ Please send feedback to <linux-bugs at chelsio.com>.
++
++ To compile this driver as a module, choose M here: the module
++ will be called cxgb3.
++
++config CHELSIO_T4_DEPENDS
++ tristate
++ depends on PCI && INET
++ default y
++
++config CHELSIO_T4
++ tristate "Chelsio Communications T4 Ethernet support"
++ depends on CHELSIO_T4_DEPENDS
++ select FW_LOADER
++ select MDIO
++ help
++ This driver supports Chelsio T4-based gigabit and 10Gb Ethernet
++ adapters.
++
++ For general information about Chelsio and our products, visit
++ our website at <http://www.chelsio.com>.
++
++ For customer support, please visit our customer support page at
++ <http://www.chelsio.com/support.htm>.
++
++ Please send feedback to <linux-bugs at chelsio.com>.
++
++ To compile this driver as a module choose M here; the module
++ will be called cxgb4.
++
++config EHEA
++ tristate "eHEA Ethernet support"
++ depends on IBMEBUS && INET && SPARSEMEM
++ select INET_LRO
++ ---help---
++ This driver supports the IBM pSeries eHEA ethernet adapter.
++
++ To compile the driver as a module, choose M here. The module
++ will be called ehea.
++
++config ENIC
++ tristate "Cisco VIC Ethernet NIC Support"
++ depends on PCI && INET
++ select INET_LRO
++ help
++ This enables the support for the Cisco VIC Ethernet card.
++
++config IXGBE
++ tristate "Intel(R) 10GbE PCI Express adapters support"
++ depends on PCI && INET
++ select MDIO
++ ---help---
++ This driver supports Intel(R) 10GbE PCI Express family of
++ adapters. For more information on how to identify your adapter, go
++ to the Adapter & Driver ID Guide at:
++
++ <http://support.intel.com/support/network/adapter/pro100/21397.htm>
++
++ For general information and support, go to the Intel support
++ website at:
++
++ <http://support.intel.com>
++
++ To compile this driver as a module, choose M here. The module
++ will be called ixgbe.
++
++config IXGBE_DCA
++ bool "Direct Cache Access (DCA) Support"
++ default y
++ depends on IXGBE && DCA && !(IXGBE=y && DCA=m)
++ ---help---
++ Say Y here if you want to use Direct Cache Access (DCA) in the
++ driver. DCA is a method for warming the CPU cache before data
++ is used, with the intent of lessening the impact of cache misses.
++
++config IXGBE_DCB
++ bool "Data Center Bridging (DCB) Support"
++ default n
++ depends on IXGBE && DCB
++ ---help---
++ Say Y here if you want to use Data Center Bridging (DCB) in the
++ driver.
++
++ If unsure, say N.
++
++config IXGBEVF
++ tristate "Intel(R) 82599 Virtual Function Ethernet support"
++ depends on PCI_MSI
++ ---help---
++ This driver supports Intel(R) 82599 virtual functions. For more
++ information on how to identify your adapter, go to the Adapter &
++ Driver ID Guide at:
++
++ <http://support.intel.com/support/network/sb/CS-008441.htm>
++
++ For general information and support, go to the Intel support
++ website at:
++
++ <http://support.intel.com>
++
++ More specific information on configuring the driver is in
++ <file:Documentation/networking/ixgbevf.txt>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called ixgbevf. MSI-X interrupt support is required
++ for this driver to work correctly.
++
++config IXGB
++ tristate "Intel(R) PRO/10GbE support"
++ depends on PCI
++ ---help---
++ This driver supports Intel(R) PRO/10GbE family of adapters for
++ PCI-X type cards. For PCI-E type cards, use the "ixgbe" driver
++ instead. For more information on how to identify your adapter, go
++ to the Adapter & Driver ID Guide at:
++
++ <http://support.intel.com/support/network/adapter/pro100/21397.htm>
++
++ For general information and support, go to the Intel support
++ website at:
++
++ <http://support.intel.com>
++
++ More specific information on configuring the driver is in
++ <file:Documentation/networking/ixgb.txt>.
++
++ To compile this driver as a module, choose M here. The module
++ will be called ixgb.
++
++config S2IO
++ tristate "S2IO 10Gbe XFrame NIC"
++ depends on PCI
++ ---help---
++ This driver supports the 10Gbe XFrame NIC of S2IO.
++ More specific information on configuring the driver is in
++ <file:Documentation/networking/s2io.txt>.
++
++config VXGE
++ tristate "Neterion X3100 Series 10GbE PCIe Server Adapter"
++ depends on PCI && INET
++ ---help---
++ This driver supports Neterion Inc's X3100 Series 10 GbE PCIe
++ I/O Virtualized Server Adapter.
++ More specific information on configuring the driver is in
++ <file:Documentation/networking/vxge.txt>.
++
++config VXGE_DEBUG_TRACE_ALL
++ bool "Enabling All Debug trace statments in driver"
++ default n
++ depends on VXGE
++ ---help---
++ Say Y here if you want to enabling all the debug trace statements in
++ driver. By default only few debug trace statements are enabled.
++
++config MYRI10GE
++ tristate "Myricom Myri-10G Ethernet support"
++ depends on PCI && INET
++ select FW_LOADER
++ select CRC32
++ select INET_LRO
++ ---help---
++ This driver supports Myricom Myri-10G Dual Protocol interface in
++ Ethernet mode. If the eeprom on your board is not recent enough,
++ you will need a newer firmware image.
++ You may get this image or more information, at:
++
++ <http://www.myri.com/scs/download-Myri10GE.html>
++
++ To compile this driver as a module, choose M here. The module
++ will be called myri10ge.
++
++config MYRI10GE_DCA
++ bool "Direct Cache Access (DCA) Support"
++ default y
++ depends on MYRI10GE && DCA && !(MYRI10GE=y && DCA=m)
++ ---help---
++ Say Y here if you want to use Direct Cache Access (DCA) in the
++ driver. DCA is a method for warming the CPU cache before data
++ is used, with the intent of lessening the impact of cache misses.
++
++config NETXEN_NIC
++ tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"
++ depends on PCI
++ select FW_LOADER
++ help
++ This enables the support for NetXen's Gigabit Ethernet card.
++
++config NIU
++ tristate "Sun Neptune 10Gbit Ethernet support"
++ depends on PCI
++ select CRC32
++ help
++ This enables support for cards based upon Sun's
++ Neptune chipset.
++
++config PASEMI_MAC
++ tristate "PA Semi 1/10Gbit MAC"
++ depends on PPC_PASEMI && PCI
++ select PHYLIB
++ select INET_LRO
++ help
++ This driver supports the on-chip 1/10Gbit Ethernet controller on
++ PA Semi's PWRficient line of chips.
++
++config MLX4_EN
++ tristate "Mellanox Technologies 10Gbit Ethernet support"
++ depends on PCI && INET
++ select MLX4_CORE
++ select INET_LRO
++ help
++ This driver supports Mellanox Technologies ConnectX Ethernet
++ devices.
++
++config MLX4_CORE
++ tristate
++ depends on PCI
++ default n
++
++config MLX4_DEBUG
++ bool "Verbose debugging output" if (MLX4_CORE && EMBEDDED)
++ depends on MLX4_CORE
++ default y
++ ---help---
++ This option causes debugging code to be compiled into the
++ mlx4_core driver. The output can be turned on via the
++ debug_level module parameter (which can also be set after
++ the driver is loaded through sysfs).
++
++config TEHUTI
++ tristate "Tehuti Networks 10G Ethernet"
++ depends on PCI
++ help
++ Tehuti Networks 10G Ethernet NIC
++
++config BNX2X
++ tristate "Broadcom NetXtremeII 10Gb support"
++ depends on PCI
++ select FW_LOADER
++ select ZLIB_INFLATE
++ select LIBCRC32C
++ select MDIO
++ help
++ This driver supports Broadcom NetXtremeII 10 gigabit Ethernet cards.
++ To compile this driver as a module, choose M here: the module
++ will be called bnx2x. This is recommended.
++
++config QLCNIC
++ tristate "QLOGIC QLCNIC 1/10Gb Converged Ethernet NIC Support"
++ depends on PCI
++ select FW_LOADER
++ help
++ This driver supports QLogic QLE8240 and QLE8242 Converged Ethernet
++ devices.
++
++config QLGE
++ tristate "QLogic QLGE 10Gb Ethernet Driver Support"
++ depends on PCI
++ help
++ This driver supports QLogic ISP8XXX 10Gb Ethernet cards.
++
++ To compile this driver as a module, choose M here: the module
++ will be called qlge.
++
++source "drivers/net/sfc/Kconfig"
++
++source "drivers/net/benet/Kconfig"
++
++endif # NETDEV_10000
++
++source "drivers/net/tokenring/Kconfig"
++
++source "drivers/net/wireless/Kconfig"
++
++source "drivers/net/wimax/Kconfig"
++
++source "drivers/net/usb/Kconfig"
++
++source "drivers/net/pcmcia/Kconfig"
++
++source "drivers/net/wan/Kconfig"
++
++source "drivers/atm/Kconfig"
++
++source "drivers/ieee802154/Kconfig"
++
++source "drivers/s390/net/Kconfig"
++
++source "drivers/net/caif/Kconfig"
++
++config XEN_NETDEV_FRONTEND
++ tristate "Xen network device frontend driver"
++ depends on XEN
++ default y
++ help
++ The network device frontend driver allows the kernel to
++ access network devices exported exported by a virtual
++ machine containing a physical network device driver. The
++ frontend driver is intended for unprivileged guest domains;
++ if you are compiling a kernel for a Xen guest, you almost
++ certainly want to enable this.
++
++config ISERIES_VETH
++ tristate "iSeries Virtual Ethernet driver support"
++ depends on PPC_ISERIES
++
++config RIONET
++ tristate "RapidIO Ethernet over messaging driver support"
++ depends on RAPIDIO
++
++config RIONET_TX_SIZE
++ int "Number of outbound queue entries"
++ depends on RIONET
++ default "128"
++
++config RIONET_RX_SIZE
++ int "Number of inbound queue entries"
++ depends on RIONET
++ default "128"
++
++config FDDI
++ tristate "FDDI driver support"
++ depends on (PCI || EISA || TC)
++ help
++ Fiber Distributed Data Interface is a high speed local area network
++ design; essentially a replacement for high speed Ethernet. FDDI can
++ run over copper or fiber. If you are connected to such a network and
++ want a driver for the FDDI card in your computer, say Y here (and
++ then also Y to the driver for your FDDI card, below). Most people
++ will say N.
++
++config DEFXX
++ tristate "Digital DEFTA/DEFEA/DEFPA adapter support"
++ depends on FDDI && (PCI || EISA || TC)
++ ---help---
++ This is support for the DIGITAL series of TURBOchannel (DEFTA),
++ EISA (DEFEA) and PCI (DEFPA) controllers which can connect you
++ to a local FDDI network.
++
++ To compile this driver as a module, choose M here: the module
++ will be called defxx. If unsure, say N.
++
++config DEFXX_MMIO
++ bool
++ prompt "Use MMIO instead of PIO" if PCI || EISA
++ depends on DEFXX
++ default n if PCI || EISA
++ default y
++ ---help---
++ This instructs the driver to use EISA or PCI memory-mapped I/O
++ (MMIO) as appropriate instead of programmed I/O ports (PIO).
++ Enabling this gives an improvement in processing time in parts
++ of the driver, but it may cause problems with EISA (DEFEA)
++ adapters. TURBOchannel does not have the concept of I/O ports,
++ so MMIO is always used for these (DEFTA) adapters.
++
++ If unsure, say N.
++
++config SKFP
++ tristate "SysKonnect FDDI PCI support"
++ depends on FDDI && PCI
++ select BITREVERSE
++ ---help---
++ Say Y here if you have a SysKonnect FDDI PCI adapter.
++ The following adapters are supported by this driver:
++ - SK-5521 (SK-NET FDDI-UP)
++ - SK-5522 (SK-NET FDDI-UP DAS)
++ - SK-5541 (SK-NET FDDI-FP)
++ - SK-5543 (SK-NET FDDI-LP)
++ - SK-5544 (SK-NET FDDI-LP DAS)
++ - SK-5821 (SK-NET FDDI-UP64)
++ - SK-5822 (SK-NET FDDI-UP64 DAS)
++ - SK-5841 (SK-NET FDDI-FP64)
++ - SK-5843 (SK-NET FDDI-LP64)
++ - SK-5844 (SK-NET FDDI-LP64 DAS)
++ - Netelligent 100 FDDI DAS Fibre SC
++ - Netelligent 100 FDDI SAS Fibre SC
++ - Netelligent 100 FDDI DAS UTP
++ - Netelligent 100 FDDI SAS UTP
++ - Netelligent 100 FDDI SAS Fibre MIC
++
++ Read <file:Documentation/networking/skfp.txt> for information about
++ the driver.
++
++ Questions concerning this driver can be addressed to:
++ <linux at syskonnect.de>
++
++ To compile this driver as a module, choose M here: the module
++ will be called skfp. This is recommended.
++
++config HIPPI
++ bool "HIPPI driver support (EXPERIMENTAL)"
++ depends on EXPERIMENTAL && INET && PCI
++ help
++ HIgh Performance Parallel Interface (HIPPI) is a 800Mbit/sec and
++ 1600Mbit/sec dual-simplex switched or point-to-point network. HIPPI
++ can run over copper (25m) or fiber (300m on multi-mode or 10km on
++ single-mode). HIPPI networks are commonly used for clusters and to
++ connect to super computers. If you are connected to a HIPPI network
++ and have a HIPPI network card in your computer that you want to use
++ under Linux, say Y here (you must also remember to enable the driver
++ for your HIPPI card below). Most people will say N here.
++
++config ROADRUNNER
++ tristate "Essential RoadRunner HIPPI PCI adapter support (EXPERIMENTAL)"
++ depends on HIPPI && PCI
++ help
++ Say Y here if this is your PCI HIPPI network card.
++
++ To compile this driver as a module, choose M here: the module
++ will be called rrunner. If unsure, say N.
++
++config ROADRUNNER_LARGE_RINGS
++ bool "Use large TX/RX rings (EXPERIMENTAL)"
++ depends on ROADRUNNER
++ help
++ If you say Y here, the RoadRunner driver will preallocate up to 2 MB
++ of additional memory to allow for fastest operation, both for
++ transmitting and receiving. This memory cannot be used by any other
++ kernel code or by user space programs. Say Y here only if you have
++ the memory.
++
++config PLIP
++ tristate "PLIP (parallel port) support"
++ depends on PARPORT
++ ---help---
++ PLIP (Parallel Line Internet Protocol) is used to create a
++ reasonably fast mini network consisting of two (or, rarely, more)
++ local machines. A PLIP link from a Linux box is a popular means to
++ install a Linux distribution on a machine which doesn't have a
++ CD-ROM drive (a minimal system has to be transferred with floppies
++ first). The kernels on both machines need to have this PLIP option
++ enabled for this to work.
++
++ The PLIP driver has two modes, mode 0 and mode 1. The parallel
++ ports (the connectors at the computers with 25 holes) are connected
++ with "null printer" or "Turbo Laplink" cables which can transmit 4
++ bits at a time (mode 0) or with special PLIP cables, to be used on
++ bidirectional parallel ports only, which can transmit 8 bits at a
++ time (mode 1); you can find the wiring of these cables in
++ <file:Documentation/networking/PLIP.txt>. The cables can be up to
++ 15m long. Mode 0 works also if one of the machines runs DOS/Windows
++ and has some PLIP software installed, e.g. the Crynwr PLIP packet
++ driver (<http://oak.oakland.edu/simtel.net/msdos/pktdrvr-pre.html>)
++ and winsock or NCSA's telnet.
++
++ If you want to use PLIP, say Y and read the PLIP mini-HOWTO as well
++ as the NET-3-HOWTO, both available from
++ <http://www.tldp.org/docs.html#howto>. Note that the PLIP
++ protocol has been changed and this PLIP driver won't work together
++ with the PLIP support in Linux versions 1.0.x. This option enlarges
++ your kernel by about 8 KB.
++
++ To compile this driver as a module, choose M here. The module
++ will be called plip. If unsure, say Y or M, in case you buy
++ a laptop later.
++
++config PPP
++ tristate "PPP (point-to-point protocol) support"
++ select SLHC
++ ---help---
++ PPP (Point to Point Protocol) is a newer and better SLIP. It serves
++ the same purpose: sending Internet traffic over telephone (and other
++ serial) lines. Ask your access provider if they support it, because
++ otherwise you can't use it; most Internet access providers these
++ days support PPP rather than SLIP.
++
++ To use PPP, you need an additional program called pppd as described
++ in the PPP-HOWTO, available at
++ <http://www.tldp.org/docs.html#howto>. Make sure that you have
++ the version of pppd recommended in <file:Documentation/Changes>.
++ The PPP option enlarges your kernel by about 16 KB.
++
++ There are actually two versions of PPP: the traditional PPP for
++ asynchronous lines, such as regular analog phone lines, and
++ synchronous PPP which can be used over digital ISDN lines for
++ example. If you want to use PPP over phone lines or other
++ asynchronous serial lines, you need to say Y (or M) here and also to
++ the next option, "PPP support for async serial ports". For PPP over
++ synchronous lines, you should say Y (or M) here and to "Support
++ synchronous PPP", below.
++
++ If you said Y to "Version information on all symbols" above, then
++ you cannot compile the PPP driver into the kernel; you can then only
++ compile it as a module. To compile this driver as a module, choose M
++ here. The module will be called ppp_generic.
++
++config PPP_MULTILINK
++ bool "PPP multilink support (EXPERIMENTAL)"
++ depends on PPP && EXPERIMENTAL
++ help
++ PPP multilink is a protocol (defined in RFC 1990) which allows you
++ to combine several (logical or physical) lines into one logical PPP
++ connection, so that you can utilize your full bandwidth.
++
++ This has to be supported at the other end as well and you need a
++ version of the pppd daemon which understands the multilink protocol.
++
++ If unsure, say N.
++
++config PPP_FILTER
++ bool "PPP filtering"
++ depends on PPP
++ help
++ Say Y here if you want to be able to filter the packets passing over
++ PPP interfaces. This allows you to control which packets count as
++ activity (i.e. which packets will reset the idle timer or bring up
++ a demand-dialed link) and which packets are to be dropped entirely.
++ You need to say Y here if you wish to use the pass-filter and
++ active-filter options to pppd.
++
++ If unsure, say N.
++
++config PPP_ASYNC
++ tristate "PPP support for async serial ports"
++ depends on PPP
++ select CRC_CCITT
++ ---help---
++ Say Y (or M) here if you want to be able to use PPP over standard
++ asynchronous serial ports, such as COM1 or COM2 on a PC. If you use
++ a modem (not a synchronous or ISDN modem) to contact your ISP, you
++ need this option.
++
++ To compile this driver as a module, choose M here.
++
++ If unsure, say Y.
++
++config PPP_SYNC_TTY
++ tristate "PPP support for sync tty ports"
++ depends on PPP
++ help
++ Say Y (or M) here if you want to be able to use PPP over synchronous
++ (HDLC) tty devices, such as the SyncLink adapter. These devices
++ are often used for high-speed leased lines like T1/E1.
++
++ To compile this driver as a module, choose M here.
++
++config PPP_DEFLATE
++ tristate "PPP Deflate compression"
++ depends on PPP
++ select ZLIB_INFLATE
++ select ZLIB_DEFLATE
++ ---help---
++ Support for the Deflate compression method for PPP, which uses the
++ Deflate algorithm (the same algorithm that gzip uses) to compress
++ each PPP packet before it is sent over the wire. The machine at the
++ other end of the PPP link (usually your ISP) has to support the
++ Deflate compression method as well for this to be useful. Even if
++ they don't support it, it is safe to say Y here.
++
++ To compile this driver as a module, choose M here.
++
++config PPP_BSDCOMP
++ tristate "PPP BSD-Compress compression"
++ depends on PPP
++ ---help---
++ Support for the BSD-Compress compression method for PPP, which uses
++ the LZW compression method to compress each PPP packet before it is
++ sent over the wire. The machine at the other end of the PPP link
++ (usually your ISP) has to support the BSD-Compress compression
++ method as well for this to be useful. Even if they don't support it,
++ it is safe to say Y here.
++
++ The PPP Deflate compression method ("PPP Deflate compression",
++ above) is preferable to BSD-Compress, because it compresses better
++ and is patent-free.
++
++ Note that the BSD compression code will always be compiled as a
++ module; it is called bsd_comp and will show up in the directory
++ modules once you have said "make modules". If unsure, say N.
++
++config PPP_MPPE
++ tristate "PPP MPPE compression (encryption) (EXPERIMENTAL)"
++ depends on PPP && EXPERIMENTAL
++ select CRYPTO
++ select CRYPTO_SHA1
++ select CRYPTO_ARC4
++ select CRYPTO_ECB
++ ---help---
++ Support for the MPPE Encryption protocol, as employed by the
++ Microsoft Point-to-Point Tunneling Protocol.
++
++ See http://pptpclient.sourceforge.net/ for information on
++ configuring PPTP clients and servers to utilize this method.
++
++config PPPOE
++ tristate "PPP over Ethernet (EXPERIMENTAL)"
++ depends on EXPERIMENTAL && PPP
++ help
++ Support for PPP over Ethernet.
++
++ This driver requires the latest version of pppd from the CVS
++ repository at cvs.samba.org. Alternatively, see the
++ RoaringPenguin package (<http://www.roaringpenguin.com/pppoe>)
++ which contains instruction on how to use this driver (under
++ the heading "Kernel mode PPPoE").
++
++config PPPOATM
++ tristate "PPP over ATM"
++ depends on ATM && PPP
++ help
++ Support PPP (Point to Point Protocol) encapsulated in ATM frames.
++ This implementation does not yet comply with section 8 of RFC2364,
++ which can lead to bad results if the ATM peer loses state and
++ changes its encapsulation unilaterally.
++
++config PPPOL2TP
++ tristate "PPP over L2TP (EXPERIMENTAL)"
++ depends on EXPERIMENTAL && L2TP && PPP
++ help
++ Support for PPP-over-L2TP socket family. L2TP is a protocol
++ used by ISPs and enterprises to tunnel PPP traffic over UDP
++ tunnels. L2TP is replacing PPTP for VPN uses.
++
++config SLIP
++ tristate "SLIP (serial line) support"
++ ---help---
++ Say Y if you intend to use SLIP or CSLIP (compressed SLIP) to
++ connect to your Internet service provider or to connect to some
++ other local Unix box or if you want to configure your Linux box as a
++ Slip/CSlip server for other people to dial in. SLIP (Serial Line
++ Internet Protocol) is a protocol used to send Internet traffic over
++ serial connections such as telephone lines or null modem cables;
++ nowadays, the protocol PPP is more commonly used for this same
++ purpose.
++
++ Normally, your access provider has to support SLIP in order for you
++ to be able to use it, but there is now a SLIP emulator called SLiRP
++ around (available from
++ <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
++ allows you to use SLIP over a regular dial up shell connection. If
++ you plan to use SLiRP, make sure to say Y to CSLIP, below. The
++ NET-3-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>, explains how to
++ configure SLIP. Note that you don't need this option if you just
++ want to run term (term is a program which gives you almost full
++ Internet connectivity if you have a regular dial up shell account on
++ some Internet connected Unix computer. Read
++ <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>). SLIP
++ support will enlarge your kernel by about 4 KB. If unsure, say N.
++
++ To compile this driver as a module, choose M here. The module
++ will be called slip.
++
++config SLIP_COMPRESSED
++ bool "CSLIP compressed headers"
++ depends on SLIP
++ select SLHC
++ ---help---
++ This protocol is faster than SLIP because it uses compression on the
++ TCP/IP headers (not on the data itself), but it has to be supported
++ on both ends. Ask your access provider if you are not sure and
++ answer Y, just in case. You will still be able to use plain SLIP. If
++ you plan to use SLiRP, the SLIP emulator (available from
++ <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
++ allows you to use SLIP over a regular dial up shell connection, you
++ definitely want to say Y here. The NET-3-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>, explains how to configure
++ CSLIP. This won't enlarge your kernel.
++
++config SLHC
++ tristate
++ help
++ This option enables Van Jacobsen serial line header compression
++ routines.
++
++config SLIP_SMART
++ bool "Keepalive and linefill"
++ depends on SLIP
++ help
++ Adds additional capabilities to the SLIP driver to support the
++ RELCOM line fill and keepalive monitoring. Ideal on poor quality
++ analogue lines.
++
++config SLIP_MODE_SLIP6
++ bool "Six bit SLIP encapsulation"
++ depends on SLIP
++ help
++ Just occasionally you may need to run IP over hostile serial
++ networks that don't pass all control characters or are only seven
++ bit. Saying Y here adds an extra mode you can use with SLIP:
++ "slip6". In this mode, SLIP will only send normal ASCII symbols over
++ the serial device. Naturally, this has to be supported at the other
++ end of the link as well. It's good enough, for example, to run IP
++ over the async ports of a Camtec JNT Pad. If unsure, say N.
++
++config NET_FC
++ bool "Fibre Channel driver support"
++ depends on SCSI && PCI
++ help
++ Fibre Channel is a high speed serial protocol mainly used to connect
++ large storage devices to the computer; it is compatible with and
++ intended to replace SCSI.
++
++ If you intend to use Fibre Channel, you need to have a Fibre channel
++ adaptor card in your computer; say Y here and to the driver for your
++ adaptor below. You also should have said Y to "SCSI support" and
++ "SCSI generic support".
++
++config NETCONSOLE
++ tristate "Network console logging support"
++ ---help---
++ If you want to log kernel messages over the network, enable this.
++ See <file:Documentation/networking/netconsole.txt> for details.
++
++config NETCONSOLE_DYNAMIC
++ bool "Dynamic reconfiguration of logging targets"
++ depends on NETCONSOLE && SYSFS
++ select CONFIGFS_FS
++ help
++ This option enables the ability to dynamically reconfigure target
++ parameters (interface, IP addresses, port numbers, MAC addresses)
++ at runtime through a userspace interface exported using configfs.
++ See <file:Documentation/networking/netconsole.txt> for details.
++
++config NETPOLL
++ def_bool NETCONSOLE
++
++config NETPOLL_TRAP
++ bool "Netpoll traffic trapping"
++ default n
++ depends on NETPOLL
++
++config NET_POLL_CONTROLLER
++ def_bool NETPOLL
++
++config VIRTIO_NET
++ tristate "Virtio network driver (EXPERIMENTAL)"
++ depends on EXPERIMENTAL && VIRTIO
++ ---help---
++ This is the virtual network driver for virtio. It can be used with
++ lguest or QEMU based VMMs (like KVM or Xen). Say Y or M.
++
++config VMXNET3
++ tristate "VMware VMXNET3 ethernet driver"
++ depends on PCI && INET
++ help
++ This driver supports VMware's vmxnet3 virtual ethernet NIC.
++ To compile this driver as a module, choose M here: the
++ module will be called vmxnet3.
++
++endif # NETDEVICES
+diff -rupN linux-2.6.35.11/drivers/net/Makefile linux-2.6.35.11-ts7500/drivers/net/Makefile
+--- linux-2.6.35.11/drivers/net/Makefile 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/Makefile 2011-03-14 11:18:24.000000000 -0400
+@@ -8,6 +8,9 @@ obj-$(CONFIG_PHYLIB) += phy/
+
+ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
+
++obj-$(CONFIG_FAST_BRIDGE) += fast_bridge.o
++obj-$(CONFIG_STAR_GSW) += str9100/
++obj-$(CONFIG_STAR_NIC) += str8100/
+ obj-$(CONFIG_E1000) += e1000/
+ obj-$(CONFIG_E1000E) += e1000e/
+ obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac/
+diff -rupN linux-2.6.35.11/drivers/net/str8100/Kconfig linux-2.6.35.11-ts7500/drivers/net/str8100/Kconfig
+--- linux-2.6.35.11/drivers/net/str8100/Kconfig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/str8100/Kconfig 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,28 @@
++menu "CNS2100 NIC support"
++ depends on ARCH_STR8100 && (NET_ETHERNET || NETDEV_1000)
++
++config STAR_NIC
++ tristate "CNS2100 NIC driver support"
++ help
++
++choice
++ depends on STAR_NIC
++ prompt "PHY Driver"
++ default STR_NIC_PHY_VSC8201
++
++config STAR_NIC_PHY_INTERNAL_PHY
++ bool "Internal 10/100 PHY"
++
++config STAR_NIC_PHY_VSC8601
++ bool "Vitesse 8601"
++
++config STAR_NIC_PHY_IP101A
++ bool "ICPlus IP101A"
++
++config STAR_NIC_PHY_IP1001
++ bool "ICPlus IP1001"
++
++endchoice
++
++endmenu
++
+diff -rupN linux-2.6.35.11/drivers/net/str8100/Makefile linux-2.6.35.11-ts7500/drivers/net/str8100/Makefile
+--- linux-2.6.35.11/drivers/net/str8100/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/str8100/Makefile 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,34 @@
++################################################################################
++#
++#
++# Copyright(c) 2005 - Star semiconduction. 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 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.
++#
++# The full GNU General Public License is included in this distribution in the
++# file called LICENSE.
++#
++# Contact Information:
++# Star semiconduction Linux Support <support at starsemi.com>
++#
++################################################################################
++
++#
++# Makefile for the Star GSW ethernet driver
++#
++
++obj-$(CONFIG_STAR_NIC) += star_nic_module.o
++star_nic_module-objs := star_nic.o
++
+diff -rupN linux-2.6.35.11/drivers/net/str8100/star_nic.c linux-2.6.35.11-ts7500/drivers/net/str8100/star_nic.c
+--- linux-2.6.35.11/drivers/net/str8100/star_nic.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/str8100/star_nic.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,3070 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/bootmem.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/fcntl.h>
++#include <linux/interrupt.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/in.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/proc_fs.h>
++#include <asm/bitops.h>
++#include <asm/irq.h> // 2006.03.22 richliu add list include file
++#include <asm/io.h>
++#include <asm/hardware.h>
++#include <linux/pci.h>
++#include <linux/errno.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <linux/ip.h>
++#include <linux/if_ether.h>
++#include <linux/icmp.h>
++#include <linux/udp.h>
++#include <linux/tcp.h>
++#include <linux/if_arp.h>
++#include <net/arp.h>
++
++#include <asm/arch/star_nic.h>
++
++#ifdef CONFIG_PM
++#include <linux/suspend.h>
++#endif
++
++#if 1
++#define DBG_PRINT printk
++#else
++#define DBG_PRINT(arg...)
++#endif
++
++#if 0
++#define DO_PRINT printk
++#define STAR_NIC_PRINT_ISR_STATUS
++#else
++#define DO_PRINT(arg...)
++#endif /* __DEBUG_PRINT_OUT */
++
++// VSC8601 and WavePlus Phy are the same
++#define STAR_NIC_PHY_ADDR 0
++
++#define CONFIG_STAR_NIC_NAPI
++//#define FREE_TX_SKB_MULTI // FIXME: define this will cause samba fail
++
++#define STAR_NIC_TX_HW_CHECKSUM
++#define STAR_NIC_RX_HW_CHECKSUM
++
++#define STAR_NIC_SG
++
++#if defined(STAR_NIC_SG) && !defined(STAR_NIC_TX_HW_CHECKSUM)
++#define STAR_NIC_TX_HW_CHECKSUM
++#endif
++
++#define STAR_NIC_STATUS_ISR
++#define STAR_NIC_RXQF_ISR
++
++//#ifndef CONFIG_STAR_NIC_NAPI
++#define STAR_NIC_DELAYED_INTERRUPT
++//#endif
++
++#define MAX_PEND_INT_CNT 0x20
++#define MAX_PEND_TIME 0x20
++
++//#ifdef CONFIG_STAR_NIC_PHY_VSC8601
++//#define CONFIG_STAR_JUMBO
++//#endif
++//#define CONFIG_STAR_JUMBO
++#ifdef CONFIG_STAR_JUMBO
++#define MAX_PACKET_LEN (2038)
++//#define MAX_PACKET_LEN (9038)
++#else
++#define MAX_PACKET_LEN (1536)
++#endif
++/* This constant(PKT_MIN_SIZE) can be replaced with ETH_ZLEN defined in
++ * include/linux/if_ether.h */
++#define PKT_MIN_SIZE 60
++
++//#define STAR_NIC_TIMER
++
++/*
++ * Maximum Transmit/Receive Frame Descriptors for NIC's MAC frame
++ */
++#ifdef FREE_TX_SKB_MULTI
++#define STAR_NIC_MAX_TFD_NUM 48
++#define STAR_NIC_MAX_RFD_NUM 256
++#else
++#define STAR_NIC_MAX_TFD_NUM 48 // FIXME: original 64 will cause UDP fail
++#define STAR_NIC_MAX_RFD_NUM 64
++#endif
++
++
++#define LAN_PORT 1
++
++typedef struct
++{
++ u32 mib_rx_ok_pkt;
++ u32 mib_rx_ok_byte;
++ u32 mib_rx_runt;
++ u32 mib_rx_over_size;
++ u32 mib_rx_no_buffer_drop;
++ u32 mib_rx_crc_err;
++ u32 mib_rx_arl_drop;
++ u32 mib_rx_myvid_drop;
++ u32 mib_rx_csum_err;
++ u32 mib_rx_pause_frame;
++ u32 mib_tx_ok_pkt;
++ u32 mib_tx_ok_byte;
++ u32 mib_tx_pause_frame;
++} mib_info_t;
++
++/* store this information for the driver.. */
++struct star_nic_private {
++ struct napi_struct napi;
++ struct net_device *dev;
++ struct net_device_stats stats;
++ spinlock_t lock;
++ int dev_index;
++ u8 phy_addr;
++ u16 phy_id;
++ mib_info_t mib_info;
++};
++
++/*
++ * Network Driver, Receive/Send and Initial Buffer Function
++ */
++typedef struct {
++ // 1st 32Bits
++ u32 data_ptr;
++
++ // 2nd 32Bits
++ u32 length:16;
++ u32 reserved0:7;
++ u32 tco:1;
++ u32 uco:1;
++ u32 ico:1;
++ u32 insv:1;
++ u32 intr:1;
++ u32 ls:1;
++ u32 fs:1;
++ u32 eor:1;
++ u32 cown:1;
++
++ // 3rd 32Bits
++ u32 vid:12;
++ u32 cfi:1;
++ u32 pri:3;
++ u32 epid:16;
++
++ // 4th 32Bits
++ u32 reserved1;
++} __attribute__((packed)) STAR_NIC_TXDESC;
++
++typedef struct {
++ // 1st 32Bits
++ u32 data_ptr;
++
++ // 2nd 32Bits
++ u32 length:16;
++ u32 l4f:1;
++ u32 ipf:1;
++ u32 prot:2;
++ u32 vted:1;
++ u32 mymac:1;
++ u32 hhit:1;
++ u32 rmc:1;
++ u32 crce:1;
++ u32 osize:1;
++ u32 reserved0:2;
++ u32 ls:1;
++ u32 fs:1;
++ u32 eor:1;
++ u32 cown:1;
++
++ // 3rd 32Bits
++ u32 vid:12;
++ u32 cfi:1;
++ u32 pri:3;
++ u32 epid:16;
++
++ // 4th 32Bits
++ u32 reserved1;
++} __attribute__((packed)) STAR_NIC_RXDESC;
++
++/*
++ * Transmit Frame Descriptor Ring for TFDS
++ */
++typedef struct {
++ u32 phy_addr;
++ STAR_NIC_TXDESC *vir_addr;
++ u32 cur_index; // TX's current will point to Free Descriptors
++#if defined(FREE_TX_SKB_MULTI) || defined(STAR_NIC_TIMER)
++ u32 to_free_index;
++#endif
++ struct sk_buff *skb_ptr[STAR_NIC_MAX_TFD_NUM]; // TX's sk_buff ptr
++} TXRING_INFO;
++
++/*
++ * Receive Frame Descriptor Ring for RFDS
++ */
++typedef struct {
++ u32 phy_addr;
++ STAR_NIC_RXDESC *vir_addr;
++ u32 cur_index;
++ struct sk_buff *skb_ptr[STAR_NIC_MAX_RFD_NUM]; // RX's sk_buff ptr
++} RXRING_INFO;
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,32)
++#define IRQ_RETURN void
++#define IRQ_HANDLED
++static const char star_nic_driver_version[] =
++ "Star NIC Driver(for Linux Kernel 2.4) - Star Semiconductor\n";
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++#define IRQ_RETURN irqreturn_t
++static const char star_nic_driver_version[] =
++ "Star NIC Driver(for Linux Kernel 2.6) - Star Semiconductor\n";
++#endif
++
++//========================================================
++#ifdef CONFIG_STAR_NIC_PHY_INTERNAL_PHY
++#define FE_PHY_LED_MODE (0x1 << 12)
++#define CONFIG_INTERNEL_PHY_PATCH
++#endif
++
++#ifdef CONFIG_INTERNEL_PHY_PATCH
++#define INTERNAL_PHY_PATCH_CHECKCNT 16
++#define INTERNAL_PHY_PATCH_CHECK_PERIOD 1000 //ms
++static struct timer_list internal_phy_timer;
++static void internal_phy_patch_check(int);
++static void internal_phy_update(unsigned long data);
++#endif
++//========================================================
++
++extern void fa_dma_inv_range(unsigned long s, unsigned long e);
++extern void fa_dma_clean_range(unsigned long s, unsigned long e);
++
++#define increase_cyclic(var, limit) {\
++ var++; \
++ if (var>=limit) var=0;\
++ }
++
++//static struct net_device *CUR_NAPI_DEV;
++static struct net_device *STAR_NIC_LAN_DEV;
++
++static int install_isr_account = 0;
++static int is_qf = 0; // determine queue full state
++
++static spinlock_t star_nic_send_lock;
++
++static TXRING_INFO txring;
++static RXRING_INFO rxring;
++
++static struct proc_dir_entry *star_nic_proc_entry;
++
++static u8 default_mac_addr[] = { 0x08, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e };
++
++typedef struct
++{
++ u32 vid; //0~4095
++ u32 control; //ENABLE or DISABLE
++} my_vlan_entry_t;
++
++static my_vlan_entry_t my_vlan_id[4] =
++{
++ { 2, 0}, //value for my_vid0
++ { 2, 1}, //value for my_vid1
++ { 1, 1}, //value for my_vid2
++ { 1, 0} //value for my_vid3
++};
++
++
++#ifdef CONFIG_STAR_NIC_NAPI
++static void star_nic_receive_packet(int mode, int *work_done, int work_to_do);
++#else
++static void star_nic_receive_packet(int mode);
++#endif
++
++static void star_nic_phy_powerdown(struct net_device *dev);
++static void star_nic_phy_powerup(struct net_device *dev);
++
++#ifdef STAR_NIC_TIMER
++static struct timer_list star_nic_timer;
++static void star_nic_timer_func(unsigned long data)
++{
++ int i;
++ int txsd_index;
++ int txsd_current;
++ int skb_free_count = 0;
++ STAR_NIC_TXDESC volatile *txdesc_ptr;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ HAL_NIC_READ_TXSD(txsd_current);
++ txsd_index = (txsd_current - (u32)txring.phy_addr) >> 4;
++ if (txsd_index > txring.to_free_index) {
++ skb_free_count = txsd_index - txring.to_free_index;
++ } else if (txsd_index <= txring.to_free_index) {
++ skb_free_count = STAR_NIC_MAX_TFD_NUM + txsd_index - txring.to_free_index;
++ }
++ for (i = 0; i < skb_free_count; i++) {
++ txdesc_ptr = txring.vir_addr + txring.to_free_index;
++ if (txdesc_ptr->cown == 0) {
++ break;
++ }
++ if (txring.skb_ptr[txring.to_free_index]) {
++ dev_kfree_skb_any(txring.skb_ptr[txring.to_free_index]);
++ txring.skb_ptr[txring.to_free_index] = NULL;
++ }
++ txring.to_free_index++;
++ if (txring.to_free_index == STAR_NIC_MAX_TFD_NUM) {
++ txring.to_free_index = 0;
++ }
++ }
++ local_irq_restore(flags);
++}
++#endif
++
++#if 0
++#define between(x, start, end) ((x)>=(start) && (x)<=(end))
++static void print_packet(unsigned char *data, int len)
++{
++ int i, j;
++
++ printk("packet length: %d%s:\n", len, len>100?"(only show the first 100 bytes)":"");
++ if (len > 100) {
++ len = 100;
++ }
++ for (i = 0; len;) {
++ if (len >=16) {
++ for (j=0;j<16;j++) {
++ printk("%02x ", data[i++]);
++ }
++ printk("| ");
++ i -= 16;
++ for(j=0;j<16;j++) {
++ if (between(data[i], 0x21, 0x7e) ) {
++ printk("%c", data[i++]);
++ } else {
++ printk(".");
++ i++;
++ }
++ }
++ printk("\n");
++ len -= 16;
++ } else {
++ /* last line */
++ for (j = 0; j < len; j++) {
++ printk("%02x ", data[i++]);
++ }
++ for (;j < 16; j++) {
++ printk(" ");
++ }
++ printk("| ");
++ i -= len;
++ for (j = 0;j < len; j++) {
++ if (between(data[i], 0x21, 0x7e)) {
++ printk("%c", data[i++]);
++ } else {
++ printk(".");
++ i++;
++ }
++ }
++ for (; j < 16; j++) {
++ printk(" ");
++ }
++ printk("\n");
++ len = 0;
++ }
++ }
++
++ return;
++}
++#endif /* Disable function print_packet */
++
++#ifdef STAR_NIC_DEBUG
++static void star_nic_show_format_reg(u32 val)
++{
++ int i;
++
++ for (i = 31; i >= 0; i--) {
++ if (val & ((unsigned long)1 << i)) {
++ printk("[%02d:1] ", i);
++ } else {
++ printk("[%02d:0] ", i);
++ }
++ if ((i % 8) == 0) {
++ printk("\n");
++ }
++ }
++ printk("==================================================================\n");
++}
++
++static void star_nic_show_reg(void)
++{
++ u32 reg_val;
++
++ printk("\n");
++
++ reg_val = NIC_MEM_MAP_VALUE(0x000);
++ printk("NIC REG OFF 0x000: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x004);
++ printk("NIC REG OFF 0x004: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x008);
++ printk("NIC REG OFF 0x008: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x00C);
++ printk("NIC REG OFF 0x00C: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x010);
++ printk("NIC REG OFF 0x010: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x014);
++ printk("NIC REG OFF 0x014: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x018);
++ printk("NIC REG OFF 0x018: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x01C);
++ printk("NIC REG OFF 0x01C: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x020);
++ printk("NIC REG OFF 0x020: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x024);
++ printk("NIC REG OFF 0x024: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x028);
++ printk("NIC REG OFF 0x028: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x030);
++ printk("NIC REG OFF 0x030: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x034);
++ printk("NIC REG OFF 0x034: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x038);
++ printk("NIC REG OFF 0x038: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x03C);
++ printk("NIC REG OFF 0x03C: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x040);
++ printk("NIC REG OFF 0x040: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x044);
++ printk("NIC REG OFF 0x044: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x048);
++ printk("NIC REG OFF 0x048: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x04C);
++ printk("NIC REG OFF 0x04C: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x050);
++ printk("NIC REG OFF 0x050: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x054);
++ printk("NIC REG OFF 0x054: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x058);
++ printk("NIC REG OFF 0x058: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++
++ reg_val = NIC_MEM_MAP_VALUE(0x05C);
++ printk("NIC REG OFF 0x05C: 0x%08x\n", reg_val);
++ star_nic_show_format_reg(reg_val);
++}
++#endif
++
++static void star_nic_mib_reset(void)
++{
++ u32 v;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ v = NIC_MIB_RX_OK_PKT_CNTR;
++ v = NIC_MIB_RX_OK_BYTE_CNTR;
++ v = NIC_MIB_RX_RUNT_BYTE_CNTR;
++ v = NIC_MIB_RX_OSIZE_DROP_PKT_CNTR;
++ v = NIC_MIB_RX_NO_BUF_DROP_PKT_CNTR;
++ v = NIC_MIB_RX_CRC_ERR_PKT_CNTR;
++ v = NIC_MIB_RX_ARL_DROP_PKT_CNTR;
++ v = NIC_MIB_MYVLANID_MISMATCH_DROP_PKT_CNTR;
++ v = NIC_MIB_RX_CHKSUM_ERR_PKT_CNTR;
++ v = NIC_MIB_RX_PAUSE_FRAME_PKT_CNTR;
++ v = NIC_MIB_TX_OK_PKT_CNTR;
++ v = NIC_MIB_TX_OK_BYTE_CNTR;
++ v = NIC_MIB_TX_PAUSE_FRAME_CNTR;
++ local_irq_restore(flags);
++}
++
++static void star_nic_mib_read(struct net_device *dev)
++{
++ struct star_nic_private *priv = netdev_priv(dev);
++ unsigned long flags;
++
++ local_irq_save(flags);
++ priv->mib_info.mib_rx_ok_pkt += NIC_MIB_RX_OK_PKT_CNTR;
++ priv->mib_info.mib_rx_ok_byte += NIC_MIB_RX_OK_BYTE_CNTR;
++ priv->mib_info.mib_rx_runt += NIC_MIB_RX_RUNT_BYTE_CNTR;
++ priv->mib_info.mib_rx_over_size += NIC_MIB_RX_OSIZE_DROP_PKT_CNTR;
++ priv->mib_info.mib_rx_no_buffer_drop += NIC_MIB_RX_NO_BUF_DROP_PKT_CNTR;
++ priv->mib_info.mib_rx_crc_err += NIC_MIB_RX_CRC_ERR_PKT_CNTR;
++ priv->mib_info.mib_rx_arl_drop += NIC_MIB_RX_ARL_DROP_PKT_CNTR;
++ priv->mib_info.mib_rx_myvid_drop += NIC_MIB_MYVLANID_MISMATCH_DROP_PKT_CNTR;
++ priv->mib_info.mib_rx_csum_err += NIC_MIB_RX_CHKSUM_ERR_PKT_CNTR;
++ priv->mib_info.mib_rx_pause_frame += NIC_MIB_RX_PAUSE_FRAME_PKT_CNTR;
++ priv->mib_info.mib_tx_ok_pkt += NIC_MIB_TX_OK_PKT_CNTR;
++ priv->mib_info.mib_tx_ok_byte += NIC_MIB_TX_OK_BYTE_CNTR;
++ priv->mib_info.mib_tx_pause_frame += NIC_MIB_TX_PAUSE_FRAME_CNTR;
++ local_irq_restore(flags);
++}
++
++static int star_nic_write_phy(u8 phy_addr, u8 phy_reg, u16 write_data)
++{
++ int i;
++
++ if (phy_addr > 31) {
++ return 0;
++ }
++
++ //clear previous rw_ok status
++ NIC_PHY_CONTROL_REG0 = (0x1 << 15);
++
++ NIC_PHY_CONTROL_REG0 = ((phy_addr & 0x1F) |
++ ((phy_reg & 0x1F) << 8) |
++ (0x1 << 13) |
++ ((write_data & 0xFFFF) << 16));
++
++ for (i = 0; i < 10000; i++) {
++ // if write command completed
++ if ((NIC_PHY_CONTROL_REG0) & (0x1 << 15)) {
++ // clear the rw_ok status, and clear other bits value
++ NIC_PHY_CONTROL_REG0 = (0x1 << 15);
++ return (0); /* for ok indication */
++ }
++ udelay(1000);
++ }
++
++ printk("star_nic_write_phy() failed!! phy_addr:0x%x phy_reg:0x%x write_data:0x%x\n",
++ phy_addr, phy_reg, write_data);
++ return (-1); /* for failure indication */
++}
++
++static int star_nic_read_phy(u8 phy_addr, u8 phy_reg, u16 *read_data)
++{
++ u32 status;
++ int i;
++
++ if (phy_addr > 31) {
++ return 0;
++ }
++
++ // clear previous rw_ok status
++ NIC_PHY_CONTROL_REG0 = (0x1 << 15);
++
++ NIC_PHY_CONTROL_REG0 = ((phy_addr & 0x1F) |
++ ((phy_reg & 0x1F) << 8) |
++ (0x1 << 14));
++
++ for (i = 0; i < 10000; i++) {
++ status = NIC_PHY_CONTROL_REG0;
++ if (status & (0x1 << 15)) {
++ // clear the rw_ok status, and clear other bits value
++ NIC_PHY_CONTROL_REG0 = (0x1 << 15);
++ *read_data = (u16)((status >> 16) & 0xFFFF);
++ return (0); /* for ok indication */
++ }
++ udelay(1000);
++ }
++
++ printk("star_nic_read_phy() failed!! phy_addr:0x%x phy_reg:0x%x\n",
++ phy_addr, phy_reg);
++ return (-1); /* for failure indication */
++}
++
++static int star_nic_dma_config(struct net_device *dev)
++{
++ u32 dma_config = 0;
++
++ dma_config = NIC_DMA_CONFIG_REG;
++
++#if 1
++ /* Config TX DMA */
++ dma_config &= ~(0x3 << 6); //TX auto polling :1 us
++ //dma_config |= (0x1 << 6); //TX auto polling :10 us
++ dma_config |= (0x2 << 6); //TX auto polling :100us
++ //dma_config |= (0x3 << 6); //TX auto polling :1000us
++ dma_config |= (0x1 << 5); //TX auto polling C-bit enable
++ dma_config &= ~(0x1 << 4); //TX can transmit packets,No suspend
++#endif
++
++#if 1
++ /* Config RX DMA */
++ dma_config &= ~(0x3 << 2); //RX auto polling :1 us
++ //dma_config |= (0x1 << 2); //RX auto polling :10 us
++ dma_config |= (0x2 << 2); //RX auto polling :100us
++ //dma_config |= (0x3 << 2); //RX auto polling :1000us
++ dma_config |= (0x1 << 1); //RX auto polling C-bit enable
++ dma_config &= ~0x1; //RX can receive packets, No suspend
++#endif
++
++ // 4N+2(for Linux)
++ dma_config &= ~(0x1 << 16);
++ // 4N
++ //dma_config |= (0x1 << 16);
++
++ NIC_DMA_CONFIG_REG = dma_config;
++
++ return 0;
++}
++
++static int star_nic_mac_config(struct net_device *dev)
++{
++ u32 mac_config;
++
++ mac_config = NIC_MAC_CONTROL_REG;
++
++#ifdef STAR_NIC_TX_HW_CHECKSUM
++ // Tx ChkSum offload On: TCP/UDP/IP
++ mac_config |= (0x1 << 26);
++#else
++ // Tx ChkSum offload Off: TCP/UDP/IP
++ mac_config &= ~(0x1 << 26);
++#endif
++
++#ifdef STAR_NIC_RX_HW_CHECKSUM
++ // Rx ChkSum offload On: TCP/UDP/IP
++ mac_config |= (0x1 << 25);
++#else
++ // Rx ChkSum offload Off: TCP/UDP/IP
++ mac_config &= ~(0x1 << 25);
++#endif
++
++ mac_config |= (0x1 << 24); // Accept CSUM error pkt
++ //mac_config &= ~(0x1 << 24); // Discard CSUM error pkt
++
++ //mac_config |= (0x1 << 23); // IST Enable
++ mac_config &= ~(0x1 << 23); // IST disable
++
++ mac_config |= (0x1 << 22); // Strip vlan tag
++ //mac_config &= ~(0x1 << 22); // Keep vlan tag
++
++ mac_config |= (0x1 << 21); // Accept CRC error pkt
++ //mac_config &= ~(0x1 << 21); // Disacrd CRC error pkt
++
++ mac_config |= (0x1 << 20); // CRC strip
++ //mac_config &= ~(0x1 << 20); // Keep CRC
++
++#ifdef CONFIG_STAR_JUMBO
++ mac_config |= (0x1 << 18); // Accept oversize pkt
++#else
++ mac_config &= ~(0x1 << 18); // Discard oversize pkt
++#endif
++
++ mac_config &= ~(0x3 << 16); // clear, set 1518
++
++#ifdef CONFIG_STAR_JUMBO
++ mac_config |= (0x3 << 16); //set reserved, for jumbo frame
++#else
++ mac_config |= (0x2 << 16); // 1536
++ //mac_config |= (0x1 << 16); // 1522
++#endif
++
++ // IPG
++ mac_config |= (0x1f << 10);
++
++ // Do not skip 16 consecutive collisions pkt
++ mac_config |= (0x1 << 9); // allow to re-tx
++ //mac_config &= ~(0x1 << 9); // drop pkt
++
++ mac_config |= (0x1 << 8); // Fast retry
++ //mac_config &= ~(0x1 << 8); // standard
++
++ NIC_MAC_CONTROL_REG = mac_config;
++
++ return 0;
++}
++
++static int star_nic_fc_config(struct net_device *dev)
++{
++ u32 fc_config;
++
++ fc_config = NIC_FLOW_CONTROL_CONFIG_REG;
++
++ // Send pause on frame threshold
++ fc_config &= ~(0xfff << 16); // Clear
++ fc_config |= (0x360 << 16); // Set
++
++ //fc_config |= (0x1 << 8); // Enable UC_PAUSE
++ fc_config &= ~(0x1 << 8); // Disable UC_PAUSE
++
++ fc_config |= (0x1 << 7); // Enable Half Duplex backpressure
++ //fc_config &= ~(0x1 << 7); // Disable Half Duplex backpressure
++
++ //fc_config |= (0x1 << 6); // CRS-based BP
++ fc_config &= ~(0x1 << 6); // Collision-based BP
++
++ //fc_config |= (0x1 << 5); // Enable max BP collision
++ fc_config &= ~(0x1 << 5); // Disable max BP collision
++
++ // max BP collision count
++ fc_config &= ~(0x1f); // Clear
++ fc_config |= (0xc); // Set
++
++ NIC_FLOW_CONTROL_CONFIG_REG = fc_config;
++
++ return 0;
++}
++
++static int star_nic_phy_config(struct net_device *dev)
++{
++ struct star_nic_private *priv = netdev_priv(dev);
++ u32 phy_config = NIC_PHY_CONTROL_REG1;
++#ifdef CONFIG_STAR_NIC_PHY_VSC8601
++ u32 phy_addr=0;
++#endif /* CONFIG_STAR_NIC_PHY_VSC8601 */
++ //int i;
++
++#ifdef CONFIG_STAR_NIC_PHY_INTERNAL_PHY
++ printk("Star Internal PHY\n");
++
++#if 0
++ {
++ u16 phy_data;
++ // restart the internal phy
++ star_nic_write_phy(STAR_NIC_PHY_ADDR, 0, 0x8000);
++ while (1) {
++ star_nic_read_phy(STAR_NIC_PHY_ADDR, 0, &phy_data);
++ if ( (phy_data&0x8000) ==0x0000) { // phy now at normal mode
++ break;
++ }
++ }
++ }
++#endif
++
++ priv->phy_addr = STAR_NIC_PHY_ADDR;
++ // set phy addr for auto-polling
++ phy_config |= (priv->phy_addr & 0x1f) << 24;
++
++ // set internal phy mode
++ // internel 10/100 phy
++ phy_config |= 0x1 << 18;
++
++ // MII
++ phy_config &= ~(0x1 << 17);
++
++ // MAC mode
++ phy_config &= ~(0x1 << 16);
++
++ // config PHY LED bit[13:12]
++ star_nic_read_phy(priv->phy_addr, 31, (u16 *)(&phy_config));
++ phy_config &= ~(0x3 << 12); // clear LED control
++ phy_config |= FE_PHY_LED_MODE;
++ star_nic_write_phy(priv->phy_addr, 31, phy_config);
++#endif
++#ifdef CONFIG_STAR_NIC_PHY_VSC8601
++ u16 phy_data;
++
++ printk("VSC8601 Chip\n");
++
++ // phy addr for auto-polling
++ phy_config |= ((phy_addr & 0x1f) << 24);
++
++ // set external phy mode
++ phy_config &= ~(0x1 << 18);
++
++ // set RGMII
++ phy_config |= (0x1 << 17);
++
++ // set MII interface
++ phy_config &= ~(0x1 << 16);
++
++ NIC_PHY_CONTROL_REG1 = phy_config;
++//=========================================================
++
++ priv->phy_addr = STAR_NIC_PHY_ADDR;
++ // set phy addr for auto-polling
++ phy_config |= (priv->phy_addr & 0x1f) << 24;
++
++ // set external phy mode
++ // MII/RGMII interface
++ phy_config &= ~(0x1 << 18);
++
++ // RGMII
++ phy_config |= (0x1 << 17);
++
++ // MAC mode
++ phy_config &= ~(0x1 << 16);
++
++ star_nic_read_phy(priv->phy_addr, 3, &phy_data);
++ if ((phy_data & 0x000f) == 0x0000) { // type A chip
++ u16 tmp16;
++
++ printk("VSC8601 Type A Chip\n");
++ star_nic_write_phy(priv->phy_addr, 31, 0x52B5);
++ star_nic_write_phy(priv->phy_addr, 16, 0xAF8A);
++
++ phy_data = 0x0;
++ star_nic_read_phy(priv->phy_addr, 18, &tmp16);
++ phy_data |= (tmp16 & ~0x0);
++ star_nic_write_phy(priv->phy_addr, 18, phy_data);
++
++ phy_data = 0x0008;
++ star_nic_read_phy(priv->phy_addr, 17, &tmp16);
++ phy_data |= (tmp16 & ~0x000C);
++ star_nic_write_phy(priv->phy_addr, 17, phy_data);
++
++ star_nic_write_phy(priv->phy_addr, 16, 0x8F8A);
++
++ star_nic_write_phy(priv->phy_addr, 16, 0xAF86);
++
++ phy_data = 0x0008;
++ star_nic_read_phy(priv->phy_addr, 18, &tmp16);
++ phy_data |= (tmp16 & ~0x000C);
++ star_nic_write_phy(priv->phy_addr, 18, phy_data);
++
++ phy_data = 0x0;
++ star_nic_read_phy(priv->phy_addr, 17, &tmp16);
++ phy_data |= (tmp16 & ~0x0);
++ star_nic_write_phy(priv->phy_addr, 17, phy_data);
++
++ star_nic_write_phy(priv->phy_addr, 16, 0x8F8A);
++
++ star_nic_write_phy(priv->phy_addr, 16, 0xAF82);
++
++ phy_data = 0x0;
++ star_nic_read_phy(priv->phy_addr, 18, &tmp16);
++ phy_data |= (tmp16 & ~0x0);
++ star_nic_write_phy(priv->phy_addr, 18, phy_data);
++
++ phy_data = 0x0100;
++ star_nic_read_phy(priv->phy_addr, 17, &tmp16);
++ phy_data |= (tmp16 & ~0x0180);
++ star_nic_write_phy(priv->phy_addr, 17, phy_data);
++
++ star_nic_write_phy(priv->phy_addr, 16, 0x8F82);
++
++ star_nic_write_phy(priv->phy_addr, 31, 0x0);
++
++ //Set port type: single port
++ star_nic_read_phy(priv->phy_addr, 9, &phy_data);
++ phy_data &= ~(0x1 << 10);
++ star_nic_write_phy(priv->phy_addr, 9, phy_data);
++ } else if ((phy_data & 0x000f) == 0x0001) { // type B chip
++ printk("VSC8601 Type B Chip\n");
++ star_nic_read_phy(priv->phy_addr, 23, &phy_data);
++ phy_data |= ( 0x1 << 8); //set RGMII timing skew
++ star_nic_write_phy(priv->phy_addr, 23, phy_data);
++ }
++
++ // change to extened registers
++ star_nic_write_phy(priv->phy_addr, 31, 0x0001);
++
++ star_nic_read_phy(priv->phy_addr, 28, &phy_data);
++ phy_data &= ~(0x3 << 14); // set RGMII TX timing skew
++ phy_data |= (0x3 << 14); // 2.0ns
++ phy_data &= ~(0x3 << 12); // set RGMII RX timing skew
++ phy_data |= (0x3 << 12); // 2.0ns
++ star_nic_write_phy(priv->phy_addr, 28, phy_data);
++
++ // change to normal registers
++ star_nic_write_phy(priv->phy_addr, 31, 0x0000);
++
++ // set TX and RX clock skew
++ //NIC_TEST_0_REG = (0x2 << 2) | (0x2 << 0);
++
++#endif
++
++#ifdef CONFIG_STAR_NIC_PHY_IP101A
++ // ICPlus IP101A
++ printk("ICPlus IP101A\n");
++ priv->phy_addr = 1;
++ // set phy addr for auto-polling
++ phy_config |= (priv->phy_addr & 0x1f) << 24;
++
++ // set external phy mode
++ // MII/RGMII interface
++ phy_config &= ~(0x1 << 18);
++
++ // MII
++ phy_config &= ~(0x1 << 17);
++
++ // MAC mode
++ phy_config &= ~(0x1 << 16);
++#endif
++
++/* robin 080102 */
++/* added ICPlus IP1001 support */
++#ifdef CONFIG_STAR_NIC_PHY_IP1001
++u16 phy_data;
++
++u32 phy_addr = 1;
++
++phy_config = NIC_PHY_CONTROL_REG1;
++
++ // set phy addr for auto-polling
++ phy_config |= ((phy_addr & 0x1f) << 24);
++
++ // set external phy mode
++ // MII/RGMII interface
++ phy_config &= ~(0x1 << 18);
++
++ // RGMII
++ phy_config |= (0x1 << 17);
++
++ // MAC mode
++ phy_config &= ~(0x1 << 16);
++
++ NIC_PHY_CONTROL_REG1 = phy_config;
++ star_nic_read_phy(phy_addr,2,&phy_data);
++ //printf("\n phy.reg2=0x%04x",phy_data);
++
++#if 1//set AN capability
++
++
++ star_nic_read_phy(phy_addr,4,&phy_data);
++
++ phy_data &= ~(0xf<<5);//clear
++ phy_data |= (0x1<<5); //10Half
++ phy_data |= (0x1<<6); //10Full
++ phy_data |= (0x1<<7); //100Half
++ phy_data |= (0x1<<8); //100Full
++// phy_data &= ~(0x1<<10); //FC off
++ phy_data |= (0x1<<10); //FC on
++ star_nic_write_phy(phy_addr,4,phy_data);
++
++
++ star_nic_read_phy(phy_addr,9,&phy_data);
++
++ phy_data |= (0x1<<9); //1000Full on
++
++ phy_data &= ~(0x1<<10);
++
++ phy_data |= (0x1<<12);
++
++ star_nic_write_phy(phy_addr,9,phy_data);
++
++
++
++
++ star_nic_read_phy(phy_addr,16,&phy_data);
++
++ phy_data &= ~(0x1<<11); //Smart function off
++
++ phy_data |= (0x1<<0); //TX delay
++
++ phy_data |= (0x1<<1); //RX delay
++
++ star_nic_write_phy(phy_addr,16,phy_data);
++
++ star_nic_read_phy(phy_addr,16,&phy_data);
++ //printf("\n phy.reg16=0x%04x",phy_data);
++
++
++// Hal_Nic_Read_PHY(NIC_PHY_ADDRESS,20,&phy_data);
++//
++// phy_data &= ~(0x1<<2);
++//
++// phy_data |= (0x1<<9);
++// Hal_Nic_Write_PHY(NIC_PHY_ADDRESS,20,phy_data);
++
++
++
++
++ star_nic_read_phy(phy_addr,0,&phy_data);
++ phy_data |= (0x1<<9); //re-AN
++ star_nic_write_phy(phy_addr,0,phy_data);
++
++
++ star_nic_read_phy(phy_addr,9,&phy_data);
++ //printf("\n phy.reg9=0x%04x",phy_data);
++
++
++#endif
++#endif // CONFIG_STAR_NIC_PHY_IP1001
++/* robin 080102 - end of modification */
++
++
++
++ phy_config |= (0x1 << 8); // AN On
++ //phy_config &= ~(0x1 << 8); // AN off
++
++ if (!((phy_config >> 8) & 0x1)) { // AN disbale
++ // Force to FullDuplex mode
++ phy_config &= ~(0x1 << 11); // Half
++
++ // Force to 100Mbps mode
++ phy_config &= ~(0x3 << 9); // clear to 10M
++ phy_config |= (0x1 << 9); // set to 100M
++ }
++
++ // Force TX FlowCtrl On,in 1000M
++ phy_config |= (0x1 << 13);
++
++ // Force TX FlowCtrl On, in 10/100M
++ phy_config |= (0x1 << 12);
++
++ // Enable MII auto polling
++ phy_config &= ~(0x1 << 7); // auto-polling enable
++ //phy_config |= (0x1 << 7); // auto-polling disable
++
++ NIC_PHY_CONTROL_REG1 = phy_config;
++#if 1
++ star_nic_phy_powerdown(dev);
++#endif
++
++ return 0;
++}
++
++static int star_nic_vlan_config(struct net_device *dev)
++{
++ u32 vlan_id;
++
++ //1.Setup MyVLAN ID0_1
++ vlan_id = 0; //clear
++ vlan_id |= (my_vlan_id[0].vid & 0x0fff);
++ vlan_id |= ((my_vlan_id[1].vid & 0x0fff) << 16);
++ NIC_MY_VLANID_0_1 = vlan_id;
++
++ //2.Setup MyVLAN ID2_3
++ vlan_id = 0; //clear
++ vlan_id |= (my_vlan_id[2].vid & 0x0fff);
++ vlan_id |= ((my_vlan_id[3].vid & 0x0fff) << 16);
++ NIC_MY_VLANID_2_3 = vlan_id;
++
++ //3.Setup vlan_id control bits
++ NIC_MY_VLANID_CONTROL_REG = ( (my_vlan_id[0].control << 0) |
++ (my_vlan_id[1].control << 1) |
++ (my_vlan_id[2].control << 2) |
++ (my_vlan_id[3].control << 3) );
++
++ return 0;
++}
++
++static int star_nic_arl_config(struct net_device *dev)
++{
++ u32 arl_config;
++
++ arl_config = NIC_ARL_CONFIG_REG;
++ arl_config |= (0x1 << 4); // Misc Mode ON
++ //arl_config &= ~(0x1 << 4); // Misc Mode Off
++ arl_config |= (0x1 << 3); // My MAC only enable
++ arl_config &= ~(0x1 << 2); // Learn SA On
++ arl_config &= ~(0x1 << 1); // Forward MC to CPU
++ arl_config &= ~(0x1); // Hash direct mode
++ NIC_ARL_CONFIG_REG = arl_config;
++
++ return 0;
++}
++
++#if 0
++static void star_nic_interrupt_disable(void)
++{
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_NIC_STATUS_BIT_INDEX);
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_NIC_TXTC_BIT_INDEX);
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_NIC_RXRC_BIT_INDEX);
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_NIC_TXQE_BIT_INDEX);
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_NIC_RXQF_BIT_INDEX);
++}
++#endif /* Disable function star_nic_interrupt_disable */
++
++static void star_nic_interrupt_enable(void)
++{
++#ifdef STAR_NIC_STATUS_ISR
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_NIC_STATUS_BIT_INDEX);
++#endif
++
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_NIC_RXRC_BIT_INDEX);
++
++#ifdef STAR_NIC_RXQF_ISR
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_NIC_RXQF_BIT_INDEX);
++#endif
++}
++
++#if 0
++static int star_nic_show_rxdesc(char *page)
++{
++ int i;
++ int num = 0;
++ u32 rxsd_current;
++ int rxsd_index;
++ STAR_NIC_RXDESC volatile *rxdesc_ptr = rxring.vir_addr;
++
++ HAL_NIC_READ_RXSD(rxsd_current);
++ rxsd_index = (rxsd_current - (u32)rxring.phy_addr) >> 4;
++
++ num += sprintf(page + num, "rxring.cur_index: %d\n", rxring.cur_index);
++ num += sprintf(page + num, "rxsd_index: %d\n", rxsd_index);
++
++ for (i = 0; i < STAR_NIC_MAX_RFD_NUM; i++) {
++ num += sprintf(page + num, "rxring[%02d].cown ==> %d\n", i, rxdesc_ptr->cown);
++ rxdesc_ptr++;
++ }
++
++ return num;
++}
++#endif /* Disable function star_nic_show_rxdesc */
++
++#if 0
++static int star_nic_show_txdesc(char *page)
++{
++ int i;
++ int num = 0;
++ u32 txsd_current;
++ int txsd_index;
++ STAR_NIC_TXDESC volatile *txdesc_ptr = txring.vir_addr;
++
++ HAL_NIC_READ_TXSD(txsd_current);
++ txsd_index = (txsd_current - (u32)txring.phy_addr) >> 4;
++
++ num += sprintf(page + num, "txring.cur_index: %d\n", txring.cur_index);
++ num += sprintf(page + num, "txsd_index: %d\n", txsd_index);
++
++ for (i = 0; i < STAR_NIC_MAX_TFD_NUM; i++) {
++ num += sprintf(page + num, "txring[%02d].cown ==> %d\n", i, txdesc_ptr->cown);
++ txdesc_ptr++;
++ }
++
++ return num;
++}
++#endif /* star_nic_show_txdesc */
++
++static int star_nic_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
++{
++ struct star_nic_private *priv = netdev_priv(STAR_NIC_LAN_DEV);
++ int num = 0;
++
++ star_nic_mib_read(STAR_NIC_LAN_DEV);
++ num += sprintf(page + num, "mib_rx_ok_pkt %08d\n", priv->mib_info.mib_rx_ok_pkt);
++ num += sprintf(page + num, "mib_rx_ok_byte %08d\n", priv->mib_info.mib_rx_ok_byte);
++ num += sprintf(page + num, "mib_rx_runt %08d\n", priv->mib_info.mib_rx_runt);
++ num += sprintf(page + num, "mib_rx_over_size %08d\n", priv->mib_info.mib_rx_over_size);
++ num += sprintf(page + num, "mib_rx_no_buffer_drop %08d\n", priv->mib_info.mib_rx_no_buffer_drop);
++ num += sprintf(page + num, "mib_rx_crc_err %08d\n", priv->mib_info.mib_rx_crc_err);
++ num += sprintf(page + num, "mib_rx_arl_drop %08d\n", priv->mib_info.mib_rx_arl_drop);
++ num += sprintf(page + num, "mib_rx_myvid_drop %08d\n", priv->mib_info.mib_rx_myvid_drop);
++ num += sprintf(page + num, "mib_rx_csum_err %08d\n", priv->mib_info.mib_rx_csum_err);
++ num += sprintf(page + num, "mib_rx_pause_frame %08d\n", priv->mib_info.mib_rx_pause_frame);
++ num += sprintf(page + num, "mib_tx_ok_pkt %08d\n", priv->mib_info.mib_tx_ok_pkt);
++ num += sprintf(page + num, "mib_tx_ok_byte %08d\n", priv->mib_info.mib_tx_ok_byte);
++ num += sprintf(page + num, "mib_tx_pause_frame %08d\n", priv->mib_info.mib_tx_pause_frame);
++
++ //num += star_nic_show_rxdesc(page + num);
++ //num += star_nic_show_txdesc(page + num);
++
++ return num;
++}
++
++
++static int
++star_nic_write_proc(struct file *file, const char __user *buffer,
++ unsigned long count, void *data)
++{
++ char *str;
++ char *cmd;
++
++ if (count > 0) {
++ str = (char *)buffer,
++ cmd = strsep(&str, "\t \n");
++ if (!cmd) goto err_out;
++ if (strcmp(cmd, "clear") == 0) {
++ struct star_nic_private *priv = netdev_priv(STAR_NIC_LAN_DEV);
++
++ star_nic_mib_read(STAR_NIC_LAN_DEV);
++ memset(&priv->mib_info,0,sizeof(priv->mib_info));
++
++ //} else if (strcmp(cmd, "write") == 0) {
++ } else {
++ goto err_out;
++ }
++ }
++
++ return count;
++
++err_out:
++ return -EFAULT;
++}
++
++static void star_nic_phy_powerdown(struct net_device *dev)
++{
++ struct star_nic_private *priv = netdev_priv(dev);
++ u16 phy_data = 0;
++ // power down the PHY
++ star_nic_read_phy(priv->phy_addr, 0, &phy_data);
++ phy_data |= (0x1 << 11);
++ star_nic_write_phy(priv->phy_addr, 0, phy_data);
++
++ // set hight
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 15);
++ // set low
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG &= ~(0x1 << 15);
++}
++
++static void star_nic_phy_powerup(struct net_device *dev)
++{
++ struct star_nic_private *priv = netdev_priv(dev);
++ u16 phy_data = 0;
++ // power up the PHY
++ star_nic_read_phy(priv->phy_addr, 0, &phy_data);
++ phy_data &= ~(0x1 << 11);
++ star_nic_write_phy(priv->phy_addr, 0, phy_data);
++
++ // set hight
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 15);
++}
++
++static void star_nic_enable(struct net_device *dev)
++{
++#if 0
++ // enable NIC clock
++ HAL_PWRMGT_ENABLE_NIC_CLOCK();
++ NIC_MAC_CONTROL_REG &= ~((u32)0x3 << 30);
++ udelay(100);
++#endif
++
++ star_nic_interrupt_enable();
++ HAL_NIC_RX_DMA_START();
++#if 1
++ star_nic_phy_powerup(dev);
++#endif
++#ifdef CONFIG_INTERNEL_PHY_PATCH
++ printk("%s: starting patch check.\n", __FUNCTION__);
++ internal_phy_patch_check(1);
++ mod_timer(&internal_phy_timer, jiffies + INTERNAL_PHY_PATCH_CHECK_PERIOD / 10);
++#endif
++
++}
++
++static void star_nic_shutdown(struct net_device *dev)
++{
++ if (install_isr_account == 0) {
++ DBG_PRINT("disable port 0\n");
++ HAL_NIC_RX_DMA_STOP();
++ HAL_NIC_TX_DMA_STOP();
++#if 0
++ NIC_MAC_CONTROL_REG |= ((u32)0x1 << 31);
++ while (!(NIC_MAC_CONTROL_REG & (0x1 << 29))) {
++ udelay(1000);
++ }
++ HAL_PWRMGT_DISABLE_NIC_CLOCK();
++ NIC_MAC_CONTROL_REG |= (0x1 <<29);
++#endif
++#ifdef CONFIG_INTERNEL_PHY_PATCH
++ printk("%s: stoping patch check.\n", __FUNCTION__);
++ del_timer_sync(&internal_phy_timer);
++#endif
++ }
++}
++
++IRQ_RETURN star_nic_receive_isr(int irq, void *dev_id, struct pt_regs *regs)
++{
++ struct star_nic_private *priv = netdev_priv(STAR_NIC_LAN_DEV);
++#ifdef CONFIG_STAR_NIC_NAPI
++ if (!test_bit(5, &STAR_NIC_LAN_DEV->state))
++ napi_schedule(&priv->napi);
++#else
++#ifndef CONFIG_VIC_INTERRUPT
++ // TODO: mask interrupt
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_NIC_RXRC_BIT_INDEX);
++#endif
++ // MASK Interrupt
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_NIC_RXRC_BIT_INDEX);
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_NIC_RXQF_BIT_INDEX);
++
++ star_nic_receive_packet(0); // Receive Once
++
++ // TODO: unmask interrupt
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_NIC_RXRC_BIT_INDEX);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_NIC_RXQF_BIT_INDEX);
++#endif
++
++ return IRQ_HANDLED;
++}
++
++#ifdef STAR_NIC_RXQF_ISR
++IRQ_RETURN star_nic_rxqf_isr(int irq, void *dev_id, struct pt_regs *regs)
++{
++ struct star_nic_private *priv = netdev_priv(STAR_NIC_LAN_DEV);
++#ifndef CONFIG_VIC_INTERRUPT
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_NIC_RXQF_BIT_INDEX);
++#endif
++#ifdef CONFIG_STAR_NIC_NAPI
++ // because in normal state, fsql only invoke once and set_bit is atomic function.
++ // so I don't mask it.
++ set_bit(0, (unsigned long *)&is_qf);
++ if (!test_bit(5, &STAR_NIC_LAN_DEV->state))
++ napi_schedule(&priv->napi);
++#else
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_NIC_RXRC_BIT_INDEX);
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_NIC_RXQF_BIT_INDEX);
++
++ star_nic_receive_packet(1); // Receive at Queue Full Mode
++
++ // TODO: unmask interrupt
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_NIC_RXRC_BIT_INDEX);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_NIC_RXQF_BIT_INDEX);
++#endif
++
++ return IRQ_HANDLED;
++}
++#endif
++
++#ifdef CONFIG_PM
++int inline str8100_nic_resume();
++int inline str8100_nic_suspend(suspend_state_t state);
++#endif
++
++#ifdef STAR_NIC_STATUS_ISR
++
++IRQ_RETURN star_nic_status_isr(int irq, void *dev_id, struct pt_regs *regs)
++{
++ u32 int_status;
++#ifdef CONFIG_PM
++ extern int nic_suspended;
++ u32 nic_suspended_tmp=nic_suspended;
++#endif
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_NIC_STATUS_BIT_INDEX);
++ HAL_NIC_READ_INTERRUPT_STATUS(int_status);
++
++ //printk("%s: NIC status:%08X \n",__FUNCTION__, int_status);
++
++ if (int_status & 0x8) {
++ star_nic_mib_read((struct net_device *)STAR_NIC_LAN_DEV);
++ }
++
++#ifdef CONFIG_PM
++ if ((int_status & 0x10)&&nic_suspended_tmp) {
++// printk("W\n");
++ str8100_nic_resume();
++ }
++#endif
++ HAL_NIC_CLEAR_INTERRUPT_STATUS_SOURCES(int_status);
++#ifdef CONFIG_PM
++ if ((int_status & 0x10)&&nic_suspended_tmp) {
++ str8100_nic_suspend(0);
++ }
++#endif
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_NIC_STATUS_BIT_INDEX);
++
++ return IRQ_HANDLED;
++}
++#endif // STAR_NIC_STATUS_ISR
++
++static int star_nic_uninstall_isr(struct net_device *dev)
++{
++ --install_isr_account;
++
++ if (install_isr_account == 0) {
++ printk("star nic uninstall isr\n");
++ free_irq(INTC_NIC_RXRC_BIT_INDEX, STAR_NIC_LAN_DEV);
++
++#ifdef STAR_NIC_RXQF_ISR
++ free_irq(INTC_NIC_RXQF_BIT_INDEX, STAR_NIC_LAN_DEV);
++#endif
++
++#ifdef STAR_NIC_STATUS_ISR
++ free_irq(INTC_NIC_STATUS_BIT_INDEX, STAR_NIC_LAN_DEV);
++#endif
++ }
++
++ return 0;
++}
++
++static int star_nic_install_isr(struct net_device *dev)
++{
++ int retval;
++
++ if (install_isr_account == 0) {
++#ifdef STAR_NIC_DELAYED_INTERRUPT
++ NIC_DELAYED_INT_CONFIG_REG = (1 << 16) | ((MAX_PEND_INT_CNT & 0xFF) << 8) | (MAX_PEND_TIME & 0xFF);
++#endif
++ retval = request_irq(INTC_NIC_RXRC_BIT_INDEX, &star_nic_receive_isr, IRQF_SHARED, "NIC RXRC INT", STAR_NIC_LAN_DEV);
++
++ if (retval) {
++ DO_PRINT("%s: unable to get IRQ %d (irqval=%d).\n", "NIC RXRC INT", INTC_NIC_RXRC_BIT_INDEX, retval);
++ return 1;
++ }
++
++#ifdef STAR_NIC_RXQF_ISR
++ /* QUEUE full interrupt handler */
++ retval = request_irq(INTC_NIC_RXQF_BIT_INDEX, &star_nic_rxqf_isr, IRQF_SHARED, "NIC RXQF INT", STAR_NIC_LAN_DEV);
++
++ if (retval) {
++ DO_PRINT("%s: unable to get IRQ %d (irqval=%d).\n", "NIC RXQF INT", INTC_NIC_RXQF_BIT_INDEX, retval);
++ return 2;
++ }
++#endif
++
++#ifdef STAR_NIC_STATUS_ISR
++ /* NIC Status interrupt handler */
++ retval = request_irq(INTC_NIC_STATUS_BIT_INDEX, &star_nic_status_isr, IRQF_SHARED, "NIC STATUS", STAR_NIC_LAN_DEV);
++
++ if (retval) {
++ DO_PRINT("%s: unable to get IRQ %d (irqval=%d).\n", "NIC STATUS INT", INTC_NIC_STATUS_BIT_INDEX, retval);
++ return 3;
++ }
++ //HAL_NIC_ENABLE_ALL_INTERRUPT_STATUS_SOURCES();
++ HAL_NIC_DISABLE_ALL_INTERRUPT_STATUS_SOURCES();
++ //Enable NIC Status Interrupt: MIB counter th (3)
++ HAL_NIC_ENABLE_INTERRUPT_STATUS_SOURCE_BIT(3);
++
++#endif
++ } // end if(install_isr_account == 0)
++
++ ++install_isr_account;
++
++ return 0;
++}
++
++static int star_nic_lan_open(struct net_device *dev)
++{
++ DBG_PRINT("%s:star_nic_lan_open\n", dev->name);
++
++#ifdef MODULE
++ MOD_INC_USE_COUNT;
++#endif
++
++ //CUR_NAPI_DEV = dev;
++ //
++ struct star_nic_private *priv = netdev_priv(dev);
++ napi_enable(&priv->napi);
++
++ netif_start_queue(dev);
++
++ star_nic_install_isr(dev);
++
++ star_nic_enable(dev);
++
++ return 0;
++}
++
++static struct net_device_stats *star_nic_get_stats(struct net_device *dev)
++{
++ struct star_nic_private *priv = netdev_priv(dev);
++
++ return &priv->stats;
++}
++
++static void star_nic_timeout(struct net_device *dev)
++{
++ DBG_PRINT("%s:star_nic_timeout\n", dev->name);
++ netif_wake_queue(dev);
++ dev->trans_start = jiffies;
++}
++
++static int star_nic_close(struct net_device *dev)
++{
++#if 1
++ star_nic_phy_powerdown(dev);
++#endif
++ star_nic_uninstall_isr(dev);
++
++/* plany add 20080904 */
++#ifdef CONFIG_STAR_NIC_NAPI
++ struct star_nic_private *priv = netdev_priv(dev);
++ napi_disable(&priv->napi);
++#endif
++ netif_stop_queue(dev);
++ star_nic_shutdown(dev);
++
++#ifdef MODULE
++ MOD_DEC_USE_COUNT;
++#endif
++
++ //CUR_NAPI_DEV = STAR_NIC_LAN_DEV;
++
++ return 0;
++}
++
++static inline struct sk_buff *star_nic_alloc_skb(void)
++{
++ struct sk_buff *skb;
++
++ skb = dev_alloc_skb(MAX_PACKET_LEN + 2);
++
++ if (unlikely(!skb)) {
++ printk("\n dev_alloc_skb fail!! while allocate RFD ring !!\n");
++ return NULL;
++ }
++
++ /* Make buffer alignment 2 beyond a 16 byte boundary
++ * this will result in a 16 byte aligned IP header after
++ * the 14 byte MAC header is removed
++ */
++ skb_reserve(skb, 2); /* 16 bit alignment */
++
++ return skb;
++}
++
++static void __init star_nic_buffer_free(void)
++{
++ int i;
++
++ if (rxring.vir_addr) {
++ for (i = 0; i < STAR_NIC_MAX_RFD_NUM; i++) {
++ if (rxring.skb_ptr[i]) {
++ dev_kfree_skb(rxring.skb_ptr[i]);
++ }
++ }
++ dma_free_coherent(NULL, STAR_NIC_MAX_RFD_NUM * sizeof(STAR_NIC_RXDESC), rxring.vir_addr, rxring.phy_addr);
++ memset((void *)&rxring, 0, STAR_NIC_MAX_RFD_NUM * sizeof(STAR_NIC_RXDESC));
++ }
++
++ if (txring.vir_addr) {
++ dma_free_coherent(NULL, STAR_NIC_MAX_TFD_NUM * sizeof(STAR_NIC_TXDESC), txring.vir_addr, txring.phy_addr);
++ memset((void *)&txring, 0, STAR_NIC_MAX_TFD_NUM * sizeof(STAR_NIC_TXDESC));
++ }
++}
++
++static int __init star_nic_buffer_alloc(void)
++{
++ STAR_NIC_RXDESC volatile *rxdesc_ptr;
++ STAR_NIC_TXDESC volatile *txdesc_ptr;
++ struct sk_buff *skb_ptr;
++ int err;
++ int i;
++
++ rxring.vir_addr = dma_alloc_coherent(NULL, STAR_NIC_MAX_RFD_NUM * sizeof(STAR_NIC_RXDESC), &rxring.phy_addr, GFP_KERNEL);
++ if (!rxring.vir_addr) {
++ printk("\n ERROR: Allocate RFD Failed\n");
++ err = -ENOMEM;
++ goto err_out;
++ }
++
++ txring.vir_addr = dma_alloc_coherent(NULL, STAR_NIC_MAX_TFD_NUM * sizeof(STAR_NIC_TXDESC), &txring.phy_addr, GFP_KERNEL);
++ if (!txring.vir_addr) {
++ printk("\n ERROR: Allocate TFD Failed\n");
++ err = -ENOMEM;
++ goto err_out;
++ }
++
++ // Clean RX Memory
++ memset((void *)rxring.vir_addr, 0, STAR_NIC_MAX_RFD_NUM * sizeof(STAR_NIC_RXDESC));
++ DBG_PRINT(" rxring.vir_addr=0x%08X rxring.phy_addr=0x%08X\n", (u32)rxring.vir_addr, (u32)rxring.phy_addr);
++ rxring.cur_index = 0; // Set cur_index Point to Zero
++ rxdesc_ptr = rxring.vir_addr;
++ for (i = 0; i < STAR_NIC_MAX_RFD_NUM; i++, rxdesc_ptr++) {
++ if (i == (STAR_NIC_MAX_RFD_NUM - 1)) {
++ rxdesc_ptr->eor = 1; // End bit == 0;
++ }
++ skb_ptr = star_nic_alloc_skb();
++ if (!skb_ptr) {
++ printk("ERROR: Allocate skb Failed!\n");
++ err = -ENOMEM;
++ goto err_out;
++ }
++ // Trans Packet from Virtual Memory to Physical Memory
++ rxring.skb_ptr[i] = skb_ptr;
++ rxdesc_ptr->data_ptr = (u32)virt_to_phys(skb_ptr->data);
++ rxdesc_ptr->length = MAX_PACKET_LEN;
++ }
++
++ // Clean TX Memory
++ memset((void *)txring.vir_addr, 0, STAR_NIC_MAX_TFD_NUM * sizeof(STAR_NIC_TXDESC));
++ DBG_PRINT(" txring.vir_addr=0x%08X txring.phy_addr=0x%08X\n", (u32)txring.vir_addr, (u32)txring.phy_addr);
++ txring.cur_index = 0; // Set cur_index Point to Zero
++ txdesc_ptr = txring.vir_addr;
++ for (i = 0; i < STAR_NIC_MAX_TFD_NUM; i++, txdesc_ptr++) {
++ if (i == (STAR_NIC_MAX_TFD_NUM - 1)) {
++ txdesc_ptr->eor = 1; // End of Ring ==1
++ }
++ txdesc_ptr->cown = 1; // TX Ring , Cown == 1
++
++#ifdef STAR_NIC_TX_HW_CHECKSUM
++ // Enable Checksum
++ txdesc_ptr->ico = 1;
++ txdesc_ptr->uco = 1;
++ txdesc_ptr->tco = 1;
++#else
++ txdesc_ptr->ico = 0;
++ txdesc_ptr->uco = 0;
++ txdesc_ptr->tco = 0;
++#endif
++ txring.skb_ptr[i] = NULL; // clear txring.skb_ptr
++ }
++
++ return 0;
++
++err_out:
++ star_nic_buffer_free();
++ return err;
++}
++
++
++#ifdef CONFIG_STAR_JUMBO
++#define MINIMUM_ETHERNET_FRAME_SIZE 64
++#define MAX_JUMBO_FRAME_SIZE 2036
++#define ENET_HEADER_SIZE 14
++#define ETHERNET_FCS_SIZE 4
++#define ETHERNET_VLAN_SIZE 4
++#define NET_IP_ALIGN 2
++static int
++str8100_change_mtu(struct net_device *netdev, int new_mtu)
++{
++printk("%s: new_mtu=%d\n",__FUNCTION__,new_mtu);
++ int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE+ETHERNET_VLAN_SIZE;
++ if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
++ (max_frame > MAX_JUMBO_FRAME_SIZE)) {
++ printk("%s: Invalid MTU setting (%d)\n",__FUNCTION__,new_mtu);
++ return -EINVAL;
++ }
++ netdev->mtu = new_mtu;
++
++// star_nic_buffer_free();
++// star_nic_buffer_alloc();
++
++// if (netif_running(netdev))
++// e1000_reinit_locked(adapter);
++
++ return 0;
++
++}
++#endif
++
++#ifdef CONFIG_STAR_NIC_NAPI
++#if 1
++static int star_nic_poll(struct napi_struct *napi, int budget)
++{
++ struct star_nic_private *priv = netdev_priv(STAR_NIC_LAN_DEV);
++ int work_done = 0;
++ int work_to_do = budget;
++
++ star_nic_receive_packet(0, &work_done, work_to_do);
++
++ budget -= work_done;
++
++ /* if no Tx and not enough Rx work done, exit the polling mode */
++ if (work_done) {
++ if (test_bit(0, (unsigned long *)&is_qf) == 1) { // queue full
++ clear_bit(0, (unsigned long *)&is_qf);
++ HAL_NIC_RX_DMA_START();
++ return 1;
++ }
++ } else {
++ napi_complete(&priv->napi);
++#ifdef CONFIG_STAR_NIC_NAPI_MASK_IRQ
++ enable_irq(INTC_NIC_RXRC_BIT_INDEX);
++#endif
++ return 0;
++ }
++
++ return work_done;
++}
++#else
++static int star_nic_poll(struct net_device *netdev, int *budget)
++{
++ struct star_nic_private *priv = netdev_priv(STAR_NIC_LAN_DEV);
++ int work_done = 0;
++ int work_to_do = min(*budget, netdev->quota); // where is min define
++
++ star_nic_receive_packet(0, &work_done, work_to_do);
++
++ *budget -= work_done;
++ netdev->quota -= work_done;
++
++ /* if no Tx and not enough Rx work done, exit the polling mode */
++ if (work_done) {
++ if (test_bit(0, (unsigned long *)&is_qf) == 1) { // queue full
++ clear_bit(0, (unsigned long *)&is_qf);
++ HAL_NIC_RX_DMA_START();
++ return 1;
++ }
++ } else {
++ napi_complete(&priv->napi);
++#ifdef CONFIG_STAR_NIC_NAPI_MASK_IRQ
++ enable_irq(INTC_NIC_RXRC_BIT_INDEX);
++#endif
++ return 0;
++ }
++ return 1;
++}
++#endif
++#endif
++
++static int star_nic_get_rfd_buff(int index)
++{
++ struct star_nic_private *priv;
++ STAR_NIC_RXDESC volatile *rxdesc_ptr;
++ struct sk_buff *skb_ptr;
++ unsigned char *data;
++ int len;
++
++ //TODO: get rxdesc ptr
++ rxdesc_ptr = rxring.vir_addr + index;
++ skb_ptr = rxring.skb_ptr[index];
++#ifdef CONFIG_STAR_JUMBO
++ if (rxdesc_ptr->fs != 1 || rxdesc_ptr->ls != 1) {
++ goto freepacket;
++ }
++#endif
++ len = rxdesc_ptr->length;
++
++ //dma_cache_maintenance(skb_ptr->data, len, PCI_DMA_FROMDEVICE);
++ fa_dma_inv_range(skb_ptr->data, (unsigned long)skb_ptr->data + len);
++
++ data = skb_put(skb_ptr, len);
++
++ skb_ptr->dev = STAR_NIC_LAN_DEV;
++
++ priv = netdev_priv(skb_ptr->dev);
++
++#ifdef STAR_NIC_RX_HW_CHECKSUM
++ if (rxdesc_ptr->ipf == 1 || rxdesc_ptr->l4f == 1) {
++ if (rxdesc_ptr->prot != 0x11) {
++ skb_ptr->ip_summed = CHECKSUM_NONE;
++ } else {
++ // CheckSum Fail
++ priv->stats.rx_errors++;
++ goto freepacket;
++ }
++ } else {
++ skb_ptr->ip_summed = CHECKSUM_UNNECESSARY;
++ }
++#else
++ skb_ptr->ip_summed = CHECKSUM_NONE;
++#endif
++
++ // this line must, if no, packet will not send to network layer
++ skb_ptr->protocol = eth_type_trans(skb_ptr, skb_ptr->dev);
++
++ priv->stats.rx_packets++;
++ priv->stats.rx_bytes += len;
++ skb_ptr->dev->last_rx = jiffies;
++
++ // if netif_rx any package, will let this driver core dump.
++#ifdef CONFIG_STAR_NIC_NAPI
++ netif_receive_skb(skb_ptr);
++#else
++ netif_rx(skb_ptr);
++#endif
++
++ return 0;
++
++freepacket:
++ dev_kfree_skb_any(skb_ptr);
++ return 0;
++}
++
++#ifdef CONFIG_STAR_NIC_NAPI
++void star_nic_receive_packet(int mode, int *work_done, int work_to_do)
++#else
++void star_nic_receive_packet(int mode)
++#endif
++{
++ int rxsd_index;
++ u32 rxsd_current;
++ STAR_NIC_RXDESC volatile *rxdesc_ptr = rxring.vir_addr + rxring.cur_index;
++ struct sk_buff *skb_ptr;
++#ifndef CONFIG_STAR_NIC_NAPI
++ int rxqf = 0; // Queue Full Mode =0
++#endif
++ int i, rxcount = 0;
++ HAL_NIC_READ_RXSD(rxsd_current);
++ rxsd_index = (rxsd_current - (u32)rxring.phy_addr) >> 4;
++
++ if (rxsd_index > rxring.cur_index) {
++ rxcount = rxsd_index - rxring.cur_index;
++ } else if (rxsd_index < rxring.cur_index) {
++ rxcount = (STAR_NIC_MAX_RFD_NUM - rxring.cur_index) + rxsd_index;
++ } else {
++ if (rxdesc_ptr->cown == 0) {
++ goto receive_packet_exit;
++ } else {
++ // Queue Full
++#ifndef CONFIG_STAR_NIC_NAPI
++ rxqf = 1;
++#endif
++ rxcount = STAR_NIC_MAX_RFD_NUM;
++ }
++ }
++
++#ifndef CONFIG_STAR_NIC_NAPI
++ if (mode == 1) {
++ rxqf = 1;
++ rxcount = STAR_NIC_MAX_RFD_NUM;
++ }
++#endif
++
++ for (i = 0; i < rxcount; i++) {
++#ifdef CONFIG_STAR_NIC_NAPI
++ if (*work_done >= work_to_do)
++ break;
++ ++(*work_done);
++#endif
++ if (rxdesc_ptr->cown != 0) {
++ // Alloc New skb_buff
++ skb_ptr = star_nic_alloc_skb();
++ // Check skb_buff
++ if (skb_ptr != NULL) {
++ star_nic_get_rfd_buff(rxring.cur_index);
++ rxring.skb_ptr[rxring.cur_index] = skb_ptr;
++ rxdesc_ptr->data_ptr = (u32)virt_to_phys(skb_ptr->data);
++ rxdesc_ptr->length = MAX_PACKET_LEN;
++ rxdesc_ptr->cown = 0; // set cbit to 0 for CPU Transfer
++ } else {
++ // TODO:
++ // I will add dev->lp.stats->rx_dropped, it will effect the performance
++ DBG_PRINT("%s: Alloc sk_buff fail, reuse the buffer\n", __FUNCTION__);
++ rxdesc_ptr->cown = 0; // set cbit to 0 for CPU Transfer
++ return;
++ }
++ } else {
++ //printk("[KC_DEBUG] star_nic_receive_packet() encounter COWN==0 BUG\n");
++ }
++
++ if (rxring.cur_index == (STAR_NIC_MAX_RFD_NUM - 1)) {
++ rxring.cur_index = 0;
++ rxdesc_ptr = rxring.vir_addr;
++ } else {
++ rxring.cur_index++;
++ rxdesc_ptr++;
++ }
++ }
++
++#ifndef CONFIG_STAR_NIC_NAPI
++ if (rxqf) {
++ rxring.cur_index = rxsd_index;
++ mb();
++ HAL_NIC_RX_DMA_START();
++ }
++#endif
++
++receive_packet_exit:
++ return;
++}
++
++#ifdef FREE_TX_SKB_MULTI
++#define FREE_TX_SKB_MULTI_MAX 16
++#define MAX_TX_SKB_FREE_NUM FREE_TX_SKB_MULTI_MAX + MAX_SKB_FRAGS
++#endif
++
++#define FIX_NFS
++static int star_nic_send_packet(struct sk_buff *skb, struct net_device *dev)
++{
++#if defined(STAR_NIC_TX_HW_CHECKSUM) && defined(MAX_SKB_FRAGS) && defined(STAR_NIC_SG)
++ struct star_nic_private *priv = netdev_priv(dev);
++ STAR_NIC_TXDESC volatile *txdesc_ptr;
++ unsigned long flags;
++
++#ifdef FREE_TX_SKB_MULTI
++ int i;
++ int tssd_index;
++ int tssd_current;
++ int skb_free_count = 0;
++ struct sk_buff *skb_free[MAX_TX_SKB_FREE_NUM];
++#endif
++
++#if defined(STAR_NIC_TX_HW_CHECKSUM) && defined(MAX_SKB_FRAGS) && defined(STAR_NIC_SG)
++ int org_index;
++ int cur_index;
++
++
++ unsigned int f;
++ unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
++ unsigned int len = skb->len - skb->data_len;
++ int padding_size = ETH_ZLEN - len;
++ unsigned int offset;
++
++
++#ifndef FREE_TX_SKB_MULTI
++ int skb_free_count = 0;
++ struct sk_buff *skb_free[MAX_SKB_FRAGS];
++#endif
++#else
++#ifndef FREE_TX_SKB_MULTI
++ struct sk_buff *skb_free;
++#endif
++#endif
++
++ spin_lock_irqsave(&star_nic_send_lock, flags);
++
++#ifdef FREE_TX_SKB_MULTI
++ int count = 0;
++
++ for (i = 0; i < FREE_TX_SKB_MULTI_MAX; i++) {
++ txdesc_ptr = txring.vir_addr + txring.to_free_index;
++ if (txdesc_ptr->cown == 0) {
++ break;
++ }
++ if (txring.skb_ptr[txring.to_free_index]) {
++ skb_free[count++] = txring.skb_ptr[txring.to_free_index];
++ txring.skb_ptr[txring.to_free_index] = NULL;
++ }
++
++ increase_cyclic(txring.to_free_index, STAR_NIC_MAX_TFD_NUM);
++
++ if (count == FREE_TX_SKB_MULTI_MAX) {
++ break;
++ }
++ }
++ skb_free_count = count;
++#endif
++
++#if defined(STAR_NIC_TX_HW_CHECKSUM) && defined(MAX_SKB_FRAGS) && defined(STAR_NIC_SG)
++ org_index = txring.cur_index;
++ cur_index = txring.cur_index;
++ for (f = 0; f < (nr_frags + 1); f++) {
++ txdesc_ptr = txring.vir_addr + cur_index;
++
++ if (txdesc_ptr->cown == 0) {
++ spin_unlock_irqrestore(&star_nic_send_lock, flags);
++#ifdef FREE_TX_SKB_MULTI
++ for (i = 0; i < skb_free_count; i++) {
++ dev_kfree_skb(skb_free[i]);
++ }
++#endif
++ /* Not enough tx buffer, re-queue the skb. */
++ return NETDEV_TX_BUSY;
++ }
++
++ if (txring.skb_ptr[cur_index]) {
++ skb_free[skb_free_count++] = txring.skb_ptr[cur_index];
++ }
++
++#if defined(FREE_TX_SKB_MULTI) || defined(STAR_NIC_TIMER)
++ if(cur_index==txring.to_free_index)
++ increase_cyclic(txring.to_free_index, STAR_NIC_MAX_TFD_NUM);
++#endif
++
++ if (f == 0) {
++ txdesc_ptr->fs = 1;
++ } else {
++ txdesc_ptr->fs = 0;
++ }
++ if (f == nr_frags) {
++ txdesc_ptr->ls = 1;
++ } else {
++ txdesc_ptr->ls = 0;
++ }
++
++ increase_cyclic(cur_index, STAR_NIC_MAX_TFD_NUM);
++ }
++
++ txdesc_ptr = (txring.vir_addr + txring.cur_index);
++ txdesc_ptr->data_ptr = virt_to_phys(skb->data);
++
++ if ((nr_frags == 0) && (len < PKT_MIN_SIZE)) {
++ txdesc_ptr->length = PKT_MIN_SIZE;
++ memset(skb->data + len, 0x00, PKT_MIN_SIZE - len);
++ } else {
++ txdesc_ptr->length = len;
++ }
++
++ if (nr_frags) {
++ txring.skb_ptr[txring.cur_index] = NULL;
++ } else {
++ txring.skb_ptr[txring.cur_index] = skb;
++ }
++ //dma_cache_maintenance(skb->data, txdesc_ptr->length, PCI_DMA_TODEVICE);
++ fa_dma_clean_range(skb->data, (unsigned long)skb->data + txdesc_ptr->length);
++
++ increase_cyclic(txring.cur_index, STAR_NIC_MAX_TFD_NUM);
++
++ for (f = 0; f < nr_frags; f++) {
++ struct skb_frag_struct *frag;
++ txdesc_ptr = txring.vir_addr + txring.cur_index;
++ frag = &skb_shinfo(skb)->frags[f];
++#if 1
++ padding_size -= frag->size;
++
++ //txdesc_ptr->data_ptr = virt_to_phys(page_address(frag->page) + frag->page_offset);
++ txdesc_ptr->data_ptr = virt_to_phys(sg_virt(frag));
++ txdesc_ptr->length = frag->size;
++#else
++ len = frag->size;
++ //offset = frag->page_offset;
++
++ //txdesc_ptr->data_ptr = virt_to_phys(page_address(frag->page) + offset);
++ txdesc_ptr->data_ptr = virt_to_phys(sg_virt(frag));
++ txdesc_ptr->length = len;
++#endif // FIX_NFS
++
++ if (f == (nr_frags - 1)) {
++ txring.skb_ptr[txring.cur_index] = skb;
++ } else {
++ txring.skb_ptr[txring.cur_index] = NULL;
++ }
++ //dma_cache_maint(page_address(frag->page) + offset, txdesc_ptr->length, PCI_DMA_TODEVICE);
++ // dma_cache_maintenance(sg_virt(frag), txdesc_ptr->length, PCI_DMA_TODEVICE);
++ fa_dma_clean_range(sg_virt(frag), (unsigned long)sg_virt(frag)+txdesc_ptr->length);
++
++ increase_cyclic(txring.cur_index, STAR_NIC_MAX_TFD_NUM);
++
++ if (padding_size > 0)
++ /* Padding zero to the end of packet to meet minimum
++ * packet size requirement. */
++ txdesc_ptr->length += padding_size;
++ }
++
++ for (f = 0; f < (nr_frags + 1); f++) {
++ txdesc_ptr = txring.vir_addr + org_index;
++ txdesc_ptr->cown = 0;
++ org_index++;
++ if (org_index == STAR_NIC_MAX_TFD_NUM) {
++ org_index = 0;
++ }
++ }
++
++
++
++#else
++ txdesc_ptr = txring.vir_addr + txring.cur_index;
++
++ if (txdesc_ptr->cown == 0) { // This TFD is busy
++ spin_unlock_irqrestore(&star_nic_send_lock, flags);
++ // re-queue the skb
++ return 1;
++ }
++
++#ifndef FREE_TX_SKB_MULTI
++ if (txring.skb_ptr[txring.cur_index]) {
++ // MUST TODO: Free skbuff
++ skb_free = txring.skb_ptr[txring.cur_index];
++ }
++#endif
++
++ txdesc_ptr->fs = 1;
++ txdesc_ptr->ls = 1;
++
++ txring.skb_ptr[txring.cur_index] = skb;
++ txdesc_ptr->data_ptr = virt_to_phys(skb->data);
++ if (skb->len < PKT_MIN_SIZE) {
++ txdesc_ptr->length = PKT_MIN_SIZE;
++ memset(skb->data + skb->len, 0x00, PKT_MIN_SIZE - skb->len);
++ } else {
++ txdesc_ptr->length = skb->len;
++ }
++
++ //dma_cache_maintenance(skb->data, txdesc_ptr->length, PCI_DMA_TODEVICE);
++ fa_dma_clean_range(skb->data, (unsigned long)skb->data+txdesc_ptr->length);
++
++ increase_cyclic(txring.cur_index, STAR_NIC_MAX_TFD_NUM);
++
++ txdesc_ptr->cown = 0;
++#endif
++
++ mb();
++ HAL_NIC_TX_DMA_START();
++
++ priv->stats.tx_packets++;
++ priv->stats.tx_bytes += skb->len;
++ dev->trans_start = jiffies;
++
++ spin_unlock_irqrestore(&star_nic_send_lock, flags);
++
++#ifdef FREE_TX_SKB_MULTI
++ for (i = 0; i < skb_free_count; i++) {
++ dev_kfree_skb(skb_free[i]);
++ }
++#else
++#if defined(STAR_NIC_TX_HW_CHECKSUM) && defined(MAX_SKB_FRAGS) && defined(STAR_NIC_SG)
++ for (f = 0; f < skb_free_count; f++) {
++ dev_kfree_skb(skb_free[f]);
++ }
++#else
++ if (skb_free) {
++ dev_kfree_skb(skb_free);
++ }
++#endif
++#endif
++
++ return NETDEV_TX_OK;
++
++#else
++ struct star_nic_private *priv = netdev_priv(dev);
++ STAR_NIC_TXDESC volatile *txdesc_ptr = (txring.vir_addr + txring.cur_index);
++ struct sk_buff *skb_free = NULL;
++ unsigned long flags;
++
++ spin_lock_irqsave(&star_nic_send_lock, flags);
++
++ if (txdesc_ptr->cown == 0) { // This TFD is busy
++ spin_unlock_irqrestore(&star_nic_send_lock, flags);
++ // re-queue the skb
++ return NETDEV_TX_BUSY;
++ }
++
++ if (txdesc_ptr->data_ptr != 0) {
++ // MUST TODO: Free skbuff
++ skb_free = txring.skb_ptr[txring.cur_index];
++#ifdef STAR_NIC_TIMER
++ txring.to_free_index = txring.cur_index + 1;
++ if (txring.to_free_index == STAR_NIC_MAX_TFD_NUM) {
++ txring.to_free_index = 0;
++ }
++#endif
++ }
++
++#ifdef STAR_NIC_TX_HW_CHECKSUM
++ if (skb->protocol == __constant_htons(ETH_P_IP)) {
++ if (skb->nh.iph->protocol == IPPROTO_UDP) {
++ txdesc_ptr->uco = 1;
++ txdesc_ptr->tco = 0;
++ //printk("[KC DEBUG] UDP PACKET\n");
++ } else if (skb->nh.iph->protocol == IPPROTO_TCP) {
++ txdesc_ptr->uco = 0;
++ txdesc_ptr->tco = 1;
++ //printk("[KC DEBUG] TCP PACKET\n");
++ } else {
++ txdesc_ptr->uco = 0;
++ txdesc_ptr->tco = 0;
++ //printk("[KC DEBUG] NOT TCP&UDP PACKET\n");
++ }
++ } else {
++#if 0
++ if (skb->protocol == __constant_htons(ETH_P_ARP)) {
++ printk("[KC DEBUG] ARP PACKET\n");
++ } else {
++ printk("[KC DEBUG] NOT IP PACKET\n");
++ }
++#endif
++ txdesc_ptr->ico = 0;
++ txdesc_ptr->uco = 0;
++ txdesc_ptr->tco = 0;
++ }
++#endif
++
++ txring.skb_ptr[txring.cur_index] = skb;
++ txdesc_ptr->data_ptr = virt_to_phys(skb->data);
++ if (skb->len < PKT_MIN_SIZE) {
++ txdesc_ptr->length = PKT_MIN_SIZE;
++ memset(skb->data + skb->len, 0x00, PKT_MIN_SIZE - skb->len);
++ } else {
++ txdesc_ptr->length = skb->len;
++ }
++
++ //dma_cache_maintenance(skb->data, txdesc_ptr->length, PCI_DMA_TODEVICE);
++ fa_dma_clean_range(skb->data, (unsigned long)skb->data+txdesc_ptr->length);
++
++ txdesc_ptr->fs = 1;
++ txdesc_ptr->ls = 1;
++ // Wake interrupt
++ txdesc_ptr->intr = 0;
++ txdesc_ptr->cown = 0;
++
++ mb();
++ HAL_NIC_TX_DMA_START();
++
++ priv->stats.tx_packets++;
++ priv->stats.tx_bytes += skb->len;
++ dev->trans_start = jiffies;
++
++ if (txring.cur_index == (STAR_NIC_MAX_TFD_NUM - 1)) {
++ txring.cur_index = 0;
++ } else {
++ txring.cur_index++;
++ }
++
++ spin_unlock_irqrestore(&star_nic_send_lock, flags);
++ if (skb_free) {
++ dev_kfree_skb(skb_free);
++ }
++
++#ifdef STAR_NIC_TIMER
++ mod_timer(&star_nic_timer, jiffies + 10);
++#endif
++ return NETDEV_TX_OK;
++#endif
++}
++
++static void star_nic_set_mac_addr(struct net_device *dev, const char *mac_addr)
++{
++ memcpy(dev->dev_addr, mac_addr, 6);
++
++ NIC_MY_MAC_HIGH_BYTE_REG =
++ (mac_addr[0] << 8) |
++ mac_addr[1];
++
++ NIC_MY_MAC_LOW_BYTE_REG =
++ (mac_addr[2] << 24) |
++ (mac_addr[3] << 16) |
++ (mac_addr[4] << 8) |
++ (mac_addr[5]);
++
++ printk("MAC Addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
++ mac_addr[0],
++ mac_addr[1],
++ mac_addr[2],
++ mac_addr[3],
++ mac_addr[4],
++ mac_addr[5]);
++}
++
++static int star_nic_set_lan_mac_addr(struct net_device *dev, void *addr)
++{
++ struct sockaddr *sock_addr = addr;
++ struct star_nic_private *priv = netdev_priv(dev);
++
++ spin_lock_irq(&priv->lock);
++ star_nic_set_mac_addr(dev, sock_addr->sa_data);
++ spin_unlock_irq(&priv->lock);
++
++ return 0;
++}
++
++
++#ifdef CONFIG_PM
++static int nic_suspended=0;
++void inline str8100_wol_enter(){
++
++ //stop tx dma
++ HAL_NIC_TX_DMA_STOP();
++ //Enable Internal Loopback mode
++ NIC_TEST_1_REG|=(0x1<<18);
++
++ //WoL
++ NIC_MAC_CONTROL_REG |= (0x1 << 30); //assert WoL bit
++
++
++ while (!((NIC_MAC_CONTROL_REG>>29)&0x1)){
++ udelay(500);
++ NIC_MAC_CONTROL_REG |= (0x1 << 30); //assert WoL bit
++ NIC_MAC_CONTROL_REG &= ~(0x1 << 30); //de-assert WoL bit
++ NIC_MAC_CONTROL_REG |= (0x1 << 30); //assert WoL bit
++ udelay(500);
++
++// if((NIC_TEST_1_REG&(0x1fff))!=4096){
++//printk("%.8x\n",NIC_TEST_1_REG);
++ u32 test=0;
++ test=test=NIC_TEST_1_REG;
++// }
++ }
++ //Disable Internal Loopback mode
++ NIC_TEST_1_REG&=~(0x1<<18);
++
++ //Enable Magic packet received of Nic status Int
++ HAL_NIC_ENABLE_INTERRUPT_STATUS_SOURCE_BIT(4);
++
++ NIC_MAC_CONTROL_REG |= (0x1 <<29);//write "1" clear
++ HAL_PWRMGT_DISABLE_NIC_CLOCK();
++}
++
++void inline str8100_wol_exit(){
++ HAL_NIC_DISABLE_INTERRUPT_STATUS_SOURCE_BIT(4);
++ HAL_PWRMGT_ENABLE_NIC_CLOCK();
++ NIC_MAC_CONTROL_REG &= ~(0x1 << 30); //de-assert power down bit
++
++ HAL_NIC_CLEAR_INTERRUPT_STATUS_SOURCES((0x1<<4));
++ HAL_NIC_TX_DMA_START();
++}
++
++int inline str8100_nic_suspend(suspend_state_t state)
++{
++ if(!netif_running(STAR_NIC_LAN_DEV)) return 0;
++ nic_suspended=1;
++
++#ifdef CONFIG_PM_DEBUG
++ printk("%s:\n",__FUNCTION__);
++#endif
++ netif_device_detach(STAR_NIC_LAN_DEV);
++/*
++ if (netif_running(STAR_NIC_LAN_DEV)) {
++ WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
++ e1000_down(adapter);
++ }
++*/
++ str8100_wol_enter();
++ return 0;
++}
++int inline str8100_nic_resume()
++{
++ //Waked
++ if(!nic_suspended) return 0;
++ nic_suspended=0;
++#ifdef CONFIG_PM_DEBUG
++ printk("%s:\n",__FUNCTION__);
++#endif
++/* if (netif_running(STAR_NIC_LAN_DEV))
++ e1000_up(adapter);
++*/
++ netif_device_attach(STAR_NIC_LAN_DEV);
++
++ str8100_wol_exit();
++
++ return 0;
++}
++#endif
++
++static int star_nic_init(struct net_device *dev)
++{
++#if 1
++ // set hight
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 15);
++ // set low
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG &= ~(0x1 << 15);
++ // set high
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 15);
++#endif
++
++#if 1
++ // set NIC clock to 67.5MHz
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (0x1 << 7);
++#else
++ // set NIC clock to 125MHz
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x1 << 7);
++#endif
++
++ // enable NIC clock
++ HAL_PWRMGT_ENABLE_NIC_CLOCK();
++ //NIC_MAC_CONTROL_REG = 0x00527C00;
++ udelay(100);
++
++ // Configure GPIO for NIC MDC/MDIO pins
++ HAL_MISC_ENABLE_MDC_MDIO_PINS();
++ HAL_MISC_ENABLE_NIC_COL_PINS();
++#ifdef CONFIG_STAR_NIC_PHY_INTERNAL_PHY
++ MISC_GPIOA_PIN_ENABLE_REG |= (0x7 << 22);
++ MISC_FAST_ETHERNET_PHY_CONFIG_REG |= (FE_PHY_LED_MODE >> 12) & 0x3;
++
++ // set hight
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 15);
++ // set low
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG &= ~(0x1 << 15);
++ // set high
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 15);
++#else
++ //Enable GPIO for NIC LED
++ HAL_MISC_ENABLE_LED012_PINS();
++#endif
++
++ // disable all interrupt status sources
++ HAL_NIC_DISABLE_ALL_INTERRUPT_STATUS_SOURCES();
++
++ // clear previous interrupt sources
++ HAL_NIC_CLEAR_ALL_INTERRUPT_STATUS_SOURCES();
++
++ // disable all DMA-related interrupt sources
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_NIC_TXTC_BIT_INDEX);
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_NIC_RXRC_BIT_INDEX);
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_NIC_TXQE_BIT_INDEX);
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_NIC_RXQF_BIT_INDEX);
++
++ // clear previous interrupt sources
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_NIC_TXTC_BIT_INDEX);
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_NIC_RXRC_BIT_INDEX);
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_NIC_TXQE_BIT_INDEX);
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_NIC_RXQF_BIT_INDEX);
++
++ HAL_NIC_TX_DMA_STOP();
++ HAL_NIC_RX_DMA_STOP();
++
++ if (star_nic_buffer_alloc() != 0) {
++ return -1;
++ }
++ star_nic_mac_config(dev);
++ star_nic_fc_config(dev);
++
++ if (star_nic_phy_config(dev) != 0) {
++ star_nic_buffer_free();
++ return -1;
++ }
++
++ star_nic_vlan_config(dev);
++ star_nic_arl_config(dev);
++
++ /* MAC address is already in MAC registers from TS-BOOTROM */
++ default_mac_addr[0] = NIC_MY_MAC_HIGH_BYTE_REG >> 8;
++ default_mac_addr[1] = NIC_MY_MAC_HIGH_BYTE_REG;
++ default_mac_addr[2] = NIC_MY_MAC_LOW_BYTE_REG >> 24;
++ default_mac_addr[3] = NIC_MY_MAC_LOW_BYTE_REG >> 16;
++ default_mac_addr[4] = NIC_MY_MAC_LOW_BYTE_REG >> 8;
++ default_mac_addr[5] = NIC_MY_MAC_LOW_BYTE_REG;
++
++ star_nic_set_mac_addr(dev, default_mac_addr);
++ star_nic_mib_reset();
++
++ *(u32 volatile *)(SYSVA_MISC_BASE_ADDR+0x0c) = 0x00000125; //0x00000105 pb0_nic
++
++ HAL_NIC_WRITE_TXSD(txring.phy_addr);
++ HAL_NIC_WRITE_TX_BASE(txring.phy_addr);
++ HAL_NIC_WRITE_RXSD(rxring.phy_addr);
++ HAL_NIC_WRITE_RX_BASE(rxring.phy_addr);
++
++ star_nic_dma_config(dev);
++
++ return 0;
++}
++
++static void set_multicast_list(struct net_device *dev) {
++}
++
++static const struct net_device_ops star_ops = {
++ .ndo_open = star_nic_lan_open,
++ .ndo_stop = star_nic_close,
++ .ndo_start_xmit = star_nic_send_packet,
++ .ndo_get_stats = star_nic_get_stats,
++ .ndo_set_multicast_list = set_multicast_list,
++ .ndo_tx_timeout = star_nic_timeout,
++ .ndo_change_mtu = eth_change_mtu,
++ .ndo_set_mac_address = star_nic_set_lan_mac_addr,
++ .ndo_validate_addr = eth_validate_addr,
++};
++
++static int __init star_nic_probe(int port_type)
++{
++ struct net_device *netdev;
++ struct star_nic_private *priv;
++ int err;
++
++ netdev = alloc_etherdev(sizeof(struct star_nic_private));
++ if (!netdev) {
++ err = -ENOMEM;
++ goto err_alloc_etherdev;
++ }
++
++ priv = netdev_priv(netdev);
++ memset(priv, 0, sizeof(struct star_nic_private));
++ spin_lock_init(&priv->lock);
++
++ netdev->base_addr = SYSVA_NIC_BASE_ADDR;
++ netdev->netdev_ops = &star_ops;
++
++#if defined(STAR_NIC_TX_HW_CHECKSUM) && defined(MAX_SKB_FRAGS) && defined(STAR_NIC_SG)
++ netdev->features = NETIF_F_IP_CSUM | NETIF_F_SG;
++#elif defined(STAR_NIC_TX_HW_CHECKSUM)
++ netdev->features = NETIF_F_IP_CSUM;
++#endif
++#ifdef CONFIG_STAR_NIC_NAPI
++ netif_napi_add(netdev, &priv->napi, star_nic_poll, 64);
++#else
++ netdev->poll = star_nic_poll;
++ netdev->weight = 64;
++#endif
++ priv->dev_index = LAN_PORT;
++
++#ifdef CONFIG_STAR_JUMBO
++ #error fix me
++ netdev->change_mtu = &str8100_change_mtu;
++#endif
++
++ err = register_netdev(netdev);
++ if (err) {
++ goto err_register_netdev;
++ }
++
++ //SET_MODULE_OWNER(netdev);
++
++ STAR_NIC_LAN_DEV = netdev;
++
++ if ((err = star_nic_init(netdev))) {
++ goto err_nic_init;
++ }
++
++ return 0;
++
++err_register_netdev:
++ free_netdev(netdev);
++ return err;
++
++err_nic_init:
++ unregister_netdev(netdev);
++ return err;
++
++err_alloc_etherdev:
++ return err;
++}
++
++static int __init star_nic_lan_init(void)
++{
++ return star_nic_probe(LAN_PORT);
++}
++
++static int __init star_nic_proc_init(void)
++{
++ star_nic_proc_entry = create_proc_entry("str8100/nic", S_IFREG | S_IRUGO, NULL);
++ if (star_nic_proc_entry) {
++ star_nic_proc_entry->read_proc = star_nic_read_proc;
++ star_nic_proc_entry->write_proc = star_nic_write_proc;
++ }
++
++ return 0;
++}
++
++static int __init star_nic_init_module(void)
++{
++ int err = 0;
++
++ printk(KERN_INFO "%s", star_nic_driver_version);
++ spin_lock_init(&star_nic_send_lock);
++ err = star_nic_lan_init();
++ if (err != 0) {
++ return err;
++ }
++ star_nic_proc_init();
++
++ printk("\n");
++#ifdef CONFIG_INTERNEL_PHY_PATCH
++ printk("%s: internal phy patch included.\n",__FUNCTION__);
++ //str813x_internal_phy_proc_init();
++#elif defined(CONFIG_STAR_NIC_PHY_INTERNAL_PHY)
++ printk("%s: internal phy used but no patch included.\n",__FUNCTION__);
++#endif
++#if defined(STAR_NIC_TX_HW_CHECKSUM) && defined(MAX_SKB_FRAGS) && defined(STAR_NIC_SG)
++ printk("%s: scatter/gather enabled.\n",__FUNCTION__);
++#else
++ printk("%s: scatter/gather disabled.\n",__FUNCTION__);
++#endif
++ printk("\n");
++
++#ifdef STAR_NIC_TIMER
++ init_timer(&star_nic_timer);
++ star_nic_timer.function = &star_nic_timer_func;
++ star_nic_timer.data = (unsigned long)NULL;
++#endif
++
++ return 0;
++}
++
++module_init(star_nic_init_module);
++
++//========================================================
++#ifdef CONFIG_INTERNEL_PHY_PATCH
++
++static void (*phy_statemachine)(int, int, int);
++
++#define ETH3220_PHY_MON_PERIOD INTERNAL_PHY_PATCH_CHECK_PERIOD
++
++/*===================================================================================*/
++/* phy monitor state */
++#define NUM_PHY 1
++#define PHY_STATE_INIT 0
++#define LINK_DOWN_POSITIVE 1
++#define WAIT_LINK_UP_POSITIVE 2
++#define LINK_UP_POSITIVE 3
++#define WAIT_BYPASS_LINK_UP_POSITIVE 4
++#define BYPASS_AND_LINK_UP_POSITIVE 5
++#define LINK_UP_8101_POSITIVE 6
++#define WAIT_8101_LINK_UP_POSITIVE 7
++
++#define PHY_STATE_LAST (WAIT_8101_LINK_UP_POSITIVE+1)
++/*===================================================================================*/
++/* time setting */
++#define WAIT_BYPASS_LINK_UP_POSITIVE_TIMEOUT 5000 /* 5000 ms */
++#define WAIT_BYPASS_LINK_UP_NEGATIVE_TIMEOUT 5000 /* 5000 ms */
++#define LINK_DOWN_ABILITY_DETECT_TIMEOUT 5000 /* 5000 ms */
++#define DETECT_8101_PERIOD 7000 /* 7000 ms */
++#define WAIT_8101_LINK_UP_TIMEOUT 3000 /* 3000 ms */
++
++#define MAX_PHY_PORT 1
++#define DEFAULT_AGC_TRAIN 16
++#define MAX_AGC_TRAIN 16 //train 16 times
++static int agc_train_num = DEFAULT_AGC_TRAIN;
++u32 port_displaybuf[NUM_PHY][MAX_AGC_TRAIN + 1] = {{0}};
++
++static int cuv[3][3] = {
++ {1, 1, 4},
++ {1, 1, 0},
++ {1, 1, -4}};
++static u32 link_status_old = 0;
++//static int agc_th[2] = {0x18, 0x28}; /* To be deleted */
++//static u32 phy_mon_timer; /* To be deleted */
++//static u32 current_agc = 0; //0:Not patch, 1:patch
++/*===================================================================================*/
++
++typedef struct eth3220_phy_s {
++ u16 state;
++ u16 linkdown_cnt;
++ u32 state_time;
++ u32 timer;
++} eth3220_phy_t;
++
++#define DEBUG_PHY_STATE_TRANSITION 1
++#if DEBUG_PHY_STATE_TRANSITION
++/* show state transition of debug phy port.
++ * -1 for all ports
++ * -2 for disable all ports
++ * 0 - 4 for each port */
++static int debug_phy_port = -2;
++static char *phystate_name[] = {
++ "init", /* PHY_STATE_INIT */
++ "ldp", /* LINK_DOWN_POSITIVE */
++ "wait_lup", /* WAIT_LINK_UP_POSITIVE */
++ "lup", /* LINK_UP_POSITIVE */
++ "wait_bp_lup", /* WAIT_BYPASS_LINK_UP_POSITIVE */
++ "bp_lup", /* BYPASS_AND_LINK_UP_POSITIVE */
++ "8101_lup", /* LINK_UP_8101_POSITIVE */
++ "wait_8101_lup", /* WAIT_8101_LINK_UP_POSITIVE */
++ "err",
++};
++#endif /* DEBUG_PHY_STATE_TRANSITION */
++static eth3220_phy_t phy[5] = { {PHY_STATE_INIT, 0, 0, 0},
++ {PHY_STATE_INIT, 0, 0, 0},
++ {PHY_STATE_INIT, 0, 0, 0},
++ {PHY_STATE_INIT, 0, 0, 0},
++ {PHY_STATE_INIT, 0, 0, 0}};
++
++static u16 long_cable_global_reg[32]={
++0x0000,0x19a0,0x1d00,0x0e80,0x0f60,0x07c0,0x07e0,0x03e0,
++0x0000,0x0000,0x0000,0x2000,0x8250,0x1700,0x0000,0x0000,
++0x0000,0x0000,0x0000,0x0000,0x0000,0x204b,0x01c2,0x0000,
++0x0000,0x0000,0x0fff,0x4100,0x9319,0x0021,0x0034,0x270a|FE_PHY_LED_MODE
++};
++
++static u16 long_cable_local_reg[32]={
++0x3100,0x786d,0x01c1,0xca51,0x05e1,0x45e1,0x0003,0x001c,
++0x2000,0x9828,0xf3c4,0x400c,0xf8ff,0x6940,0xb906,0x503c,
++0x8000,0x297a,0x1010,0x5010,0x6ae1,0x7c73,0x783c,0xfbdf,
++0x2080,0x3244,0x1301,0x1a80,0x8e8f,0x8000,0x9c29,0xa70a|FE_PHY_LED_MODE
++};
++
++static void internal_phy_update(unsigned long data)
++{
++ internal_phy_patch_check(0);
++ mod_timer(&internal_phy_timer, jiffies + INTERNAL_PHY_PATCH_CHECK_PERIOD / 10);
++}
++
++static struct timer_list internal_phy_timer =
++ TIMER_INITIALIZER(internal_phy_update, 0, 0);
++
++/*=============================================================*
++ * eth3220ac_rt8101_phy_setting
++ *=============================================================*/
++static void eth3220ac_rt8101_phy_setting(int port)
++{
++ star_nic_write_phy(port, 12, 0x18ff);
++ star_nic_write_phy(port, 18, 0x6400);
++}
++
++static void eth3220ac_release_bpf(int port)
++{
++ star_nic_write_phy(port, 18, 0x6210);
++}
++
++static void eth3220ac_def_bpf(int port)
++{
++ star_nic_write_phy(port, 18, 0x6bff);
++}
++
++static void eth3220ac_def_linkdown_setting(int port)
++{
++ star_nic_write_phy(port, 13, 0xe901);
++ star_nic_write_phy(port, 14, 0xa3c6);
++}
++
++static void eth3220ac_def_linkup_setting(int port)
++{
++ star_nic_write_phy(port, 13, 0x6901);
++ star_nic_write_phy(port, 14, 0xa286);
++}
++
++/*=============================================================*
++ * eth3220ac_link_agc:
++ *=============================================================*/
++static int eth3220ac_link_agc(int port, int speed)
++{
++ u16 reg;
++ u32 agc_data = 0;
++ u32 short_cable;
++ int i, jj;
++
++ /* if speed = 100MHz, then continue */
++ if (speed == 0)
++ return 0;
++
++ short_cable = 0;
++ jj = 0;
++ for (i=0; i < agc_train_num; i++) {
++ star_nic_read_phy(port, 15, ®);
++ reg &= 0x7f;
++ if (reg <= 0x12) {
++ short_cable = 1;
++ jj++;
++ agc_data += (u32)reg;
++ }
++ }
++ if (short_cable) {
++ agc_data = (agc_data / jj) + 4;
++ } else {
++ agc_data = (cuv[2][0] * agc_data) / cuv[2][1] / agc_train_num - 4;
++ }
++
++ /* Fix AGC */
++ agc_data = 0xd0 | (agc_data << 9);
++ star_nic_write_phy(port, 15, agc_data);
++ udelay(1000);
++ star_nic_read_phy(port, 15, ®);
++ reg &= ~(0x1 << 7);
++ star_nic_write_phy(port, 15, reg);
++
++ return 0;
++}
++
++/*=============================================================*
++ * eth3220ac_unlink_agc:
++ *=============================================================*/
++static void eth3220ac_unlink_agc(int port)
++{
++ // start AGC adaptive
++ star_nic_write_phy(port, 15, 0xa050);
++}
++
++/*=============================================================*
++ * eth3220ac_rt8100_check
++ *=============================================================*/
++static int eth3220ac_rt8100_check(int port)
++{
++ u16 reg, reg2;
++
++ /* Read reg27 (error register) */
++ star_nic_read_phy(port, 27, ®);
++ /* if error exists, set Bypass Filter enable */
++ if ((reg & 0xfffc)) {
++ star_nic_read_phy(port, 15, ®);
++ star_nic_read_phy(port, 27, ®2);
++ if (( reg2 & 0xfffc) && (((reg >> 9) & 0xff) < 0x1c)) {
++ printk("8100 pos err\n");
++ /* Bypass agcgain disable */
++ star_nic_write_phy(port, 15, (reg & (~(0x1 << 7))));
++
++ /* repeat counts when reaching threshold error */
++ star_nic_write_phy(port, 13, 0x4940);
++
++ /* Speed up AN speed && compensate threshold phase error */
++ star_nic_write_phy(port, 14, 0xa306);
++
++ /* Bypass Filter enable */
++ star_nic_read_phy(port, 18, ®2);
++
++ star_nic_write_phy(port, 18, (reg | 0x400));
++
++ /* restart AN */
++ star_nic_write_phy(port, 0, 0x3300);
++ return 1;
++ }
++ }
++ return 0;
++}
++
++
++/*=============================================================*
++ * eth3220ac_rt8100_linkdown
++ *=============================================================*/
++static void eth3220ac_rt8100_linkdown(int port)
++{
++ u16 reg;
++
++ /* Bypass Filter disable */
++ star_nic_read_phy(port, 18, ®);
++ star_nic_write_phy(port, 18, (reg & (~(0x1 << 10))));
++ eth3220ac_def_linkdown_setting(port);
++}
++
++static void eth3220ac_normal_phy_setting(int port)
++{
++ star_nic_write_phy(port, 12, 0xd8ff);
++ eth3220ac_def_bpf(port);
++}
++
++/*=============================================================*
++ * wp3220ac_phystate
++ *=============================================================*/
++static void wp3220ac_phystate(int port, int link, int speed)
++{
++ int next_state;
++ u16 reg, reg2;
++
++ phy[port].timer += ETH3220_PHY_MON_PERIOD;
++
++ if (link) {
++ /* Link up state */
++ switch(phy[port].state) {
++ case LINK_UP_POSITIVE:
++ next_state = eth3220ac_rt8100_check(port) ?
++ WAIT_BYPASS_LINK_UP_POSITIVE :
++ LINK_UP_POSITIVE;
++ break;
++
++ case PHY_STATE_INIT:
++ case WAIT_LINK_UP_POSITIVE:
++ case LINK_DOWN_POSITIVE:
++ next_state = LINK_UP_POSITIVE;
++ eth3220ac_def_linkup_setting(port);
++ eth3220ac_link_agc(port, speed);
++ eth3220ac_release_bpf(port);
++ break;
++
++ case WAIT_BYPASS_LINK_UP_POSITIVE:
++ case BYPASS_AND_LINK_UP_POSITIVE:
++ next_state = BYPASS_AND_LINK_UP_POSITIVE;
++ break;
++
++ case WAIT_8101_LINK_UP_POSITIVE:
++ next_state = LINK_UP_8101_POSITIVE;
++ eth3220ac_link_agc(port, speed);
++ star_nic_write_phy(port, 12, 0x98ff);
++ break;
++
++ case LINK_UP_8101_POSITIVE:
++ next_state = LINK_UP_8101_POSITIVE;
++ break;
++
++ default:
++ next_state = LINK_UP_POSITIVE;
++ eth3220ac_def_linkup_setting(port);
++ eth3220ac_link_agc(port, speed);
++ }
++ } else {
++ /* Link down state */
++ switch(phy[port].state) {
++ case LINK_DOWN_POSITIVE:
++ star_nic_read_phy(port, 5, ®);
++ star_nic_read_phy(port, 28, ®2);
++ /* AN Link Partner Ability Register or NLP */
++ if (reg || (reg2 & 0x100))
++ next_state = WAIT_LINK_UP_POSITIVE;
++ else
++ next_state = LINK_DOWN_POSITIVE;
++ break;
++
++ case WAIT_LINK_UP_POSITIVE:
++ if (phy[port].state_time > LINK_DOWN_ABILITY_DETECT_TIMEOUT)
++ next_state = LINK_DOWN_POSITIVE;
++ else
++ next_state = WAIT_LINK_UP_POSITIVE;
++ break;
++
++ case WAIT_BYPASS_LINK_UP_POSITIVE:
++ /* set timeout = 5 sec */
++ if (phy[port].state_time > WAIT_BYPASS_LINK_UP_POSITIVE_TIMEOUT) {
++ next_state = LINK_DOWN_POSITIVE;
++ /* Bypass Filter disable */
++ eth3220ac_rt8100_linkdown(port);
++ eth3220ac_def_bpf(port);
++ } else {
++ next_state = WAIT_BYPASS_LINK_UP_POSITIVE;
++ }
++ break;
++
++ case BYPASS_AND_LINK_UP_POSITIVE:
++ next_state = LINK_DOWN_POSITIVE;
++ eth3220ac_rt8100_linkdown(port);
++ eth3220ac_def_bpf(port);
++ break;
++
++ case WAIT_8101_LINK_UP_POSITIVE:
++ if (phy[port].state_time > WAIT_8101_LINK_UP_TIMEOUT) {
++ next_state = LINK_DOWN_POSITIVE;
++ eth3220ac_normal_phy_setting(port);
++ eth3220ac_def_linkdown_setting(port);
++ } else {
++ next_state = WAIT_8101_LINK_UP_POSITIVE;
++ }
++ break;
++
++ case LINK_UP_POSITIVE:
++ eth3220ac_unlink_agc(port);
++ eth3220ac_def_linkdown_setting(port);
++ eth3220ac_def_bpf(port);
++ if (phy[port].timer > DETECT_8101_PERIOD) {
++ next_state = LINK_DOWN_POSITIVE;
++ phy[port].timer = 0;
++ phy[port].linkdown_cnt = 1;
++ } else {
++ if (++phy[port].linkdown_cnt > 2) {
++ next_state = WAIT_8101_LINK_UP_POSITIVE;
++ eth3220ac_rt8101_phy_setting(port);
++ } else {
++ next_state = LINK_DOWN_POSITIVE;
++ }
++ }
++ break;
++
++ case LINK_UP_8101_POSITIVE:
++ eth3220ac_normal_phy_setting(port);
++ /* fall down to phy normal state */
++ case PHY_STATE_INIT:
++ eth3220ac_def_linkdown_setting(port);
++ eth3220ac_unlink_agc(port);
++ default:
++ next_state = LINK_DOWN_POSITIVE;
++ }
++ }
++
++ if (phy[port].state != next_state) {
++ phy[port].state_time = 0;
++#if DEBUG_PHY_STATE_TRANSITION
++ if (debug_phy_port == -1 || port == debug_phy_port)
++ {
++ if ((phy[port].state < PHY_STATE_LAST) && (next_state < PHY_STATE_LAST))
++ {
++ printk("p%d: %s->%s, %d, %d\n", port, phystate_name[phy[port].state],
++ phystate_name[next_state], phy[port].timer, phy[port].linkdown_cnt);
++ }
++ else
++ {
++ printk("p%d: %d->%d\n", port, phy[port].state, next_state);
++ }
++ }
++#endif /* DEBUG_PHY_STATE_TRANSITION */
++ } else {
++ phy[port].state_time += ETH3220_PHY_MON_PERIOD;
++ }
++ phy[port].state = next_state;
++}
++
++/*=============================================================*
++ * eth3220_phyinit:
++ *=============================================================*/
++static void eth3220ac_10m_agc(void)
++{
++ /* Force 10M AGC = 2c globally */
++ star_nic_write_phy(0, 31, 0x2f1a);
++ star_nic_write_phy(0, 12, 0x112c);
++ star_nic_write_phy(0, 13, 0x2e21);
++ star_nic_write_phy(0, 31, 0xaf1a);
++}
++
++static void eth3220ac_dfe_init(void)
++{
++ int i;
++
++ star_nic_write_phy(0, 31, 0x2f1a);
++ for (i=0; i <= 7; i++)
++ star_nic_write_phy(0, i, 0);
++ star_nic_write_phy(0, 11, 0x0b50);
++ star_nic_write_phy(0, 31, 0xaf1a);
++}
++
++static void eth3220ac_phy_cdr_training_init(void)
++{
++ int volatile i;
++
++ /* Force all port in 10M FD mode */
++ for (i=0; i < NUM_PHY; i++)
++ star_nic_write_phy(i, 0, 0x100);
++
++ /* Global setting */
++ star_nic_write_phy(0, 31, 0x2f1a);
++ star_nic_write_phy(0, 29, 0x5021);
++ udelay(2000); //2ms, wait > 1 ms
++ star_nic_write_phy(0, 29, 0x4021);
++ udelay(2000); //2ms, wait > 1 ms
++ star_nic_write_phy(0, 31, 0xaf1a);
++
++ /* Enable phy AN */
++ for (i=0; i < NUM_PHY; i++)
++ star_nic_write_phy(i, 0, 0x3100);
++}
++
++static void eth3220_phyinit(void)
++{
++ eth3220ac_10m_agc();
++ eth3220ac_dfe_init();
++ eth3220ac_phy_cdr_training_init();
++}
++
++static void eth3220_phycfg(int phyaddr)
++{
++ eth3220ac_def_linkdown_setting(phyaddr);
++ eth3220ac_normal_phy_setting(phyaddr);
++ star_nic_write_phy(phyaddr, 9, 0x7f);
++}
++
++static void internal_phy_patch_check(int init)
++{
++ u32 short_cable_agc_detect_count;
++ u32 link_status = 0, link_speed;
++ u32 ii, jj;
++ u16 phy_data;
++ u16 phy_data2;
++
++ star_nic_read_phy(STAR_NIC_PHY_ADDR, 1, &phy_data);
++ udelay(100);
++ star_nic_read_phy(STAR_NIC_PHY_ADDR, 1, &phy_data2);
++ if (((phy_data & 0x0004) != 0x0004) && ((phy_data2 & 0x0004) != 0x0004)) { // link down
++ short_cable_agc_detect_count = 0;
++ for (jj = 0; jj < INTERNAL_PHY_PATCH_CHECKCNT; jj++) {
++ star_nic_read_phy(STAR_NIC_PHY_ADDR, 15, &phy_data);
++ udelay(1000);
++ if (((phy_data) & 0x7F) <= 0x12) { // short cable
++ short_cable_agc_detect_count++;
++ break;
++ }
++ }
++ if (short_cable_agc_detect_count) { // short cable
++ phy_statemachine = wp3220ac_phystate;
++ eth3220_phyinit();
++ star_nic_read_phy(STAR_NIC_PHY_ADDR, 1, &phy_data);
++ if (phy_data & 0x0040) { // link up
++ link_status = 1;
++ }
++ if ((NIC_MAC_CONTROL_REG & 0xC) == 0x4) { // 100Mbps
++ link_speed = 1;
++ } else {
++ link_speed = 0;
++ }
++ link_status_old = link_status;
++ for (ii = 0; ii < MAX_PHY_PORT; link_status >>= 1, ii++) {
++ eth3220_phycfg(ii);
++#if 0
++ if (phy_statemachine != NULL)
++ (*phy_statemachine)(ii, link_status & 1, link_speed & 1);
++#endif
++ }
++ } else { // long cable
++ // set to global domain
++ star_nic_write_phy(NIC_PHY_ADDRESS, 31, 0x2f1a);
++ for (ii = 0; ii < 32; ii++) {
++ star_nic_write_phy(NIC_PHY_ADDRESS, ii, long_cable_global_reg[ii]);
++ }
++ // set to local domain
++ star_nic_write_phy(NIC_PHY_ADDRESS, 31, 0xaf1a);
++ for (ii = 0; ii < 32; ii++) {
++ star_nic_write_phy(NIC_PHY_ADDRESS, ii, long_cable_local_reg[ii]);
++ }
++ }
++ }
++}
++
++#endif
++//========================================================
+diff -rupN linux-2.6.35.11/drivers/net/str9100/dorado2.h linux-2.6.35.11-ts7500/drivers/net/str9100/dorado2.h
+--- linux-2.6.35.11/drivers/net/str9100/dorado2.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/str9100/dorado2.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,223 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef DORADO2_H
++#define DORADO2_H
++
++#include <linux/types.h>
++
++// this configure is for star dorado2
++
++// add by descent 2006/07/10
++#define DORADO2
++
++// add by KC 2006/09/07
++#ifdef CONFIG_STAR9100_SHNAT_PCI_FASTPATH
++// if no VSC8201 on MAC PORT1, we need to define this
++// if VSC8201 is present, mark it
++//#define DORADO2_PCI_FASTPATH_MAC_PORT1_LOOPBACK
++#endif
++
++#ifdef DORADO2
++// init phy or switch chip
++#define INIT_PORT0_PHY star_gsw_config_VSC7385();
++#ifdef DORADO2_PCI_FASTPATH_MAC_PORT1_LOOPBACK
++#define INIT_PORT1_PHY star_gsw_config_mac_port1_loopback();
++#else
++#define INIT_PORT1_PHY star_gsw_config_VSC8201(1,1);
++#endif
++//#define INIT_PORT1_PHY
++
++// configure mac0/mac1 register
++#define INIT_PORT0_MAC init_packet_forward(0);
++#define INIT_PORT1_MAC init_packet_forward(1);
++//#define INIT_PORT1_MAC
++
++#define PORT0_LINK_DOWN disable_AN(0, 0);
++#define PORT0_LINK_UP disable_AN(0, 1);
++
++#ifdef DORADO2_PCI_FASTPATH_MAC_PORT1_LOOPBACK
++#define PORT1_LINK_DOWN
++#define PORT1_LINK_UP
++#else
++#define PORT1_LINK_DOWN std_phy_power_down(1, 1);
++#define PORT1_LINK_UP std_phy_power_down(1, 0);
++#endif
++
++#define CREATE_NET_DEV0 star_gsw_probe(LAN_PORT);
++#define CREATE_NET_DEV1 star_gsw_probe(WAN_PORT);
++#define CREATE_NET_DEV2 star_gsw_probe(EWC_PORT);
++//#define CREATE_NET_DEV2
++
++#define CONFIG_STR9100_PORT_BASE
++#define CONFIG_STR9100_VLAN_BASE
++//#define CONFIG_HAVE_VLAN_TAG
++
++// for port base, port base max is 2 port.
++// use in star_gsw_get_rfd_buff().
++// if a port no used, define to "0;"
++// NET_DEV0 : rx->sp 0 (port 0)
++#define NET_DEV0 0
++// NET_DEV1 : rx->sp 1 (port 1)
++#define NET_DEV1 STAR_GSW_EWC_DEV
++
++// for star_gsw_send_packet
++// port base and vlan base packet flow
++#define PORT_BASE_PMAP_LAN_PORT -1
++#define PORT_BASE_PMAP_WAN_PORT -1
++#define PORT_BASE_PMAP_EWC_PORT 2 // 2 port 1
++
++#define MODEL "DORADO2"
++
++// OPEN_PORT0 include 2 actions
++// 1. enable mac port
++// 2. link up port
++#define OPEN_PORT(dev) \
++{ \
++ u32 mac_port_config; \
++ \
++ if (dev == STAR_GSW_EWC_DEV) { \
++ memcpy(dev->dev_addr, star_gsw_info.vlan[2].vlan_mac, 6);\
++ PRINT_INFO("open mac port1\n"); \
++ mac_port_config = GSW_MAC_PORT_1_CONFIG; \
++ /* disable port 1 */ \
++ mac_port_config &= (~(0x1 << 18)); \
++ GSW_MAC_PORT_1_CONFIG = mac_port_config; \
++ PORT1_LINK_UP \
++ } \
++ if (dev == STAR_GSW_LAN_DEV || dev == STAR_GSW_WAN_DEV) { \
++ if (dev == STAR_GSW_LAN_DEV) \
++ memcpy(dev->dev_addr, star_gsw_info.vlan[1].vlan_mac, 6);\
++ if (dev == STAR_GSW_WAN_DEV) \
++ memcpy(dev->dev_addr, star_gsw_info.vlan[0].vlan_mac, 6);\
++ /* rc_port is a reference count variable. */ \
++ if (rc_port == 0) {\
++ PRINT_INFO("open mac port 0\n");\
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;\
++ /* enable port 0 */ \
++ mac_port_config &= (~(0x1 << 18));\
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;\
++ PORT0_LINK_UP\
++ }\
++ else{\
++ PRINT_INFO("port 0 already open\n");\
++ }\
++ ++rc_port;\
++ } \
++}
++
++// CLOSE_PORT include 2 actions
++// 1. disable mac port
++// 2. link down port
++#define CLOSE_PORT(dev) \
++{ \
++ u32 mac_port_config; \
++ \
++ if (dev == STAR_GSW_EWC_DEV) { \
++ PRINT_INFO("close mac port1\n"); \
++ PORT1_LINK_DOWN \
++ mac_port_config = GSW_MAC_PORT_1_CONFIG; \
++ /* disable port 1 */ \
++ mac_port_config |= ((0x1 << 18)); \
++ GSW_MAC_PORT_1_CONFIG = mac_port_config; \
++ } \
++ if (dev == STAR_GSW_LAN_DEV || dev == STAR_GSW_WAN_DEV) { \
++ --rc_port;\
++ /* rc_port is a reference count variable. */ \
++ if (rc_port == 0) {\
++ PRINT_INFO("close mac port 0\n");\
++ PORT0_LINK_DOWN\
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;\
++ /* disable port 0 */ \
++ mac_port_config |= ((0x1 << 18));\
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;\
++ }\
++ else {\
++ PRINT_INFO("a live net device\n");\
++ }\
++ } \
++}
++
++
++
++#define VLAN0_VID (0x2)
++#define VLAN1_VID (0x1)
++#define VLAN2_VID (0x3)
++#define VLAN3_VID (0x4)
++#define VLAN4_VID (0x5)
++#define VLAN5_VID (0x6)
++#define VLAN6_VID (0x7)
++#define VLAN7_VID (0x8)
++
++#define VLAN0_GROUP (PORT0 | CPU_PORT)
++#define VLAN1_GROUP (PORT0 | CPU_PORT)
++#define VLAN2_GROUP (PORT1 | CPU_PORT)
++#define VLAN3_GROUP (PORT1 | CPU_PORT)
++#define VLAN4_GROUP (0)
++#define VLAN5_GROUP (0)
++#define VLAN6_GROUP (0)
++#define VLAN7_GROUP (PORT1 | CPU_PORT)
++
++
++#ifdef CONFIG_HAVE_VLAN_TAG
++
++#define VLAN0_VLAN_TAG (5) // cpu port and mac 0 port
++#define VLAN1_VLAN_TAG (5) // cpu port and mac 0 port
++
++#else
++#define VLAN0_VLAN_TAG (1) // only mac 0 port
++#define VLAN1_VLAN_TAG (1) // only mac 0 port
++#endif
++
++#define VLAN2_VLAN_TAG (0)
++#define VLAN3_VLAN_TAG (0)
++#define VLAN4_VLAN_TAG (0)
++#define VLAN5_VLAN_TAG (0)
++#define VLAN6_VLAN_TAG (0)
++#define VLAN7_VLAN_TAG (0)
++
++
++/* wan eth1 */
++static u8 my_vlan0_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x50};
++
++/* lan eth 0*/
++static u8 my_vlan1_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x60};
++
++/* cpu */
++static u8 my_vlan2_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x22};
++
++/* ewc */
++static u8 my_vlan3_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x23};
++
++// this value is for hnat
++// GID is vlan group id
++#define LAN_GID 1
++#define WAN_GID 0
++
++
++#endif //DORADO2
++
++
++
++
++#endif
+diff -rupN linux-2.6.35.11/drivers/net/str9100/dorado.h linux-2.6.35.11-ts7500/drivers/net/str9100/dorado.h
+--- linux-2.6.35.11/drivers/net/str9100/dorado.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/str9100/dorado.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,188 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef DORADO_H
++#define DORADO_H
++
++int disable_AN(int port, int y);
++// this configure is for star dorado2
++
++// add by descent 2006/07/10
++#define DORADO
++#ifdef DORADO
++// init phy or switch chip
++#define INIT_PORT0_PHY star_gsw_config_VSC7385();
++#define INIT_PORT1_PHY
++//#define INIT_PORT1_PHY
++
++// configure mac0/mac1 register
++#define INIT_PORT0_MAC init_packet_forward(0);
++#define INIT_PORT1_MAC
++//#define INIT_PORT1_MAC
++
++#define PORT0_LINK_DOWN disable_AN(0, 0);
++#define PORT0_LINK_UP disable_AN(0, 1);
++
++#define PORT1_LINK_DOWN
++#define PORT1_LINK_UP
++
++#define CREATE_NET_DEV0 star_gsw_probe(LAN_PORT);
++#define CREATE_NET_DEV1 star_gsw_probe(WAN_PORT);
++#define CREATE_NET_DEV2
++//#define CREATE_NET_DEV2
++
++#undef CONFIG_STR9100_PORT_BASE
++#define CONFIG_STR9100_VLAN_BASE
++#undef CONFIG_HAVE_VLAN_TAG
++
++
++// for star_gsw_send_packet
++// port base and vlan base packet flow
++#define PORT_BASE_PMAP_LAN_PORT INVALID_PORT_BASE_PMAP_PORT
++#define PORT_BASE_PMAP_WAN_PORT INVALID_PORT_BASE_PMAP_PORT
++#define PORT_BASE_PMAP_EWC_PORT INVALID_PORT_BASE_PMAP_PORT
++
++#define MODEL "DORADO"
++
++// OPEN_PORT0 include 2 actions
++// 1. enable mac port
++// 2. link up port
++#define OPEN_PORT(dev) \
++{ \
++ u32 mac_port_config; \
++ \
++ if (dev == STAR_GSW_LAN_DEV || dev == STAR_GSW_WAN_DEV) { \
++ if (dev == STAR_GSW_LAN_DEV) { \
++ /*printk("STAR_GSW_LAN_DEV\n"); */ \
++ /*memcpy(dev->dev_addr, star_gsw_info.vlan[LAN_GID].vlan_mac, 6);*/ \
++ } \
++ if (dev == STAR_GSW_WAN_DEV) { \
++ /* printk("STAR_GSW_WAN_DEV\n"); */ \
++ /*memcpy(dev->dev_addr, star_gsw_info.vlan[WAN_GID].vlan_mac, 6);*/ \
++ } \
++ /* rc_port is a reference count variable. */ \
++ if (rc_port == 0) {\
++ PRINT_INFO("open mac port 0\n");\
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;\
++ /* enable port 0 */ \
++ mac_port_config &= (~(0x1 << 18));\
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;\
++ PORT0_LINK_UP\
++ }\
++ else{\
++ PRINT_INFO("port 0 already open\n");\
++ }\
++ ++rc_port;\
++ } \
++}
++
++// CLOSE_PORT include 2 actions
++// 1. disable mac port
++// 2. link down port
++#define CLOSE_PORT(dev) \
++{ \
++ u32 mac_port_config; \
++ \
++ if (dev == STAR_GSW_LAN_DEV || dev == STAR_GSW_WAN_DEV) { \
++ /* rc_port is a reference count variable. */ \
++ --rc_port;\
++ if (rc_port == 0) {\
++ PRINT_INFO("close mac port 0\n");\
++ PORT0_LINK_DOWN\
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;\
++ /* disable port 0 */ \
++ mac_port_config |= ((0x1 << 18));\
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;\
++ }\
++ else {\
++ PRINT_INFO("a live net device\n");\
++ }\
++ } \
++}
++
++
++
++// the vlan past waht vlan tag value
++#define VLAN0_VID (0x2) // wan
++#define VLAN1_VID (0x1) // lan
++#define VLAN2_VID (0x3)
++#define VLAN3_VID (0x4)
++#define VLAN4_VID (0x5)
++#define VLAN5_VID (0x6)
++#define VLAN6_VID (0x7)
++#define VLAN7_VID (0x8)
++
++// the vlan include ports
++#define VLAN0_GROUP (PORT0 | CPU_PORT)
++#define VLAN1_GROUP (PORT0 | CPU_PORT)
++#define VLAN2_GROUP (0)
++#define VLAN3_GROUP (0)
++#define VLAN4_GROUP (0)
++#define VLAN5_GROUP (0)
++#define VLAN6_GROUP (0)
++#define VLAN7_GROUP (0)
++
++
++#ifdef CONFIG_HAVE_VLAN_TAG
++
++// the vlan which ports will past vlan tags.
++#define VLAN0_VLAN_TAG (5) // cpu port and mac 0 port
++#define VLAN1_VLAN_TAG (5) // cpu port and mac 0 port
++
++#else
++#define VLAN0_VLAN_TAG (1) // only mac 0 port
++#define VLAN1_VLAN_TAG (1) // only mac 0 port
++#endif
++
++#define VLAN2_VLAN_TAG (0)
++#define VLAN3_VLAN_TAG (0)
++#define VLAN4_VLAN_TAG (0)
++#define VLAN5_VLAN_TAG (0)
++#define VLAN6_VLAN_TAG (0)
++#define VLAN7_VLAN_TAG (0)
++
++
++/* wan eth1 */
++static u8 my_vlan0_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x50};
++
++/* lan eth 0*/
++static u8 my_vlan1_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x60};
++
++/* cpu */
++static u8 my_vlan2_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x22};
++
++/* ewc */
++static u8 my_vlan3_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x23};
++
++// this value is for hnat
++// GID is vlan group id
++#define LAN_GID 1
++#define WAN_GID 0
++
++
++#endif //DORADO
++
++
++
++
++#endif
+diff -rupN linux-2.6.35.11/drivers/net/str9100/Kconfig linux-2.6.35.11-ts7500/drivers/net/str9100/Kconfig
+--- linux-2.6.35.11/drivers/net/str9100/Kconfig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/str9100/Kconfig 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,45 @@
++menu "CNS1100 Gigabit Switch support"
++ depends on ARCH_STR9100
++
++config STAR_GSW
++ tristate "CNS1100 Gigabit Switch driver support"
++
++config STR9100_SHNAT
++ bool "CNS1100 Smart HNAT Support"
++ depends on STAR_GSW
++ help
++ Add STAR Smart HNAT support function in kernel
++
++config STAR9100_SHNAT_PCI_FASTPATH
++ bool "FastPath(From PCI to WAN) Support"
++ depends on STR9100_SHNAT
++ help
++ Add FastPath Support for Smart HNAT.
++
++choice
++ prompt "CNS1100 Board"
++ depends on STAR_GSW
++ default DORADO
++
++config DORADO
++ bool "Dorado"
++
++config DORADO2
++ bool "Dorado2"
++
++config VIRGO
++ bool "Virgo"
++
++config VELA
++ bool "Vela"
++
++config LIBRA
++ bool "Libra"
++
++config LEO
++ bool "Leo"
++
++endchoice
++
++endmenu
++
+diff -rupN linux-2.6.35.11/drivers/net/str9100/leo.h linux-2.6.35.11-ts7500/drivers/net/str9100/leo.h
+--- linux-2.6.35.11/drivers/net/str9100/leo.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/str9100/leo.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,152 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef LEO_H
++#define LEO_H
++
++// add by descent 2006/07/10
++#define LEO
++#ifdef LEO
++// init phy or switch chip
++#define INIT_PORT0_PHY star_gsw_config_VSC8201(0,0);
++#define INIT_PORT1_PHY
++
++// configure mac0/mac1 register
++#define INIT_PORT0_MAC init_packet_forward(0);
++#define INIT_PORT1_MAC disable_AN(1, 1);
++// if no disable_AN port 1, maybe get link up/down (change link state)
++
++#define PORT0_LINK_DOWN std_phy_power_down(0,1);
++#define PORT0_LINK_UP std_phy_power_down(0,0);
++
++#define PORT1_LINK_DOWN
++#define PORT1_LINK_UP
++
++#define CREATE_NET_DEV0 star_gsw_probe(LAN_PORT);
++#define CREATE_NET_DEV1
++#define CREATE_NET_DEV2
++
++
++#define CONFIG_STR9100_PORT_BASE
++#undef CONFIG_STR9100_VLAN_BASE
++#undef CONFIG_HAVE_VLAN_TAG
++
++// for port base, port base max is 2 port.
++// NET_DEV0 : rx->sp 0 (port 0)
++#define NET_DEV0 STAR_GSW_LAN_DEV
++// NET_DEV1 : rx->sp 1 (port 1)
++#define NET_DEV1 0
++
++// for star_gsw_send_packet
++// port base and vlan base packet flow
++#define PORT_BASE_PMAP_LAN_PORT PORT0
++#define PORT_BASE_PMAP_WAN_PORT INVALID_PORT_BASE_PMAP_PORT
++#define PORT_BASE_PMAP_EWC_PORT INVALID_PORT_BASE_PMAP_PORT
++
++#define MODEL "LEO"
++
++// OPEN_PORT0 include 2 actions
++// 1. enable mac port
++// 2. link up port
++#define OPEN_PORT(dev) \
++{ \
++ u32 mac_port_config; \
++ \
++ if (dev == STAR_GSW_LAN_DEV) { \
++ memcpy(dev->dev_addr, star_gsw_info.vlan[1].vlan_mac, 6);\
++ PRINT_INFO("open mac port 0\n");\
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;\
++ /* enable port 0 */ \
++ mac_port_config &= (~(0x1 << 18));\
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;\
++ PORT0_LINK_UP\
++ } \
++}
++
++// CLOSE_PORT include 2 actions
++// 1. disable mac port
++// 2. link down port
++#define CLOSE_PORT(dev) \
++{ \
++ u32 mac_port_config; \
++ \
++ if (dev == STAR_GSW_LAN_DEV) { \
++ PRINT_INFO("close mac port 0\n");\
++ PORT0_LINK_DOWN\
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;\
++ /* disable port 0 */ \
++ mac_port_config |= ((0x1 << 18));\
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;\
++ } \
++}
++
++
++#define VLAN0_VID (0x111)
++#define VLAN1_VID (0x222)
++#define VLAN2_VID (0x333)
++#define VLAN3_VID (0x444)
++#define VLAN4_VID (0x555)
++#define VLAN5_VID (0x666)
++#define VLAN6_VID (0x777)
++#define VLAN7_VID (0x888)
++
++
++#define VLAN0_GROUP (CPU_PORT | PORT0)
++#define VLAN1_GROUP (PORT0 | CPU_PORT)
++//#define VLAN0_GROUP (PORT0 | PORT1 | CPU_PORT)
++//#define VLAN1_GROUP (PORT0 | CPU_PORT)
++//#define VLAN2_GROUP (PORT1 | CPU_PORT)
++#define VLAN2_GROUP (0)
++#define VLAN3_GROUP (0)
++#define VLAN4_GROUP (0)
++#define VLAN5_GROUP (0)
++#define VLAN6_GROUP (0)
++#define VLAN7_GROUP (0)
++
++#define VLAN0_VLAN_TAG (0)
++#define VLAN1_VLAN_TAG (0)
++#define VLAN2_VLAN_TAG (0)
++#define VLAN3_VLAN_TAG (0)
++#define VLAN4_VLAN_TAG (0)
++#define VLAN5_VLAN_TAG (0)
++#define VLAN6_VLAN_TAG (0)
++#define VLAN7_VLAN_TAG (0)
++
++//#define PORT0_PVID (VLAN0_GROUP_ID)
++//#define PORT1_PVID (VLAN2_GROUP_ID)
++//#define CPU_PORT_PVID (VLAN1_GROUP_ID)
++
++static u8 my_vlan0_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x12};
++static u8 my_vlan1_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x22};
++static u8 my_vlan2_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x32};
++static u8 my_vlan3_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x42};
++
++// this value is for hnat
++// GID is vlan group id
++#define LAN_GID 0
++#define WAN_GID 2
++
++
++#endif // LEO
++
++#endif
+diff -rupN linux-2.6.35.11/drivers/net/str9100/libra.h linux-2.6.35.11-ts7500/drivers/net/str9100/libra.h
+--- linux-2.6.35.11/drivers/net/str9100/libra.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/str9100/libra.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,184 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef LIBRA_H
++#define LIBRA_H
++
++// this configure is for star LIBRA
++
++// add by descent 2006/07/10
++#define LIBRA
++#ifdef LIBRA
++// init phy or switch chip
++#define INIT_PORT0_PHY configure_icplus_175c_phy();
++#define INIT_PORT1_PHY
++//#define INIT_PORT1_PHY
++
++// configure mac0/mac1 register
++#define INIT_PORT0_MAC init_packet_forward(0);
++#define INIT_PORT1_MAC
++//#define INIT_PORT1_MAC
++
++#define PORT0_LINK_DOWN icp_175c_all_phy_power_down(1);
++#define PORT0_LINK_UP icp_175c_all_phy_power_down(0);
++
++#define PORT1_LINK_DOWN
++#define PORT1_LINK_UP
++
++#define CREATE_NET_DEV0 star_gsw_probe(LAN_PORT);
++#define CREATE_NET_DEV1 star_gsw_probe(WAN_PORT);
++#define CREATE_NET_DEV2
++//#define CREATE_NET_DEV2
++
++#undef CONFIG_STR9100_PORT_BASE
++#define CONFIG_STR9100_VLAN_BASE
++#undef CONFIG_HAVE_VLAN_TAG
++#define CONFIG_HAVE_VLAN_TAG
++
++
++// for star_gsw_send_packet
++// port base and vlan base packet flow
++#define PORT_BASE_PMAP_LAN_PORT INVALID_PORT_BASE_PMAP_PORT
++#define PORT_BASE_PMAP_WAN_PORT INVALID_PORT_BASE_PMAP_PORT
++#define PORT_BASE_PMAP_EWC_PORT INVALID_PORT_BASE_PMAP_PORT
++
++#define MODEL "LIBRA"
++
++// OPEN_PORT0 include 2 actions
++// 1. enable mac port
++// 2. link up port
++#define OPEN_PORT(dev) \
++{ \
++ u32 mac_port_config; \
++ \
++ if (dev == STAR_GSW_LAN_DEV || dev == STAR_GSW_WAN_DEV) { \
++ if (dev == STAR_GSW_LAN_DEV) \
++ memcpy(dev->dev_addr, star_gsw_info.vlan[LAN_GID].vlan_mac, 6);\
++ if (dev == STAR_GSW_WAN_DEV) \
++ memcpy(dev->dev_addr, star_gsw_info.vlan[WAN_GID].vlan_mac, 6);\
++ /* rc_port is a reference count variable. */ \
++ if (rc_port == 0) {\
++ PRINT_INFO("open mac port 0\n");\
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;\
++ /* enable port 0 */ \
++ mac_port_config &= (~(0x1 << 18));\
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;\
++ PORT0_LINK_UP\
++ }\
++ else{\
++ PRINT_INFO("port 0 already open\n");\
++ }\
++ ++rc_port;\
++ } \
++}
++
++// CLOSE_PORT include 2 actions
++// 1. disable mac port
++// 2. link down port
++#define CLOSE_PORT(dev) \
++{ \
++ u32 mac_port_config; \
++ \
++ if (dev == STAR_GSW_LAN_DEV || dev == STAR_GSW_WAN_DEV) { \
++ /* rc_port is a reference count variable. */ \
++ --rc_port;\
++ if (rc_port == 0) {\
++ PRINT_INFO("close mac port 0\n");\
++ PORT0_LINK_DOWN\
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;\
++ /* disable port 0 */ \
++ mac_port_config |= ((0x1 << 18));\
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;\
++ }\
++ else {\
++ PRINT_INFO("a live net device\n");\
++ }\
++ } \
++}
++
++
++
++// the vlan past waht vlan tag value
++#define VLAN0_VID (0x2) // wan
++#define VLAN1_VID (0x1) // lan
++#define VLAN2_VID (0x3)
++#define VLAN3_VID (0x4)
++#define VLAN4_VID (0x5)
++#define VLAN5_VID (0x6)
++#define VLAN6_VID (0x7)
++#define VLAN7_VID (0x8)
++
++// the vlan include ports
++#define VLAN0_GROUP (PORT0 | CPU_PORT)
++#define VLAN1_GROUP (PORT0 | CPU_PORT)
++#define VLAN2_GROUP (0)
++#define VLAN3_GROUP (0)
++#define VLAN4_GROUP (0)
++#define VLAN5_GROUP (0)
++#define VLAN6_GROUP (0)
++#define VLAN7_GROUP (0)
++
++
++#ifdef CONFIG_HAVE_VLAN_TAG
++
++// the vlan which ports will past vlan tags.
++#define VLAN0_VLAN_TAG (5) // cpu port and mac 0 port
++#define VLAN1_VLAN_TAG (5) // cpu port and mac 0 port
++
++#else
++#define VLAN0_VLAN_TAG (1) // only mac 0 port
++#define VLAN1_VLAN_TAG (1) // only mac 0 port
++#endif
++
++#define VLAN2_VLAN_TAG (0)
++#define VLAN3_VLAN_TAG (0)
++#define VLAN4_VLAN_TAG (0)
++#define VLAN5_VLAN_TAG (0)
++#define VLAN6_VLAN_TAG (0)
++#define VLAN7_VLAN_TAG (0)
++
++
++/* wan eth1 */
++static u8 my_vlan0_mac[6] = {0x00, 0x11, 0xbb, 0xcc, 0xdd, 0x50};
++
++/* lan eth 0*/
++static u8 my_vlan1_mac[6] = {0x00, 0x11, 0xbb, 0xcc, 0xdd, 0x60};
++
++/* cpu */
++static u8 my_vlan2_mac[6] = {0x00, 0x11, 0xbb, 0xcc, 0xdd, 0x22};
++
++/* ewc */
++static u8 my_vlan3_mac[6] = {0x00, 0x11, 0xbb, 0xcc, 0xdd, 0x23};
++
++// this value is for hnat
++// GID is vlan group id
++#define LAN_GID 1
++#define WAN_GID 0
++
++
++#endif //LIBRA
++
++
++
++
++#endif
+diff -rupN linux-2.6.35.11/drivers/net/str9100/Makefile linux-2.6.35.11-ts7500/drivers/net/str9100/Makefile
+--- linux-2.6.35.11/drivers/net/str9100/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/str9100/Makefile 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,38 @@
++################################################################################
++#
++#
++# Copyright(c) 2005 - Star semiconduction. 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 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.
++#
++# The full GNU General Public License is included in this distribution in the
++# file called LICENSE.
++#
++# Contact Information:
++# Star semiconduction Linux Support <support at starsemi.com>
++#
++################################################################################
++
++#
++# Makefile for the Star GSW ethernet driver
++#
++
++#obj-y :=
++#obj-m :=
++
++obj-$(CONFIG_STAR_GSW) += str9100.o
++str9100-objs := star_gsw_phy.o star_gsw.o
++
++#include $(TOPDIR)/Rules.make
+diff -rupN linux-2.6.35.11/drivers/net/str9100/star_gsw.c linux-2.6.35.11-ts7500/drivers/net/str9100/star_gsw.c
+--- linux-2.6.35.11/drivers/net/str9100/star_gsw.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/str9100/star_gsw.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,3421 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include "star_gsw.h"
++
++#ifdef LINUX24
++#include <asm/arch/str9100/star_tool.h>
++#include <asm/arch/str9100/star_misc.h>
++#endif
++
++#ifdef LINUX26
++#include <asm/arch/star_misc.h>
++#endif
++
++#if defined(LINUX24)
++#if defined(CONFIG_STAR9100_SHNAT_PCI_FASTPATH)
++#include <linux/star9100/star9100_shnat.h>
++#include <linux/star9100/str9100_shnat_hook.h>
++#endif /* defined(CONFIG_STAR9100_SHNAT_PCI_FASTPATH) */
++#elif defined(LINUX26) /* defined(LINUX24) */
++#if defined(CONFIG_STR9100_SHNAT)
++#include <linux/str9100/star9100_shnat.h>
++#include <linux/str9100/str9100_shnat_hook.h>
++#endif /* defined(CONFIG_STAR9100_SHNAT_PCI_FASTPATH) */
++#endif /* defined(LINUX24) */
++
++#if defined(LINUX24)
++#define IRQ_RETURN void
++#define IRQ_HANDLED
++static const char star_gsw_driver_version[] =
++ "Star GSW Driver(for Linux Kernel 2.4) - Star Semiconductor\n";
++#elif defined(LINUX26)
++#define IRQ_RETURN irqreturn_t
++static const char star_gsw_driver_version[] =
++ "Star GSW Driver(for Linux Kernel 2.6) - Star Semiconductor\n";
++#endif
++
++
++#define DRV_VERSION "0.01"
++
++int all_netdevice=0;
++
++
++irqreturn_t star_gsw_receive_isr(int irq, void *dev_id, struct pt_regs *regs);
++//struct proc_dir_entry *str9100_gsw_procdir=0;
++static u32 max_pend_int_cnt=MAX_PEND_INT_CNT, max_pend_time=MAX_PEND_TIME;
++
++#define MIN_PACKET_LEN 60
++
++
++static struct net_device *STAR_GSW_LAN_DEV;
++static struct net_device *STAR_GSW_WAN_DEV;
++static struct net_device *STAR_GSW_EWC_DEV;
++
++static struct net_device *STAR_NAPI_DEV;
++
++#define NETDEV_SIZE 10
++static struct net_device *net_dev_array[NETDEV_SIZE];
++
++
++static int install_isr_account = 0;
++static int rc_port = 0; // rc mean reference counting, determine port open/close.
++static int fsrc_count = 0;
++static volatile unsigned long is_qf = 0; // determine queue full state
++
++gsw_info_t star_gsw_info;
++static spinlock_t star_gsw_send_lock;
++
++static TXRING_INFO txring;
++static RXRING_INFO rxring;
++
++static struct proc_dir_entry *star_gsw_proc_entry;
++
++#ifdef CONFIG_STAR_GSW_NAPI
++static void star_gsw_receive_packet(int mode, int *work_done, int work_to_do);
++#else
++static void star_gsw_receive_packet(int mode);
++#endif
++
++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++void gsw_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid);
++void gsw_vlan_rx_register(struct net_device *dev, struct vlan_group *grp);
++#endif
++
++static int star_gsw_notify_reboot(struct notifier_block *nb, unsigned long event, void *ptr);
++
++static struct notifier_block star_gsw_notifier_reboot = {
++ .notifier_call = star_gsw_notify_reboot,
++ .next = NULL,
++ .priority = 0
++};
++
++
++
++
++#ifdef STAR_GSW_TIMER
++static struct timer_list star_gsw_timer;
++static void star_gsw_timer_func(unsigned long data)
++{
++ int i;
++ int tssd_index;
++ int tssd_current;
++ int skb_free_count = 0;
++ STAR_GSW_TXDESC volatile *txdesc_ptr;
++ unsigned long flags;
++
++ local_irq_save(flags);
++ HAL_GSW_READ_TSSD(tssd_current);
++ tssd_index = (tssd_current - (u32)txring.phy_addr) >> 4;
++ if (tssd_index > txring.to_free_index) {
++ skb_free_count = tssd_index - txring.to_free_index;
++ } else if (tssd_index < txring.to_free_index) {
++ skb_free_count = STAR_GSW_MAX_TFD_NUM + tssd_index - txring.to_free_index;
++ }
++ for (i = 0; i < skb_free_count; i++) {
++ txdesc_ptr = txring.vir_addr + txring.to_free_index;
++ if (txdesc_ptr->cown == 0) {
++ break;
++ }
++ if (txring.skb_ptr[txring.to_free_index]) {
++ dev_kfree_skb_any(txring.skb_ptr[txring.to_free_index]);
++ txring.skb_ptr[txring.to_free_index] = NULL;
++ }
++ txring.to_free_index++;
++ if (txring.to_free_index == STAR_GSW_MAX_TFD_NUM) {
++ txring.to_free_index = 0;
++ }
++ }
++ local_irq_restore(flags);
++}
++#endif
++
++
++#define between(x, start, end) ((x)>=(start) && (x)<=(end))
++void print_packet(unsigned char *data, int len)
++{
++ int i,j;
++
++ printk("packet length: %d%s:\n", len, len>128?"(only show the first 128 bytes)":"");
++ if(len > 128) {
++ len = 128;
++ }
++ for(i=0;len;) {
++ if(len >=16 ) {
++ for(j=0;j<16;j++) {
++ printk("%02x ", data[i++]);
++ }
++ printk("| ");
++
++ i -= 16;
++ for(j=0;j<16;j++) {
++ if( between(data[i], 0x21, 0x7e) ) {
++ printk("%c", data[i++]);
++ }
++ else {
++ printk(".");
++ i++;
++ }
++ }
++ printk("\n");
++
++ len -= 16;
++ }
++ else {
++ /* last line */
++
++ for(j=0; j<len; j++) {
++ printk("%02x ", data[i++]);
++ }
++ for(;j<16;j++) {
++ printk(" ");
++ }
++ printk("| ");
++
++ i -= len;
++ for(j=0;j<len;j++) {
++ if( between(data[i], 0x21, 0x7e) ) {
++ printk("%c", data[i++]);
++ }
++ else {
++ printk(".");
++ i++;
++ }
++ }
++ for(;j<16;j++) {
++ printk(" ");
++ }
++ printk("\n");
++
++ len = 0;
++ }
++ }
++ return;
++
++}
++
++// add by descent 2006/07/07
++void init_switch()
++{
++ u32 sw_config;
++
++ /*
++ * Configure GSW configuration
++ */
++ sw_config = GSW_SWITCH_CONFIG;
++
++#if 0
++ // orignal virgon configuration
++ // enable fast aging
++ sw_config |= (0xF);
++
++ // CRC stripping
++ sw_config |= (0x1 << 21);
++
++ // IVL learning
++ sw_config |= (0x1 << 22);
++ // HNAT disable
++ sw_config &= ~(0x1 << 23);
++
++ GSW_SWITCH_CONFIG = sw_config;
++
++ sw_config = GSW_SWITCH_CONFIG;
++#endif
++
++//#if 0
++ /* configure switch */
++ sw_config = GSW_SWITCH_CONFIG;
++
++ sw_config &= ~0xF; /* disable aging */
++ sw_config |= 0x1; /* disable aging */
++
++#ifdef JUMBO_ENABLE
++
++ // CRC stripping and GSW_CFG_MAX_LEN_JMBO
++ //sw_config |= (GSW_CFG_CRC_STRP | GSW_CFG_MAX_LEN_JMBO);
++ // CRC stripping and GSW_CFG_MAX_LEN_JMBO
++ sw_config |= ((0x1 << 21) | (0x3 << 4));
++
++#else
++ // CRC stripping and 1536 bytes
++ //sw_config |= (GSW_CFG_CRC_STRP | GSW_CFG_MAX_LEN_1536);
++ sw_config |= ((0x1 << 21) | (0x2 << 4));
++#endif
++
++ /* IVL */
++ //sw_config |= GSW_CFG_IVL;
++ sw_config |= (0x1 << 22);
++
++
++ /* disable HNAT */
++ //sw_config &= ~GSW_CFG_HNAT_EN;
++ sw_config &= ~(0x1 << 23);
++
++
++#ifdef CONFIG_STAR9100_SHNAT_PCI_FASTPATH
++ // PCI FASTPATH must enable firewall mode
++ sw_config |= (0x1 << 24);
++#endif
++
++ GSW_SWITCH_CONFIG = sw_config;
++//#endif
++}
++
++
++
++static int star_gsw_write_arl_table_entry(gsw_arl_table_entry_t *arl_table_entry)
++{
++ int i;
++
++ GSW_ARL_TABLE_ACCESS_CONTROL_0 = 0x0;
++ GSW_ARL_TABLE_ACCESS_CONTROL_1 = 0x0;
++ GSW_ARL_TABLE_ACCESS_CONTROL_2 = 0x0;
++
++ GSW_ARL_TABLE_ACCESS_CONTROL_1 = (((arl_table_entry->filter & 0x1) << 3) |
++ ((arl_table_entry->vlan_mac & 0x1) << 4) |
++ ((arl_table_entry->vlan_gid & 0x7) << 5) |
++ ((arl_table_entry->age_field & 0x7) << 8) |
++ ((arl_table_entry->port_map & 0x7) << 11) |
++ ((arl_table_entry->mac_addr[0] & 0xFF) << 16) |
++ ((arl_table_entry->mac_addr[1] & 0xFF) << 24));
++
++ GSW_ARL_TABLE_ACCESS_CONTROL_2 = (((arl_table_entry->mac_addr[2] & 0xFF) << 0) |
++ ((arl_table_entry->mac_addr[3] & 0xFF) << 8) |
++ ((arl_table_entry->mac_addr[4] & 0xFF) << 16) |
++ ((arl_table_entry->mac_addr[5] & 0xFF) << 24));
++
++ // issue the write command
++ GSW_ARL_TABLE_ACCESS_CONTROL_0 = (0x1 << 3);
++
++ for (i = 0; i < 0x1000; i++) {
++ if (GSW_ARL_TABLE_ACCESS_CONTROL_1 & (0x1)) {
++ return (1); // write OK
++ } else {
++ udelay(10);
++ }
++ }
++
++ return (0); // write failed
++}
++
++static int star_gsw_config_cpu_port(void)
++{
++ gsw_arl_table_entry_t arl_table_entry;
++ u32 cpu_port_config;
++
++ /*
++ * Write some default ARL table entries
++ */
++ // default ARL entry for VLAN0
++ arl_table_entry.filter = 0;
++ arl_table_entry.vlan_mac = 1; // the MAC in this table entry is MY VLAN MAC
++ arl_table_entry.vlan_gid = star_gsw_info.vlan[0].vlan_gid;
++ arl_table_entry.age_field = 0x7; // static entry
++ arl_table_entry.port_map = star_gsw_info.vlan[0].vlan_group;
++ memcpy(arl_table_entry.mac_addr, star_gsw_info.vlan[0].vlan_mac, 6);
++ if (!star_gsw_write_arl_table_entry(&arl_table_entry)) {
++ return 1;
++ }
++
++ // default ARL entry for VLAN1
++ arl_table_entry.filter = 0;
++ arl_table_entry.vlan_mac = 1;
++ arl_table_entry.vlan_gid = star_gsw_info.vlan[1].vlan_gid;
++ arl_table_entry.age_field = 0x7;
++ arl_table_entry.port_map = star_gsw_info.vlan[1].vlan_group;
++ memcpy(arl_table_entry.mac_addr, star_gsw_info.vlan[1].vlan_mac, 6);
++ if (!star_gsw_write_arl_table_entry(&arl_table_entry)) {
++ return 1;
++ }
++
++ // default ARL entry for VLAN2
++ arl_table_entry.filter = 0;
++ arl_table_entry.vlan_mac = 1;
++ arl_table_entry.vlan_gid = star_gsw_info.vlan[2].vlan_gid;
++ arl_table_entry.age_field = 0x7;
++ arl_table_entry.port_map = star_gsw_info.vlan[2].vlan_group;
++ memcpy(arl_table_entry.mac_addr, star_gsw_info.vlan[2].vlan_mac, 6);
++ if (!star_gsw_write_arl_table_entry(&arl_table_entry)) {
++ return 1;
++ }
++
++ // default ARL entry for VLAN3
++ arl_table_entry.filter = 0;
++ arl_table_entry.vlan_mac = 1;
++ arl_table_entry.vlan_gid = star_gsw_info.vlan[3].vlan_gid;
++ arl_table_entry.age_field = 0x7;
++ arl_table_entry.port_map = star_gsw_info.vlan[3].vlan_group;
++ memcpy(arl_table_entry.mac_addr, star_gsw_info.vlan[3].vlan_mac, 6);
++ if (!star_gsw_write_arl_table_entry(&arl_table_entry)) {
++ return 1;
++ }
++
++ GSW_SET_PORT0_PVID(star_gsw_info.port[0].pvid);
++ GSW_SET_PORT1_PVID(star_gsw_info.port[1].pvid);
++ GSW_SET_CPU_PORT_PVID(star_gsw_info.port[2].pvid);
++
++ GSW_SET_VLAN_0_VID(star_gsw_info.vlan[0].vlan_vid);
++ GSW_SET_VLAN_1_VID(star_gsw_info.vlan[1].vlan_vid);
++ GSW_SET_VLAN_2_VID(star_gsw_info.vlan[2].vlan_vid);
++ GSW_SET_VLAN_3_VID(star_gsw_info.vlan[3].vlan_vid);
++ GSW_SET_VLAN_4_VID(star_gsw_info.vlan[4].vlan_vid);
++ GSW_SET_VLAN_5_VID(star_gsw_info.vlan[5].vlan_vid);
++ GSW_SET_VLAN_6_VID(star_gsw_info.vlan[6].vlan_vid);
++ GSW_SET_VLAN_7_VID(star_gsw_info.vlan[7].vlan_vid);
++
++ GSW_SET_VLAN_0_MEMBER(star_gsw_info.vlan[0].vlan_group);
++ GSW_SET_VLAN_1_MEMBER(star_gsw_info.vlan[1].vlan_group);
++ GSW_SET_VLAN_2_MEMBER(star_gsw_info.vlan[2].vlan_group);
++ GSW_SET_VLAN_3_MEMBER(star_gsw_info.vlan[3].vlan_group);
++ GSW_SET_VLAN_4_MEMBER(star_gsw_info.vlan[4].vlan_group);
++ GSW_SET_VLAN_5_MEMBER(star_gsw_info.vlan[5].vlan_group);
++ GSW_SET_VLAN_6_MEMBER(star_gsw_info.vlan[6].vlan_group);
++ GSW_SET_VLAN_7_MEMBER(star_gsw_info.vlan[7].vlan_group);
++
++ GSW_SET_VLAN_0_TAG(star_gsw_info.vlan[0].vlan_tag_flag);
++ GSW_SET_VLAN_1_TAG(star_gsw_info.vlan[1].vlan_tag_flag);
++ GSW_SET_VLAN_2_TAG(star_gsw_info.vlan[2].vlan_tag_flag);
++ GSW_SET_VLAN_3_TAG(star_gsw_info.vlan[3].vlan_tag_flag);
++ GSW_SET_VLAN_4_TAG(star_gsw_info.vlan[4].vlan_tag_flag);
++ GSW_SET_VLAN_5_TAG(star_gsw_info.vlan[5].vlan_tag_flag);
++ GSW_SET_VLAN_6_TAG(star_gsw_info.vlan[6].vlan_tag_flag);
++ GSW_SET_VLAN_7_TAG(star_gsw_info.vlan[7].vlan_tag_flag);
++
++ // disable all interrupt status sources
++ GSW_DISABLE_ALL_INTERRUPT_STATUS_SOURCES();
++
++ // clear previous interrupt sources
++ GSW_CLEAR_ALL_INTERRUPT_STATUS_SOURCES();
++
++ // disable all DMA-related interrupt sources
++ INTC_DISABLE_INTERRUPT_SOURCE(INTC_GSW_TSTC_BIT_INDEX);
++ INTC_DISABLE_INTERRUPT_SOURCE(INTC_GSW_FSRC_BIT_INDEX);
++ INTC_DISABLE_INTERRUPT_SOURCE(INTC_GSW_TSQE_BIT_INDEX);
++ INTC_DISABLE_INTERRUPT_SOURCE(INTC_GSW_FSQF_BIT_INDEX);
++
++ // clear previous interrupt sources
++ INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GSW_TSTC_BIT_INDEX);
++ INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GSW_FSRC_BIT_INDEX);
++ INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GSW_TSQE_BIT_INDEX);
++ INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GSW_FSQF_BIT_INDEX);
++
++ GSW_TS_DMA_STOP();
++ GSW_FS_DMA_STOP();
++
++ GSW_WRITE_TSSD(txring.phy_addr);
++ GSW_WRITE_TS_BASE(txring.phy_addr);
++ GSW_WRITE_FSSD(rxring.phy_addr);
++ GSW_WRITE_FS_BASE(rxring.phy_addr);
++
++ /*
++ * Configure CPU port
++ */
++ cpu_port_config = GSW_CPU_PORT_CONFIG;
++
++ //SA learning Disable
++ cpu_port_config |= (0x1 << 19);
++
++ //offset 4N +2
++ cpu_port_config &= ~(1 << 31);
++ //cpu_port_config |= (1 << 31);
++
++ /* enable the CPU port */
++ cpu_port_config &= ~(1 << 18);
++
++ GSW_CPU_PORT_CONFIG = cpu_port_config;
++
++ return 0;
++}
++
++static void star_gsw_interrupt_disable(void)
++{
++ INTC_DISABLE_INTERRUPT_SOURCE(INTC_GSW_STATUS_BIT_INDEX);
++ INTC_DISABLE_INTERRUPT_SOURCE(INTC_GSW_TSTC_BIT_INDEX);
++ INTC_DISABLE_INTERRUPT_SOURCE(INTC_GSW_FSRC_BIT_INDEX);
++}
++
++static void star_gsw_interrupt_enable(void)
++{
++ INTC_ENABLE_INTERRUPT_SOURCE(INTC_GSW_STATUS_BIT_INDEX);
++ // 20070321
++ //INTC_ENABLE_INTERRUPT_SOURCE(INTC_GSW_TSTC_BIT_INDEX);
++ INTC_ENABLE_INTERRUPT_SOURCE(INTC_GSW_FSRC_BIT_INDEX);
++}
++
++static int star_gsw_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
++{
++#if 0
++ int num = 0;
++ int ad;
++ u32 port;
++ u32 fssd_current;
++ int fssd_index, rxcount;
++ STAR_GSW_RXDESC volatile *rxdesc_ptr = (rxring.vir_addr + rxring.cur_index);
++
++ GSW_READ_FSSD(fssd_current);
++ fssd_index = (fssd_current - (u32)rxring.phy_addr) >> 4;
++
++ if (fssd_index > rxring.cur_index) {
++ rxcount = fssd_index - rxring.cur_index;
++ } else if (fssd_index < rxring.cur_index) {
++ rxcount = (STAR_GSW_MAX_RFD_NUM - rxring.cur_index) + fssd_index;
++ } else {
++ if (rxdesc_ptr->cown == 0) {
++ //goto receive_packet_exit;
++ rxcount = -1;
++ } else {
++ // Queue Full
++ rxcount = STAR_GSW_MAX_RFD_NUM;
++ }
++ }
++
++ port = GSW_MAC_PORT_0_CONFIG;
++ num = sprintf(page, "\nStar Giga Bit Switch\n");
++#ifdef CONFIG_STAR_GSW_NAPI
++ num += sprintf(page + num, "Receive Method : NAPI\n");
++#else
++ num += sprintf(page + num, "Receive Method : General\n");
++#endif
++
++#ifdef CONFIG_STAR9100_SHNAT_PCI_FASTPATH
++ num += sprintf(page + num, "Support SHNAT PCI Fast PATH\n");
++#endif
++
++ HAL_MISC_ORION_ECO_AD(ad);
++ num += sprintf(page + num, "Orion Version: %s\n", ad==1?"AD":"AC");
++
++ num += sprintf(page + num, "GSW_DELAYED_INTERRUPT_CONFIG: %x\n", GSW_DELAYED_INTERRUPT_CONFIG);
++
++ num += sprintf(page + num, "GSW_VLAN_VID_0_1: %x\n", GSW_VLAN_VID_0_1);
++ num += sprintf(page + num, "GSW_VLAN_VID_2_3: %x\n", GSW_VLAN_VID_2_3);
++ num += sprintf(page + num, "GSW_VLAN_VID_4_5: %x\n", GSW_VLAN_VID_4_5);
++ num += sprintf(page + num, "GSW_VLAN_VID_6_7: %x\n", GSW_VLAN_VID_6_7);
++
++ num += sprintf(page + num, "STAR_GSW_LAN_DEV: %x\n", STAR_GSW_LAN_DEV);
++ num += sprintf(page + num, "STAR_GSW_WAN_DEV: %x\n", STAR_GSW_WAN_DEV);
++ num += sprintf(page + num, "GSW_VLAN_TAG_PORT_MAP: %x\n", GSW_VLAN_TAG_PORT_MAP);
++ num += sprintf(page + num, "GSW_SWITCH_CONFIG: %x \n", GSW_SWITCH_CONFIG);
++ //num += sprintf(page + num, "is_qf: %d \n", is_qf);
++ num += sprintf(page + num, "GSW_VLAN_VID_0_1: %08X \n", GSW_VLAN_VID_0_1);
++ num += sprintf(page + num, "VLAN0_VID: %d \n", VLAN0_VID);
++ num += sprintf(page + num, "VLAN1_VID: %d \n", VLAN1_VID);
++
++ num += sprintf(page + num, "GSW_QUEUE_STATUS_TEST_1 : %x \n", GSW_QUEUE_STATUS_TEST_1);
++ num += sprintf(page + num, "GW_GSW_MAX_RFD_NUM : %d \n", STAR_GSW_MAX_RFD_NUM);
++ num += sprintf(page + num, "GW_GSW_MAX_TFD_NUM : %d \n", STAR_GSW_MAX_TFD_NUM);
++ num += sprintf(page + num, "GSW_INTERRUPT_STATUS : %x \n", GSW_INTERRUPT_STATUS);
++
++ num += sprintf(page + num, "MAC PORT 0 : %x \n", GSW_MAC_PORT_0_CONFIG);
++ if (port & (0x1 << 22))
++ num += sprintf(page + num, " IVL: IVL\n");
++ else
++ num += sprintf(page + num, " IVL: SVL\n");
++
++ port = GSW_MAC_PORT_1_CONFIG;
++ num += sprintf(page + num, "MAC PORT 1 : %x \n", GSW_MAC_PORT_1_CONFIG);
++ if (port & (0x1 << 22))
++ num += sprintf(page + num, " IVL: IVL\n");
++ else
++ num += sprintf(page + num, " IVL: SVL\n");
++
++ num += sprintf(page + num, " CPU PORT 1 : %x \n", GSW_CPU_PORT_CONFIG);
++
++ num += sprintf(page + num, "MODEL: %s\n", MODEL);
++#ifdef STAR_GSW_TX_HW_CHECKSUM
++ num += sprintf(page + num, "use TX hardware checksum\n");
++#endif
++#ifdef STAR_GSW_RX_HW_CHECKSUM
++ num += sprintf(page + num, "use RX hardware checksum\n");
++#endif
++
++#ifdef CONFIG_STR9100_VLAN_BASE
++ num += sprintf(page + num, "VLAN BASE\n");
++ #ifdef CONFIG_HAVE_VLAN_TAG
++ num += sprintf(page + num, "HAVE VLAN TAG\n");
++ #else
++ num += sprintf(page + num, "HAVE NO VLAN TAG\n");
++ #endif
++#endif
++
++#ifdef CONFIG_STR9100_PORT_BASE
++ num += sprintf(page + num, "PORT BASE\n");
++#endif
++
++// 20060922 descent
++#ifdef CONFIG_NIC_MODE
++ num += sprintf(page + num, "NIC MODE ON\n");
++#else
++ num += sprintf(page + num, "NIC MODE OFF\n");
++#endif
++// 20060922 descent end
++
++#ifdef STAR_GSW_SG
++ num += sprintf(page + num, "scatter gather on\n");
++#else
++ num += sprintf(page + num, "scatter gather off\n");
++#endif
++
++#ifdef FREE_TX_SKB_MULTI
++ num += sprintf(page + num, "FREE_TX_SKB_MULTI on\n");
++#else
++ num += sprintf(page + num, "FREE_TX_SKB_MULTI off\n");
++#endif
++
++#ifdef STAR_GSW_TIMER
++ num += sprintf(page + num, "STAR_GSW_TIMER on\n");
++#else
++ num += sprintf(page + num, "STAR_GSW_TIMER off\n");
++#endif
++
++
++#if 0
++ num += sprintf(page + num, " lan (eth0) mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
++ star_gsw_info.vlan[1].vlan_mac[0],
++ star_gsw_info.vlan[1].vlan_mac[1],
++ star_gsw_info.vlan[1].vlan_mac[2],
++ star_gsw_info.vlan[1].vlan_mac[3],
++ star_gsw_info.vlan[1].vlan_mac[4],
++ star_gsw_info.vlan[1].vlan_mac[5]);
++ num += sprintf(page + num, " wan (eth1) mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
++ star_gsw_info.vlan[0].vlan_mac[0],
++ star_gsw_info.vlan[0].vlan_mac[1],
++ star_gsw_info.vlan[0].vlan_mac[2],
++ star_gsw_info.vlan[0].vlan_mac[3],
++ star_gsw_info.vlan[0].vlan_mac[4],
++ star_gsw_info.vlan[0].vlan_mac[5]);
++#endif
++
++ return num;
++
++#endif
++
++
++ int num = 0;
++ u32 port=0;
++ const char *STR_ENABLE="Enable";
++ const char *STR_DISABLE="Disable";
++
++
++ num = sprintf(page, "Star STR9100 Gigabit Switch Driver Information \n");
++
++ num += sprintf(page + num, "%s\n", star_gsw_driver_version);
++ num += sprintf(page + num, "Demo Board Name: %s\n", MODEL);
++#ifdef CONFIG_STAR_GSW_NAPI
++ num += sprintf(page + num, "NAPI Function : %s\n", STR_ENABLE);
++#else
++ num += sprintf(page + num, "NAPI Function : %s\n", STR_DISABLE);
++#endif
++
++ port = GSW_SWITCH_CONFIG;
++ if (port & (0x1 << 22))
++ num += sprintf(page + num, "Independent VLAN Learning(IVL) Enable\n");
++ else
++ num += sprintf(page + num, "Share VLAN Learning (SVL) Enable\n");
++
++#ifdef CONFIG_STR9100_VLAN_BASE
++ num += sprintf(page + num, "Support Tag Base VLAN , Receive packet ");
++ #ifdef CONFIG_HAVE_VLAN_TAG
++ num += sprintf(page + num, "with vlan tag\n");
++ #else
++ num += sprintf(page + num, "without vlan tag\n");
++ #endif
++#endif
++
++#ifdef CONFIG_STR9100_PORT_BASE
++ num += sprintf(page + num, "Support Port Base VLAN\n");
++#endif
++
++
++ num += sprintf(page + num, "Max Receive Ring Buffer: %02d \n", STAR_GSW_MAX_RFD_NUM );
++ num += sprintf(page + num, "Max Send Ring Buffer: %02d\n", STAR_GSW_MAX_TFD_NUM );
++#ifdef STAR_GSW_TX_HW_CHECKSUM
++ num += sprintf(page + num, "TX Hardware checksum: %s \n", STR_ENABLE);
++#else
++ num += sprintf(page + num, "TX Hardware checksum: %s \n", STR_DISABLE);
++#endif
++#ifdef STAR_GSW_RX_HW_CHECKSUM
++ num += sprintf(page + num, "Rx Hardware checksum: %s\n", STR_ENABLE );
++#else
++ num += sprintf(page + num, "Rx Hardware checksum: %s\n", STR_DISABLE );
++#endif
++
++#ifndef STAR_GSW_DELAYED_INTERRUPT
++ // Disable Delayed Interrupt
++ num += sprintf(page + num, "Delay Interrupt %s\n",STR_DISABLE);
++#else
++ num += sprintf(page + num, "Delay Interrupt %s , Max Pending Interrupt Count: %d , Max Pending Timer : %d \n",
++ STR_ENABLE, MAX_PEND_INT_CNT, MAX_PEND_TIME);
++#endif
++ num += sprintf(page + num, "Group VID Info: GVID0_VID:%02X GVID1_VID: %02X GVID2_VID:%02X GVID3_VID: %02X \n",
++ GSW_VLAN_VID_0_1&0xFFF, (GSW_VLAN_VID_0_1>>12)&0xFFF,
++ GSW_VLAN_VID_2_3&0xFFF, (GSW_VLAN_VID_2_3>>12)&0xFFF);
++
++
++ num += sprintf(page + num, " GVID4_VID:%02X GVID5_VID: %02X GVID6_VID:%02X GVID7_VID: %02X \n",
++ GSW_VLAN_VID_4_5&0xFFF, (GSW_VLAN_VID_4_5>>12)&0xFFF,
++ GSW_VLAN_VID_6_7&0xFFF, (GSW_VLAN_VID_6_7>>12)&0xFFF);
++
++
++ num += sprintf(page + num, "Int. Buffer free pages count : %x(%d)\n",
++ GSW_QUEUE_STATUS_TEST_1&0xFF,GSW_QUEUE_STATUS_TEST_1&0xFF);
++ num += sprintf(page + num, "Interrupt Status : %x (Clean After Read)\n", GSW_INTERRUPT_STATUS);
++ GSW_INTERRUPT_STATUS= GSW_INTERRUPT_STATUS;
++
++ num += sprintf(page + num, "Switch Register: %x \n", GSW_SWITCH_CONFIG);
++ num += sprintf(page + num, "MAC0 REG: %x (%s:%s,%s,%s,%s)\n", GSW_MAC_PORT_0_CONFIG,
++ (GSW_MAC_PORT_0_CONFIG&(0x1<<18))==0?"Port Enable":"Port Disable",
++ (GSW_MAC_PORT_0_CONFIG&(0x1<<7))!=0?"AN Enable":"AN Disable",
++ (GSW_MAC_PORT_0_CONFIG&(0x11<<2))!=0x10?"1000Mbps":"10/100Mbps",
++ (GSW_MAC_PORT_0_CONFIG&(0x1<<4))==0x0?"Half Duplex":"Full Duplex",
++ (GSW_MAC_PORT_0_CONFIG&(0x1))!=0?"Link Up":"Link Down"
++ );
++ num += sprintf(page + num, "MAC1 REG: %x (%s:%s,%s,%s,%s)\n", GSW_MAC_PORT_1_CONFIG,
++ (GSW_MAC_PORT_0_CONFIG&(0x1<<18))==0?"Port Enable":"Port Disable",
++ (GSW_MAC_PORT_0_CONFIG&(0x1<<7))!=0?"AN Enable":"AN Disable",
++ (GSW_MAC_PORT_0_CONFIG&(0x11<<2))!=0x10?"1000Mbps":"10/100Mbps",
++ (GSW_MAC_PORT_0_CONFIG&(0x1<<4))==0x0?"Half Duplex":"Full Duplex",
++ (GSW_MAC_PORT_0_CONFIG&(0x1))!=0?"Link Up":"Link Down"
++ );
++
++ num += sprintf(page + num, "CPU REG: %x \n", GSW_CPU_PORT_CONFIG);
++ num += sprintf(page + num, "GSW_BIST_RESULT_TEST_0: %x\n", GSW_BIST_RESULT_TEST_0);
++#ifdef CONFIG_STR9100_VLAN_BASE
++ num += sprintf(page + num, "VLAN BASE\n");
++ #ifdef CONFIG_HAVE_VLAN_TAG
++ num += sprintf(page + num, "HAVE VLAN TAG\n");
++ #else
++ num += sprintf(page + num, "HAVE NO VLAN TAG\n");
++ #endif
++#endif
++
++#ifdef CONFIG_STR9100_PORT_BASE
++ num += sprintf(page + num, "PORT BASE\n");
++#endif
++
++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++ num += sprintf(page + num, "8021Q support\n");
++#else
++ num += sprintf(page + num, "no 8021Q support\n");
++#endif
++
++#ifdef STAR_GSW_SG
++ num += sprintf(page + num, "Scatter Gather on\n");
++#else
++ num += sprintf(page + num, "Scatter Gather off\n");
++#endif
++
++#ifdef FREE_TX_SKB_MULTI
++ num += sprintf(page + num, "FREE_TX_SKB_MULTI on\n");
++#else
++ num += sprintf(page + num, "FREE_TX_SKB_MULTI off\n");
++#endif
++
++#ifdef STAR_GSW_TIMER
++ num += sprintf(page + num, "STAR_GSW_TIMER on\n");
++#else
++ num += sprintf(page + num, "STAR_GSW_TIMER off\n");
++#endif
++
++ num += sprintf(page + num, "all_netdevice: %d\n", all_netdevice);
++
++ return num;
++}
++
++int star_gsw_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
++{
++
++// 20061103 descent
++#ifdef CONFIG_CONF_VID
++ char *str, *pos;
++ u16 gid, vid;
++
++ str=buffer;
++
++ if (count)
++ {
++ //simple_strtol();
++ //printk("input str: %s\n", buffer);
++
++ // skip blank
++ while (*str==' ')
++ {
++ ++str;
++ }
++ pos = strstr(str, " ");
++ if (pos)
++ {
++ *pos='\0';
++ //printk("str : %s\n", str);
++ gid=simple_strtol(str, NULL, 10);
++ //printk("gid : %d\n", gid);
++ }
++
++ str=(++pos);
++
++ // skip blank
++ while (*str==' ')
++ {
++ ++str;
++ }
++
++ //pos = strstr(str, " ");
++ //if (pos)
++ {
++ //*pos='\0';
++ //printk("str : %s\n", str);
++ vid=simple_strtol(str, NULL, 10);
++ //printk("vid : %d\n", vid);
++ }
++ star_gsw_info.vlan[gid].vlan_vid=vid;
++ switch (gid)
++ {
++ case 0:
++ {
++ GSW_SET_VLAN_0_VID(vid);
++ break;
++ }
++ case 1:
++ {
++ GSW_SET_VLAN_1_VID(vid);
++ break;
++ }
++ case 2:
++ {
++ GSW_SET_VLAN_2_VID(vid);
++ break;
++ }
++ case 3:
++ {
++ GSW_SET_VLAN_3_VID(vid);
++ break;
++ }
++ case 4:
++ {
++ GSW_SET_VLAN_4_VID(vid);
++ break;
++ }
++ case 5:
++ {
++ GSW_SET_VLAN_5_VID(vid);
++ break;
++ }
++ case 6:
++ {
++ GSW_SET_VLAN_6_VID(vid);
++ break;
++ }
++ case 7:
++ {
++ GSW_SET_VLAN_7_VID(vid);
++ break;
++ }
++ }
++
++
++
++ printk("GSW_VLAN_VID_0_1: %x\n", GSW_VLAN_VID_0_1);
++ printk("GSW_VLAN_VID_2_3: %x\n", GSW_VLAN_VID_2_3);
++ printk("GSW_VLAN_VID_4_5: %x\n", GSW_VLAN_VID_4_5);
++ printk("GSW_VLAN_VID_6_7: %x\n", GSW_VLAN_VID_6_7);
++ }
++
++#endif
++// 20061103 descent end
++
++// 20060922 descent
++#ifdef CONFIG_NIC_MODE
++ u32 sw_config = GSW_SWITCH_CONFIG;
++
++ // NIC mode on
++ if (count && buffer[0]=='1') {
++ sw_config |= (1 << 30);
++
++ star_gsw_info.vlan[0].vlan_tag_flag = 0;
++ star_gsw_info.vlan[1].vlan_tag_flag = 0;
++
++ printk("NIC mode on\n");
++ }
++
++ // NIC mode off
++ if (count && buffer[0]=='0') {
++ sw_config &= ~(1 << 30);
++
++ star_gsw_info.vlan[0].vlan_tag_flag = VLAN0_VLAN_TAG;
++ star_gsw_info.vlan[1].vlan_tag_flag = VLAN1_VLAN_TAG;
++
++ printk("NIC mode off\n");
++ }
++ GSW_SET_VLAN_0_TAG(star_gsw_info.vlan[0].vlan_tag_flag);
++ GSW_SET_VLAN_1_TAG(star_gsw_info.vlan[1].vlan_tag_flag);
++
++ GSW_SWITCH_CONFIG = sw_config;
++#endif
++// 20060922 descent end
++
++#ifdef CHANGE_DELAY_INT
++ int i=0, j=0;
++ int c=count;
++ char *str=buffer;
++ char str_num[5];
++ unsigned long n[2];
++ int index=0;
++ const char cmd_on[]="delay_int_on";
++ const char cmd_off[]="delay_int_off";
++
++ while(*str==' ') {
++ ++str;
++ --c;
++ }
++ PDEBUG("count: %d\n", count);
++ PDEBUG("c: %d\n", c);
++ if (strncmp(cmd_on, str, strlen(cmd_on))==0) {
++ PDEBUG("delay int on\n");
++ GSW_DELAYED_INTERRUPT_CONFIG |= (1 << 16) ;
++ return count;
++ }
++ if (strncmp(cmd_off, str, strlen(cmd_off))==0) {
++ PDEBUG("delay int off \n");
++ GSW_DELAYED_INTERRUPT_CONFIG &= (~(0x1 << 16));
++ return count;
++ }
++ for (i=0, j=0 ; i < c; ++i){
++ if ( ('0' <= str[i] && str[i] <= '9') || ('a' <= str[i] && str[i] <= 'f') || ('A' <= str[i] && str[i] <= 'F'))
++ str[j++]=str[i];
++ else
++ {
++ str[j++]=0;
++ n[index]=simple_strtoul(str, NULL, 16);
++ PDEBUG("n: %x\n", n[index]);
++ ++index;
++ PDEBUG("str: %s\n", str);
++ j=0;
++ }
++ }
++ //if (count && buffer[0]=='0')
++ max_pend_int_cnt=n[0];
++ max_pend_time=n[1];
++#ifdef STAR_GSW_DELAYED_INTERRUPT
++ GSW_DELAYED_INTERRUPT_CONFIG = (1 << 16) | (max_pend_int_cnt << 8) | (max_pend_time);
++#endif
++
++#endif
++
++// add by descent, 2006/07/04
++// ADJUSTMENT TX RX SKEW
++#ifdef ADJUSTMENT_TX_RX_SKEW
++ // adjust MAC port 0/1 RX/TX clock skew
++ if (count && buffer[0]=='0')
++ {
++ printk("port 1 tx skew 0 ns\n");
++ GSW_BIST_RESULT_TEST_0 &= ~(0x3 << 30);
++ GSW_BIST_RESULT_TEST_0 |= (0x0 << 30);
++
++ }
++ if (count && buffer[0]=='1')
++ {
++ printk("port 1 tx skew 1.5 ns\n");
++ GSW_BIST_RESULT_TEST_0 &= ~(0x3 << 30);
++ GSW_BIST_RESULT_TEST_0 |= (0x1 << 30);
++ }
++ if (count && buffer[0]=='2')
++ {
++ printk("port 1 tx skew 2.0 ns\n");
++ GSW_BIST_RESULT_TEST_0 &= ~(0x3 << 30);
++ GSW_BIST_RESULT_TEST_0 |= (0x2 << 30);
++ }
++ if (count && buffer[0]=='3')
++ {
++ printk("port 1 tx skew 2.5 ns\n");
++ GSW_BIST_RESULT_TEST_0 &= ~(0x3 << 30);
++ GSW_BIST_RESULT_TEST_0 |= (0x3 << 30);
++ }
++
++
++
++ if (count && buffer[0]=='4')
++ {
++ printk("port 1 rx skew 0 ns\n");
++ GSW_BIST_RESULT_TEST_0 &= ~(0x3 << 28);
++ GSW_BIST_RESULT_TEST_0 |= (0x0 << 28);
++ }
++ if (count && buffer[0]=='5')
++ {
++ printk("port 1 rx skew 1.5 ns\n");
++ GSW_BIST_RESULT_TEST_0 &= ~(0x3 << 28);
++ GSW_BIST_RESULT_TEST_0 |= (0x1 << 28);
++ }
++ if (count && buffer[0]=='6')
++ {
++ printk("port 1 rx skew 2.0 ns\n");
++ GSW_BIST_RESULT_TEST_0 &= ~(0x3 << 28);
++ GSW_BIST_RESULT_TEST_0 |= (0x2 << 28);
++ }
++ if (count && buffer[0]=='7')
++ {
++ printk("port 1 rx skew 2.5 ns\n");
++ GSW_BIST_RESULT_TEST_0 &= ~(0x3 << 28);
++ GSW_BIST_RESULT_TEST_0 |= (0x3 << 28);
++ }
++
++
++ if (count && buffer[0]=='8')
++ {
++ printk("port 0 tx skew 0 ns\n");
++ GSW_BIST_RESULT_TEST_0 &= ~(0x3 << 26);
++ GSW_BIST_RESULT_TEST_0 |= (0x0 << 26);
++ }
++ if (count && buffer[0]=='9')
++ {
++ printk("port 0 tx skew 1.5 ns\n");
++ GSW_BIST_RESULT_TEST_0 &= ~(0x3 << 26);
++ GSW_BIST_RESULT_TEST_0 |= (0x1 << 26);
++ }
++ if (count && buffer[0]=='a')
++ {
++ printk("port 0 tx skew 2.0 ns\n");
++ GSW_BIST_RESULT_TEST_0 &= ~(0x3 << 26);
++ GSW_BIST_RESULT_TEST_0 |= (0x2 << 26);
++ }
++ if (count && buffer[0]=='b')
++ {
++ printk("port 0 tx skew 2.5 ns\n");
++ GSW_BIST_RESULT_TEST_0 &= ~(0x3 << 26);
++ GSW_BIST_RESULT_TEST_0 |= (0x3 << 26);
++ }
++
++
++ if (count && buffer[0]=='c')
++ {
++ printk("port 0 rx skew 0 ns\n");
++ GSW_BIST_RESULT_TEST_0 &= ~(0x3 << 24);
++ GSW_BIST_RESULT_TEST_0 |= (0x0 << 24);
++ }
++ if (count && buffer[0]=='d')
++ {
++ printk("port 0 rx skew 1.5 ns\n");
++ GSW_BIST_RESULT_TEST_0 &= ~(0x3 << 24);
++ GSW_BIST_RESULT_TEST_0 |= (0x1 << 24);
++ }
++ if (count && buffer[0]=='e')
++ {
++ printk("port 0 rx skew 2.0 ns\n");
++ GSW_BIST_RESULT_TEST_0 &= ~(0x3 << 24);
++ GSW_BIST_RESULT_TEST_0 |= (0x2 << 24);
++ }
++ if (count && buffer[0]=='f')
++ {
++ printk("port 0 rx skew 2.5 ns\n");
++ GSW_BIST_RESULT_TEST_0 &= ~(0x3 << 24);
++ GSW_BIST_RESULT_TEST_0 |= (0x3 << 24);
++ }
++
++ printk("GSW_BIST_RESULT_TEST_0: %x\n", GSW_BIST_RESULT_TEST_0);
++#endif
++
++#ifdef STR9100_GSW_FAST_AGE_OUT_
++ {
++ // 00:02:A5:BE:59:AA
++ u8 src_mac[6] = {0x00, 0x02, 0xa5, 0xbe, 0x59, 0xaa};
++ int vlan_gid=1; // lan
++
++ printk("src mac = %x:%x:%x:%x:%x:%x\n", *src_mac,*(src_mac+1), *(src_mac+2), *(src_mac+3), *(src_mac+4), *(src_mac+5));
++ printk("vlan_gid : %d\n", vlan_gid);
++ if (star_gsw_search_arl_table(src_mac, vlan_gid))
++ {
++ printk("find it\n");
++ }
++ else
++ {
++ printk("not found\n");
++ }
++
++ }
++
++ {
++ // 00:02:A5:BE:59:AA
++ u8 src_mac[6] = {0x00, 0x02, 0xa5, 0xbe, 0x59, 0x99};
++ int vlan_gid=1; // lan
++
++ printk("src mac = %x:%x:%x:%x:%x:%x\n", *src_mac,*(src_mac+1), *(src_mac+2), *(src_mac+3), *(src_mac+4), *(src_mac+5));
++ printk("vlan_gid : %d\n", vlan_gid);
++ if (star_gsw_search_arl_table(src_mac, vlan_gid))
++ {
++ printk("find it\n");
++ }
++ else
++ {
++ printk("not found\n");
++ }
++ }
++#endif
++ return count;
++}
++
++
++static void star_gsw_enable(struct net_device *dev)
++{
++ GSW_FS_DMA_START();
++ star_gsw_interrupt_enable();
++}
++
++
++static void star_gsw_shutdown(struct net_device *dev)
++{
++}
++
++inline int star_gsw_search_arl_table(u8 *mac, u32 vlan_gid)
++{
++ volatile u32 lookup_result;
++
++ GSW_ARL_TABLE_ACCESS_CONTROL_0 = 0x0;
++ GSW_ARL_TABLE_ACCESS_CONTROL_1 = 0x0;
++ GSW_ARL_TABLE_ACCESS_CONTROL_2 = 0x0;
++
++ GSW_ARL_TABLE_ACCESS_CONTROL_2 =
++ (((mac[2] & 0xFF) << 0) |
++ ((mac[3] & 0xFF) << 8) |
++ ((mac[4] & 0xFF) << 16) |
++ ((mac[5] & 0xFF) << 24));
++
++ GSW_ARL_TABLE_ACCESS_CONTROL_1 =
++ ((vlan_gid << 5) |
++ ((mac[0] & 0xFF) << 16) |
++ ((mac[1] & 0xFF) << 24) );
++
++ GSW_ARL_TABLE_ACCESS_CONTROL_0 = (0x1 << 2);
++
++ do {
++ lookup_result = GSW_ARL_TABLE_ACCESS_CONTROL_1;
++ // still search, bit2 and bit0
++ } while ((lookup_result & 0x5) == 0);
++
++ if (lookup_result & (0x1 << 2)) {
++ return 1;
++ } else {
++ return 0; // not found
++ }
++}
++
++// add by descent 2006/07/03
++// del arl entry
++int star_gsw_del_arl_table(u8 *mac, u32 vlan_gid)
++{
++ volatile u32 age_field=0; // invalid mean erase this entry
++ volatile u32 port_map=star_gsw_info.vlan[0].vlan_group; // invalid mean erase this entry
++ volatile u32 result;
++
++ GSW_ARL_TABLE_ACCESS_CONTROL_1 = 0x0;
++ GSW_ARL_TABLE_ACCESS_CONTROL_2 = 0x0;
++
++ GSW_ARL_TABLE_ACCESS_CONTROL_1 = ( ((vlan_gid & 0x7) << 5) |
++ ((age_field & 0x7) << 8 ) |
++ ((port_map & 0x7) << 11 ) |
++ ((mac[0] & 0xFF) << 16) |
++ ((mac[1] & 0xFF) << 24) );
++
++ GSW_ARL_TABLE_ACCESS_CONTROL_2 = ( ((mac[2] & 0xFF) << 0) |
++ ((mac[3] & 0xFF) << 8) |
++ ((mac[4] & 0xFF) << 16) |
++ ((mac[5] & 0xFF) << 24));
++
++
++ GSW_ARL_TABLE_ACCESS_CONTROL_0 = 0x8; // write command
++ do
++ {
++ result=GSW_ARL_TABLE_ACCESS_CONTROL_1;
++ }while((result & 0x1)==0);
++
++ return 0;
++}
++
++void star_gsw_hnat_write_vlan_src_mac(u8 index, u8 *vlan_src_mac)
++{
++ switch (index) {
++ case 0:
++ GSW_HNAT_SOURCE_MAC_0_HIGH = (vlan_src_mac[0] << 8) |
++ (vlan_src_mac[1] << 0);
++
++ GSW_HNAT_SOURCE_MAC_0_LOW = (vlan_src_mac[2] << 24) |
++ (vlan_src_mac[3] << 16) |
++ (vlan_src_mac[4] << 8) |
++ (vlan_src_mac[5] << 0);
++ break;
++
++ case 1:
++ GSW_HNAT_SOURCE_MAC_1_HIGH = (vlan_src_mac[0] << 8) |
++ (vlan_src_mac[1] << 0);
++
++ GSW_HNAT_SOURCE_MAC_1_LOW = (vlan_src_mac[2] << 24) |
++ (vlan_src_mac[3] << 16) |
++ (vlan_src_mac[4] << 8) |
++ (vlan_src_mac[5] << 0);
++ break;
++
++ case 2:
++ GSW_HNAT_SOURCE_MAC_2_HIGH = (vlan_src_mac[0] << 8) |
++ (vlan_src_mac[1] << 0);
++
++ GSW_HNAT_SOURCE_MAC_2_LOW = (vlan_src_mac[2] << 24) |
++ (vlan_src_mac[3] << 16) |
++ (vlan_src_mac[4] << 8) |
++ (vlan_src_mac[5] << 0);
++ break;
++
++ case 3:
++ GSW_HNAT_SOURCE_MAC_3_HIGH = (vlan_src_mac[0] << 8) |
++ (vlan_src_mac[1] << 0);
++
++ GSW_HNAT_SOURCE_MAC_3_LOW = (vlan_src_mac[2] << 24) |
++ (vlan_src_mac[3] << 16) |
++ (vlan_src_mac[4] << 8) |
++ (vlan_src_mac[5] << 0);
++ break;
++
++ case 4:
++ GSW_HNAT_SOURCE_MAC_4_HIGH = (vlan_src_mac[0] << 8) |
++ (vlan_src_mac[1] << 0);
++
++ GSW_HNAT_SOURCE_MAC_4_LOW = (vlan_src_mac[2] << 24) |
++ (vlan_src_mac[3] << 16) |
++ (vlan_src_mac[4] << 8) |
++ (vlan_src_mac[5] << 0);
++ break;
++
++ case 5:
++ GSW_HNAT_SOURCE_MAC_5_HIGH = (vlan_src_mac[0] << 8) |
++ (vlan_src_mac[1] << 0);
++
++ GSW_HNAT_SOURCE_MAC_5_LOW = (vlan_src_mac[2] << 24) |
++ (vlan_src_mac[3] << 16) |
++ (vlan_src_mac[4] << 8) |
++ (vlan_src_mac[5] << 0);
++ break;
++
++ case 6:
++ GSW_HNAT_SOURCE_MAC_6_HIGH = (vlan_src_mac[0] << 8) |
++ (vlan_src_mac[1] << 0);
++
++ GSW_HNAT_SOURCE_MAC_6_LOW = (vlan_src_mac[2] << 24) |
++ (vlan_src_mac[3] << 16) |
++ (vlan_src_mac[4] << 8) |
++ (vlan_src_mac[5] << 0);
++ break;
++
++ case 7:
++ GSW_HNAT_SOURCE_MAC_7_HIGH = (vlan_src_mac[0] << 8) |
++ (vlan_src_mac[1] << 0);
++
++ GSW_HNAT_SOURCE_MAC_7_LOW = (vlan_src_mac[2] << 24) |
++ (vlan_src_mac[3] << 16) |
++ (vlan_src_mac[4] << 8) |
++ (vlan_src_mac[5] << 0);
++ break;
++
++ default:
++ break;
++ }
++}
++
++static int star_gsw_hnat_setup_vlan_src_mac(void)
++{
++ star_gsw_hnat_write_vlan_src_mac(0, star_gsw_info.vlan[0].vlan_mac);
++ star_gsw_hnat_write_vlan_src_mac(1, star_gsw_info.vlan[1].vlan_mac);
++ star_gsw_hnat_write_vlan_src_mac(2, star_gsw_info.vlan[2].vlan_mac);
++ star_gsw_hnat_write_vlan_src_mac(3, star_gsw_info.vlan[3].vlan_mac);
++
++ return 0;
++}
++
++static void star_gsw_vlan_init(void)
++{
++ star_gsw_info.vlan[0].vlan_gid = VLAN0_GROUP_ID;
++ star_gsw_info.vlan[0].vlan_vid = VLAN0_VID;
++ star_gsw_info.vlan[0].vlan_group = VLAN0_GROUP;
++ star_gsw_info.vlan[0].vlan_tag_flag = VLAN0_VLAN_TAG;
++
++ // store My VLAN0 MAC
++ memcpy(star_gsw_info.vlan[0].vlan_mac, my_vlan0_mac, 6);
++
++ star_gsw_info.vlan[1].vlan_gid = VLAN1_GROUP_ID;
++ star_gsw_info.vlan[1].vlan_vid = VLAN1_VID;
++ star_gsw_info.vlan[1].vlan_group = VLAN1_GROUP;
++ star_gsw_info.vlan[1].vlan_tag_flag = VLAN1_VLAN_TAG;
++
++ // store My VLAN1 MAC
++ memcpy(star_gsw_info.vlan[1].vlan_mac, my_vlan1_mac, 6);
++
++ star_gsw_info.vlan[2].vlan_gid = VLAN2_GROUP_ID;
++ star_gsw_info.vlan[2].vlan_vid = VLAN2_VID;
++ star_gsw_info.vlan[2].vlan_group = VLAN2_GROUP;
++ star_gsw_info.vlan[2].vlan_tag_flag = VLAN2_VLAN_TAG;
++
++ // store My VLAN2 MAC
++ memcpy(star_gsw_info.vlan[2].vlan_mac, my_vlan2_mac, 6);
++
++ star_gsw_info.vlan[3].vlan_gid = VLAN3_GROUP_ID;
++ star_gsw_info.vlan[3].vlan_vid = VLAN3_VID;
++ star_gsw_info.vlan[3].vlan_group = VLAN3_GROUP;
++ star_gsw_info.vlan[3].vlan_tag_flag = VLAN3_VLAN_TAG;
++
++ // store My VLAN3 MAC
++ memcpy(star_gsw_info.vlan[3].vlan_mac, my_vlan3_mac, 6);
++
++ star_gsw_info.vlan[4].vlan_gid = VLAN4_GROUP_ID;
++ star_gsw_info.vlan[4].vlan_vid = VLAN4_VID;
++ star_gsw_info.vlan[4].vlan_group = VLAN4_GROUP;
++ star_gsw_info.vlan[4].vlan_tag_flag = VLAN4_VLAN_TAG;
++
++ star_gsw_info.vlan[5].vlan_gid = VLAN5_GROUP_ID;
++ star_gsw_info.vlan[5].vlan_vid = VLAN5_VID;
++ star_gsw_info.vlan[5].vlan_group = VLAN5_GROUP;
++ star_gsw_info.vlan[5].vlan_tag_flag = VLAN5_VLAN_TAG;
++
++ star_gsw_info.vlan[6].vlan_gid = VLAN6_GROUP_ID;
++ star_gsw_info.vlan[6].vlan_vid = VLAN6_VID;
++ star_gsw_info.vlan[6].vlan_group = VLAN6_GROUP;
++ star_gsw_info.vlan[6].vlan_tag_flag = VLAN6_VLAN_TAG;
++
++ star_gsw_info.vlan[7].vlan_gid = VLAN7_GROUP_ID;
++ star_gsw_info.vlan[7].vlan_vid = VLAN7_VID;
++ star_gsw_info.vlan[7].vlan_group = VLAN7_GROUP;
++ star_gsw_info.vlan[7].vlan_tag_flag = VLAN7_VLAN_TAG;
++
++ star_gsw_info.port[0].pvid = PORT0_PVID;
++ star_gsw_info.port[0].config_flag = 0;
++ star_gsw_info.port[0].status_flag = 0;
++
++ star_gsw_info.port[1].pvid = PORT1_PVID;
++ star_gsw_info.port[1].config_flag = 0;
++ star_gsw_info.port[1].status_flag = 0;
++
++ star_gsw_info.port[2].pvid = CPU_PORT_PVID;
++ star_gsw_info.port[2].config_flag = 0;
++ star_gsw_info.port[2].status_flag = 0;
++}
++
++irqreturn_t star_gsw_receive_isr(int irq, void *dev_id, struct pt_regs *regs)
++{
++ struct star_gsw_private *priv = netdev_priv(STAR_NAPI_DEV);
++
++
++#ifdef CONFIG_STAR_GSW_NAPI
++ INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GSW_FSRC_BIT_INDEX);
++ disable_irq(INTC_GSW_FSRC_BIT_INDEX);
++
++
++ if (likely(netif_rx_schedule_prep(STAR_NAPI_DEV,&priv->napi))) {
++ __netif_rx_schedule(STAR_NAPI_DEV,&priv->napi);
++ } else {
++ enable_irq(INTC_GSW_FSRC_BIT_INDEX);
++ }
++
++#if 0
++ CUR_NAPI_DEV=STAR_GSW_WAN_DEV;
++
++ if (CUR_NAPI_DEV && netif_running(CUR_NAPI_DEV)) {
++ if (likely(netif_rx_schedule_prep(CUR_NAPI_DEV))) {
++ __netif_rx_schedule(CUR_NAPI_DEV);
++ } else {
++ PDEBUG("lan driver bug! interrupt while in poll\n");
++ }
++ }
++ else
++ {
++ CUR_NAPI_DEV=STAR_GSW_LAN_DEV;
++ if (CUR_NAPI_DEV && netif_running(CUR_NAPI_DEV)) {
++ if (likely(netif_rx_schedule_prep(CUR_NAPI_DEV))) {
++ __netif_rx_schedule(CUR_NAPI_DEV);
++ } else {
++ PDEBUG("lan driver bug! interrupt while in poll\n");
++ }
++ }
++ else
++ {
++ CUR_NAPI_DEV=STAR_GSW_EWC_DEV;
++ if (CUR_NAPI_DEV && netif_running(CUR_NAPI_DEV)) {
++ if (likely(netif_rx_schedule_prep(CUR_NAPI_DEV))) {
++ __netif_rx_schedule(CUR_NAPI_DEV);
++ } else {
++ PDEBUG("lan driver bug! interrupt while in poll\n");
++ }
++ }
++
++ }
++ }
++#endif
++#else
++ // TODO: mask interrupt
++ INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GSW_FSRC_BIT_INDEX);
++ // MASK Interrupt
++ INTC_INTERRUPT_MASK |= (0x1 << INTC_GSW_FSRC_BIT_INDEX);
++ INTC_INTERRUPT_MASK |= (0x1 << INTC_GSW_FSQF_BIT_INDEX);
++ ++fsrc_count;
++ star_gsw_receive_packet(0); // Receive Once
++ // TODO: unmask interrupt
++ INTC_INTERRUPT_MASK &= ~(0x1 << INTC_GSW_FSRC_BIT_INDEX);
++ INTC_INTERRUPT_MASK &= ~(0x1 << INTC_GSW_FSQF_BIT_INDEX);
++#endif
++
++ return IRQ_HANDLED;
++}
++
++
++#ifdef STAR_GSW_FSQF_ISR
++IRQ_RETURN star_gsw_fsqf_isr(int irq, void *dev_id, struct pt_regs *regs)
++{
++ INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GSW_FSQF_BIT_INDEX);
++#ifdef CONFIG_STAR_GSW_NAPI
++ // because in normal state, fsql only invoke once and set_bit is atomic function.
++ // so I don't mask it.
++ set_bit(0, &is_qf);
++#else
++ INTC_INTERRUPT_MASK |= (0x1 << INTC_GSW_FSRC_BIT_INDEX);
++ INTC_INTERRUPT_MASK |= (0x1 << INTC_GSW_FSQF_BIT_INDEX);
++
++ star_gsw_receive_packet(1); // Receive at Queue Full Mode
++
++ // TODO: unmask interrupt
++ INTC_INTERRUPT_MASK &= ~(0x1 << INTC_GSW_FSRC_BIT_INDEX);
++ INTC_INTERRUPT_MASK &= ~(0x1 << INTC_GSW_FSQF_BIT_INDEX);
++ //INTC_INTERRUPT_MASK &= (0x0 << INTC_GSW_FSRC_BIT_INDEX);
++ //INTC_INTERRUPT_MASK &= (0x0 << INTC_GSW_FSQF_BIT_INDEX);
++#endif
++
++ return IRQ_HANDLED;
++}
++#endif
++
++#ifdef STAR_GSW_STATUS_ISR
++static char *star_gsw_status_tbl[] = {
++ "\nGlobal threshold reached and Port 0 queue threshold reached.\n",
++ "\nGlobal threshold reached and Port 1 queue threshold reached.\n",
++ "\nGlobal threshold reached and CPU port queue threshold reached.\n",
++ "\nGlobal threshold reached and HNAT queue threshold reached.\n",
++ "\nGlobal threshold reached.\n",
++ "\nAll pages of packet buffer are used.\n",
++ "\nPort change link state.\n",
++ "\nPort 0 received intruder packets.\n",
++ "\nPort 1 received intruder packets.\n",
++ "\n",
++ "\nPort 0 received packets with unknown VLAN.\n",
++ "\nPort 1 received packets with unknown VLAN.\n",
++ "\nPort CPU received packets with unknown VLAN.\n",
++ "\n",
++ "\n",
++ "\n",
++ "\nDrop by no free links(Port 0).\n",
++ "\nDrop by broadcast storm(Port 0).\n",
++ "\nDrop by rx packet error(Port 0).\n",
++ "\nDrop by backpressure(Port 0).\n",
++ "\nDrop by no destination(Port 0).\n",
++ "\nDrop by reserved MC packets(Port 0).\n",
++ "\nDrop by local traffic(Port 0).\n",
++ "\nDrop by ingress check(Port 0).\n",
++ "\nDrop by no free links(Port 1).\n",
++ "\nDrop by broadcast storm(Port 1).\n",
++ "\nDrop by rx packet error(Port 1).\n",
++ "\nDrop by backpressure(Port 1).\n",
++ "\nDrop by no destination(Port 1).\n",
++ "\nDrop by reserved MC packets(Port 1).\n",
++ "\nDrop by local traffic(Port 1).\n",
++ "\nDrop by ingress checki(Port 1).\n",
++};
++
++IRQ_RETURN star_gsw_status_isr(int irq, void *dev_id, struct pt_regs *regs)
++{
++ u32 int_status;
++ u32 i;
++
++ INTC_DISABLE_INTERRUPT_SOURCE(INTC_GSW_STATUS_BIT_INDEX);
++
++ GSW_READ_INTERRUPT_STATUS(int_status);
++
++ PDEBUG("\n status:%08X \n",int_status);
++ PDEBUG("\n GSW_MAC_PORT_0_CONFIG:%08X\n",GSW_MAC_PORT_0_CONFIG);
++ PDEBUG("\n GSW_MAC_PORT_1_CONFIG:%08X\n",GSW_MAC_PORT_1_CONFIG);
++
++ for (i = 0; i < 32; i++) {
++ if (int_status & (1 << i)) {
++ PRINT_INFO(star_gsw_status_tbl[i]);
++ }
++ }
++
++ GSW_CLEAR_INTERRUPT_STATUS_SOURCES(int_status);
++
++ INTC_ENABLE_INTERRUPT_SOURCE(INTC_GSW_STATUS_BIT_INDEX);
++
++ return IRQ_HANDLED;
++
++}
++#endif // STAR_GSW_STATUS_ISR
++
++static int star_gsw_uninstall_isr(struct net_device *dev)
++{
++ --install_isr_account;
++ if (install_isr_account == 0) {
++ PDEBUG("star gsw uninstall isr\n");
++ free_irq(INTC_GSW_FSRC_BIT_INDEX, STAR_GSW_LAN_DEV);
++
++#ifdef STAR_GSW_FSQF_ISR
++ free_irq(INTC_GSW_FSQF_BIT_INDEX, STAR_GSW_LAN_DEV);
++#endif
++
++#ifdef STAR_GSW_STATUS_ISR
++ free_irq(INTC_GSW_STATUS_BIT_INDEX, STAR_GSW_LAN_DEV);
++#endif
++
++
++#ifdef CONFIG_STAR_GSW_NAPI
++{
++ struct star_gsw_private *sp = netdev_priv(STAR_NAPI_DEV);
++
++ napi_disable(&sp->napi);
++ netif_stop_queue(STAR_NAPI_DEV);
++}
++#endif
++
++ }
++
++ return 0;
++}
++
++static int star_gsw_install_isr(struct net_device *dev)
++{
++ int retval;
++
++
++ if (install_isr_account == 0) {
++#ifdef STAR_GSW_DELAYED_INTERRUPT
++ GSW_DELAYED_INTERRUPT_CONFIG = (1 << 16) | (max_pend_int_cnt << 8) | (max_pend_time);
++#endif
++#ifdef STAR_GSW_STATUS_ISR
++ str9100_set_interrupt_trigger(INTC_GSW_STATUS_BIT_INDEX, INTC_LEVEL_TRIGGER, INTC_ACTIVE_HIGH);
++#endif
++ str9100_set_interrupt_trigger((u32)INTC_GSW_FSRC_BIT_INDEX, (u32)INTC_EDGE_TRIGGER, (u32)INTC_RISING_EDGE);
++#ifdef STAR_GSW_FSQF_ISR
++ str9100_set_interrupt_trigger(INTC_GSW_FSQF_BIT_INDEX, INTC_EDGE_TRIGGER, INTC_RISING_EDGE);
++#endif
++
++
++ retval = request_irq(INTC_GSW_FSRC_BIT_INDEX, &star_gsw_receive_isr, IRQF_SHARED, "GSW FSRC INT", STAR_GSW_LAN_DEV);
++
++ if (retval) {
++ PRINT_INFO("%s: unable to get IRQ %d (irqval=%d).\n", "GSW FSRC INT", INTC_GSW_FSRC_BIT_INDEX, retval);
++ return 1;
++ }
++
++#ifdef STAR_GSW_FSQF_ISR
++ /* QUEUE full interrupt handler */
++ retval = request_irq(INTC_GSW_FSQF_BIT_INDEX, &star_gsw_fsqf_isr, IRQF_SHARED, "GSW FSQF INT", STAR_GSW_LAN_DEV);
++
++ if (retval) {
++ PRINT_INFO("%s: unable to get IRQ %d (irqval=%d).\n", "GSW FSQF INT", INTC_GSW_FSQF_BIT_INDEX, retval);
++ return 2;
++ }
++#endif
++
++#ifdef STAR_GSW_STATUS_ISR
++ /* GSW Status interrupt handler */
++ retval = request_irq(INTC_GSW_STATUS_BIT_INDEX, &star_gsw_status_isr, IRQF_SHARED, "GSW STATUS", STAR_GSW_LAN_DEV);
++
++ if (retval) {
++ PRINT_INFO("%s: unable to get IRQ %d (irqval=%d).\n", "GSW STATUS INT", INTC_GSW_STATUS_BIT_INDEX, retval);
++ return 3;
++ }
++ GSW_ENABLE_ALL_INTERRUPT_STATUS_SOURCES();
++#endif
++
++#ifdef CONFIG_STAR_GSW_NAPI
++{
++ struct star_gsw_private *sp = netdev_priv(STAR_NAPI_DEV);
++ napi_enable(&sp->napi);
++ netif_start_queue(STAR_NAPI_DEV);
++}
++#endif
++ } // end if(install_isr_account == 0)
++
++ ++install_isr_account;
++
++ return 0;
++}
++
++// add by descent 2006/07/12
++void enable_cpu_port(int y)
++{
++ u32 cpu_port_config;
++ cpu_port_config = GSW_CPU_PORT_CONFIG;
++ if (y==1) // enable CPU
++ cpu_port_config &= ~(0x1 << 18);
++ if (y==0) // disable CPU
++ cpu_port_config |= (0x1 << 18);
++ GSW_CPU_PORT_CONFIG = cpu_port_config;
++}
++
++static int star_gsw_open(struct net_device *dev)
++{
++
++
++ OPEN_PORT(dev)
++ enable_cpu_port(1);
++ //memcpy(dev->dev_addr, star_gsw_info.vlan[1].vlan_mac, 6);
++
++ star_gsw_hnat_setup_vlan_src_mac();
++
++#if 0
++#ifdef MODULE
++ MOD_INC_USE_COUNT;
++#endif
++#endif
++
++
++
++ //CUR_NAPI_DEV = dev;
++
++ star_gsw_enable(dev);
++
++ netif_start_queue(dev);
++
++ GSW_ENABLE_ALL_INTERRUPT_STATUS_SOURCES();
++
++ star_gsw_install_isr(dev);
++
++ return 0;
++}
++
++
++
++static struct net_device_stats *star_gsw_get_stats(struct net_device *dev)
++{
++ struct star_gsw_private *priv = netdev_priv(dev);
++
++ return &priv->stats;
++}
++
++static void star_gsw_timeout(struct net_device *dev)
++{
++ PRINT_INFO("%s:star_gsw_timeout\n", dev->name);
++ star_gsw_enable(dev);
++ netif_wake_queue(dev);
++ dev->trans_start = jiffies;
++}
++
++
++
++static int star_gsw_close(struct net_device *dev)
++{
++ star_gsw_uninstall_isr(dev);
++ //star_gsw_shutdown(dev);
++
++ //CLOSE_PORT0
++ //CLOSE_PORT1
++ CLOSE_PORT(dev)
++
++#if 0
++#ifdef MODULE
++ MOD_DEC_USE_COUNT;
++#endif
++#endif
++
++#if 0
++ if (dev == STAR_GSW_WAN_DEV) {
++ CUR_NAPI_DEV = STAR_GSW_LAN_DEV;
++ } else if (dev == STAR_GSW_LAN_DEV) {
++ CUR_NAPI_DEV = STAR_GSW_WAN_DEV;
++ } else if (dev == STAR_GSW_EWC_DEV) {
++ CUR_NAPI_DEV = STAR_GSW_LAN_DEV;
++ }
++ //} // if (dev == STAR_GSW_LAN_DEV)
++#endif
++
++ //phy_power_down_ptr(1,1);
++ return 0;
++}
++
++static inline struct sk_buff *star_gsw_alloc_skb(void)
++{
++ struct sk_buff *skb;
++
++ skb = dev_alloc_skb(MAX_PACKET_LEN + 2);
++
++ if (unlikely(!skb)) {
++ PDEBUG("\n dev_alloc_skb fail!! while allocate RFD ring !!\n");
++ return NULL;
++ }
++
++
++ /* Make buffer alignment 2 beyond a 16 byte boundary
++ * this will result in a 16 byte aligned IP header after
++ * the 14 byte MAC header is removed
++ */
++
++ skb_reserve(skb, 2); /* 16 bit alignment, 4N + 2 mode */
++
++ return skb;
++}
++
++static void star_gsw_buffer_free(void)
++{
++ int i;
++
++ if (rxring.vir_addr) {
++ for (i = 0; i < STAR_GSW_MAX_RFD_NUM; i++) {
++ if (rxring.skb_ptr[i]) {
++ dev_kfree_skb(rxring.skb_ptr[i]);
++ }
++ }
++ dma_free_coherent(NULL, STAR_GSW_MAX_RFD_NUM * sizeof(STAR_GSW_RXDESC), rxring.vir_addr, rxring.phy_addr);
++ }
++
++ if (txring.vir_addr) {
++ dma_free_coherent(NULL, STAR_GSW_MAX_TFD_NUM * sizeof(STAR_GSW_TXDESC), txring.vir_addr, txring.phy_addr);
++ }
++}
++
++static int __init star_gsw_buffer_alloc(void)
++{
++ STAR_GSW_RXDESC volatile *rxdesc_ptr;
++ STAR_GSW_TXDESC volatile *txdesc_ptr;
++ struct sk_buff *skb_ptr;
++ int err;
++ int i;
++
++ rxring.vir_addr = dma_alloc_coherent(NULL, STAR_GSW_MAX_RFD_NUM * sizeof(STAR_GSW_RXDESC), &rxring.phy_addr, GFP_KERNEL);
++ if (!rxring.vir_addr) {
++ PDEBUG("\n ERROR: Allocate RFD Failed\n");
++ err = -ENOMEM;
++ goto err_out;
++ }
++
++ txring.vir_addr = dma_alloc_coherent(NULL, STAR_GSW_MAX_TFD_NUM * sizeof(STAR_GSW_TXDESC), &txring.phy_addr, GFP_KERNEL);
++ if (!txring.vir_addr) {
++ PDEBUG("\n ERROR: Allocate TFD Failed\n");
++ err = -ENOMEM;
++ goto err_out;
++ }
++
++ // Clean RX Memory
++ memset((void *)rxring.vir_addr, 0, STAR_GSW_MAX_RFD_NUM * sizeof(STAR_GSW_RXDESC));
++ PDEBUG(" rxring.vir_addr=0x%08X rxring.phy_addr=0x%08X\n", (u32)rxring.vir_addr, (u32)rxring.phy_addr);
++ rxring.cur_index = 0; // Set cur_index Point to Zero
++ rxdesc_ptr = rxring.vir_addr;
++ for (i = 0; i < STAR_GSW_MAX_RFD_NUM; i++, rxdesc_ptr++) {
++ if (i == (STAR_GSW_MAX_RFD_NUM - 1)) {
++ rxdesc_ptr->eor = 1; // End bit == 0;
++ }
++ skb_ptr = star_gsw_alloc_skb();
++ if (!skb_ptr) {
++ PDEBUG("ERROR: Allocate skb Failed!\n");
++ err = -ENOMEM;
++ goto err_out;
++ }
++ // Trans Packet from Virtual Memory to Physical Memory
++ rxring.skb_ptr[i] = skb_ptr;
++ rxdesc_ptr->data_ptr = (u32)virt_to_phys(skb_ptr->data);
++ rxdesc_ptr->length = MAX_PACKET_LEN;
++ }
++
++ // Clean TX Memory
++ memset((void *)txring.vir_addr, 0, STAR_GSW_MAX_TFD_NUM * sizeof(STAR_GSW_TXDESC));
++ PDEBUG(" txring.vir_addr=0x%08X txring.phy_addr=0x%08X\n", (u32)txring.vir_addr, (u32)txring.phy_addr);
++ txring.cur_index = 0; // Set cur_index Point to Zero
++ txdesc_ptr = txring.vir_addr;
++ for (i = 0; i < STAR_GSW_MAX_TFD_NUM; i++, txdesc_ptr++) {
++ if (i == (STAR_GSW_MAX_TFD_NUM - 1)) {
++ txdesc_ptr->eor = 1; // End of Ring ==1
++ }
++ txdesc_ptr->cown = 1; // TX Ring , Cown == 1
++
++#ifdef STAR_GSW_TX_HW_CHECKSUM
++ // Enable Checksum
++ txdesc_ptr->ico = 0;
++ txdesc_ptr->uco = 1;
++ txdesc_ptr->tco = 1;
++#else
++ txdesc_ptr->ico = 0;
++ txdesc_ptr->uco = 0;
++ txdesc_ptr->tco = 0;
++#endif
++ txring.skb_ptr[i] = NULL; // clear txring.skb_ptr
++ }
++
++ return 0;
++
++err_out:
++ star_gsw_buffer_free();
++ return err;
++}
++
++#ifdef CONFIG_STAR_GSW_NAPI
++
++#if 0
++static int star_gsw_poll(struct net_device *netdev, int *budget)
++{
++ int work_done = 0;
++ int work_to_do = min(*budget, netdev->quota); // where is min define
++
++ star_gsw_receive_packet(0, &work_done, work_to_do);
++
++ *budget -= work_done;
++ netdev->quota -= work_done;
++
++ if (work_done) {
++ if (is_qf) {
++ is_qf = 0;
++ HAL_GSW_FS_DMA_START();
++ return 1;
++ }
++ }
++ else {
++ netif_rx_complete(&STAR_NAPI_DEV);
++ enable_irq(INTC_GSW_FSRC_BIT_INDEX);
++ return 0;
++ }
++
++
++ return 1;
++}
++#else
++
++static int star_gsw_poll(struct napi_struct *napi, int budget)
++{
++
++ struct star_gsw_private *sp = container_of(napi, struct star_gsw_private, napi);
++ int work_done = 0;
++ int work_to_do = budget; // where is min define
++
++ star_gsw_receive_packet(0, &work_done, work_to_do);
++
++ budget -= work_done;
++
++ if (work_done) {
++ if (test_bit(0, (unsigned long *)&is_qf) == 1){
++ clear_bit(0, (unsigned long *)&is_qf);
++ HAL_GSW_FS_DMA_START();
++ return 1;
++ }
++ }
++ else {
++ netif_rx_complete(STAR_NAPI_DEV, &sp->napi);
++ enable_irq(INTC_GSW_FSRC_BIT_INDEX);
++ return 0;
++ }
++
++
++ return 1;
++}
++#endif
++
++
++#ifdef LINUX26_
++#ifdef CONFIG_CPU_ISPAD_ENABLE
++__attribute__((section(".ispad")))
++#endif
++
++static int star_gsw_poll(struct napi_struct *napi, int budget)
++{
++
++ struct star_gsw_private *sp = container_of(napi, struct star_gsw_private, napi);
++ int work_done = 0;
++ int work_to_do = budget; // where is min define
++
++ star_gsw_receive_packet(0, &work_done, work_to_do);
++
++ budget -= work_done;
++
++ if (work_done) {
++ if (test_bit(0, (unsigned long *)&is_qf) == 1){
++ clear_bit(0, (unsigned long *)&is_qf);
++ HAL_GSW_FS_DMA_START();
++ return 1;
++ }
++ }
++ else {
++ netif_rx_complete(STAR_NAPI_DEV, &sp->napi);
++ enable_irq(INTC_GSW_FSRC_BIT_INDEX);
++ return 0;
++ }
++
++
++ return 1;
++}
++#endif // LINUX26
++
++
++
++
++
++#endif // CONFIG_STAR_GSW_NAPI
++
++static int star_gsw_get_rfd_buff(int index)
++{
++ struct star_gsw_private *priv;
++ STAR_GSW_RXDESC volatile *rxdesc_ptr;
++ struct sk_buff *skb_ptr;
++ unsigned char *data;
++ int len;
++#ifdef CONFIG_STR9100_VLAN_BASE
++ u32 vlan_gid = 0;
++ u8 *src_mac;
++#endif
++
++ rxdesc_ptr = rxring.vir_addr + index;
++ skb_ptr = rxring.skb_ptr[index];
++ len = rxdesc_ptr->length;
++
++ dma_cache_maint(skb_ptr->data, len, PCI_DMA_FROMDEVICE);
++
++#ifdef CONFIG_STR9100_PORT_BASE
++ if (rxdesc_ptr->sp == 0) {
++ /*
++ * Note this packet is from GSW Port 0, and the device index of GSW Port 0 is 1
++ * Note the device index = 0 is for internal loopback device
++ */
++ //skb_ptr->dev = STAR_GSW_LAN_DEV;
++ skb_ptr->dev = NET_DEV0;
++ if (skb_ptr->dev)
++ goto determine_dev_ok;
++ } else {
++ // Note this packet is from GSW Port 1, and the device index of GSW Port 1 is 2
++ //skb_ptr->dev = STAR_GSW_WAN_DEV;
++ skb_ptr->dev = NET_DEV1;
++ if (skb_ptr->dev)
++ goto determine_dev_ok;
++ }
++
++#endif /* CONFIG_STR9100_PORT_BASE */
++
++#ifdef CONFIG_STAR9100_SHNAT_PCI_FASTPATH
++ if (rxdesc_ptr->hr == 0x27 && star9100_shnat_hook_ready) {
++ if(star9100_shnat_pci_fp_getdev_hook(skb_ptr)){
++ skb_put(skb_ptr, len);
++
++#if CONFIG_HAVE_VLAN_TAG
++ #define PPPOE_ID_1_LOC 16
++ #define PPPOE_ID_2_LOC 17
++#else
++ #define PPPOE_ID_1_LOC 12
++ #define PPPOE_ID_2_LOC 13
++#endif
++
++ if (skb_ptr->data[PPPOE_ID_1_LOC] == 0x88 && skb_ptr->data[PPPOE_ID_2_LOC]==0x64) { // pppoe session
++ /* Remove PPPoE Header */
++ memmove(skb_ptr->data+8, skb_ptr->data, 12);
++ skb_ptr->data+=8;
++ skb_ptr->len-=8;
++ skb_ptr->data[PPPOE_ID_1_LOC]=0x08;
++ skb_ptr->data[PPPOE_ID_2_LOC]=0x0;
++ } else {
++ /* Remove VLAN Tag */
++#ifdef CONFIG_HAVE_VLAN_TAG
++ memmove(skb_ptr->data + 4, skb_ptr->data, 12);
++ skb_ptr->len-=4;
++ skb_ptr->data+=4;
++#endif
++ }
++ skb_ptr->dev->hard_start_xmit(skb_ptr, skb_ptr->dev);
++ return 0;
++ }
++ }
++#endif /* CONFIG_STAR9100_SHNAT_PCI_FASTPATH */
++
++RECV_PACKET:
++
++#ifdef CONFIG_STR9100_VLAN_BASE
++
++#ifdef CONFIG_HAVE_VLAN_TAG
++
++
++// 20060922 descent
++ { // NIC MODE off
++
++ const char lan_tag[]={0x81, 0x00, 0x00, 0x01};
++ const char wan_tag[]={0x81, 0x00, 0x00, 0x02};
++
++
++
++ if (memcmp(skb_ptr->data+12, lan_tag,4)==0) {
++ //printk("lan dev\n");
++ skb_ptr->dev = STAR_GSW_LAN_DEV;
++ } else if (memcmp(skb_ptr->data+12, wan_tag,4)==0) {
++ //printk("wan dev\n");
++ skb_ptr->dev = STAR_GSW_WAN_DEV;
++ } else {
++ PDEBUG("no vlan tag\n");
++ //print_packet(skb_ptr->data, 32);
++ goto freepacket;
++
++ }
++// 20070503 descent
++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++ // let 8021Q to determine vlan tag
++#else /* defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) */
++ memmove(skb_ptr->data + 4, skb_ptr->data, 12);
++ //skb_ptr->data += 4;
++ skb_reserve(skb_ptr, 4);
++ len -= 4; // minus 4 byte vlan tag
++#endif /* defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) */
++
++#else /* CONFIG_HAVE_VLAN_TAG */
++
++// 20060922 descent
++#ifdef CONFIG_NIC_MODE
++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++// do nothing
++#else // defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++ // if NIC MODE on
++ if ( ((GSW_SWITCH_CONFIG >> 30) & 0x1) ==1){
++ const char lan_tag[]={0x81, 0x00, 0x00, 0x01};
++ const char wan_tag[]={0x81, 0x00, 0x00, 0x02};
++
++ //printk("NIC mode on\n");
++ if (memcmp(skb_ptr->data+12, lan_tag,4)==0) {
++ //printk("lan dev\n");
++ skb_ptr->dev = STAR_GSW_LAN_DEV;
++ } else if (memcmp(skb_ptr->data+12, wan_tag,4)==0) {
++ //printk("wan dev\n");
++ skb_ptr->dev = STAR_GSW_WAN_DEV;
++ } else {
++ //printk("no vlan tag\n");
++ //print_packet(skb_ptr->data, 32);
++ goto freepacket;
++
++ }
++
++ memmove(skb_ptr->data + 4, skb_ptr->data, 12);
++ skb_ptr->data += 4;
++ goto determine_dev_ok;
++
++ }
++#endif // defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++#endif
++// 20060922 descent end
++
++ src_mac = skb_ptr->data + 6; // get source mac address
++
++ // use gid and source mac to serarch arl table
++ vlan_gid = 1; // lan
++ if (star_gsw_search_arl_table(src_mac, vlan_gid)) {
++ //printk("STAR_GSW_LAN_DEV\n");
++ skb_ptr->dev = STAR_GSW_LAN_DEV;
++ #ifdef STR9100_GSW_FAST_AGE_OUT
++ star_gsw_del_arl_table(src_mac, vlan_gid);
++ #endif
++ goto determine_dev_ok;
++ } else {
++ vlan_gid = 0; // wan
++ if (star_gsw_search_arl_table(src_mac, vlan_gid)) {
++ //printk("STAR_GSW_WAN_DEV\n");
++ skb_ptr->dev = STAR_GSW_WAN_DEV;
++ #ifdef STR9100_GSW_FAST_AGE_OUT
++ star_gsw_del_arl_table(src_mac, vlan_gid);
++ #endif
++ goto determine_dev_ok;
++ } else {
++ PDEBUG("not determine come from lan or wan\n"); // should not go here
++ PDEBUG("not determine come from lan or wan\n"); // should not go here
++ goto freepacket;
++ }
++ }
++
++#endif // CONFIG_HAVE_VLAN_TAG
++
++#endif /* CONFIG_STR9100_VLAN_BASE */
++
++
++determine_dev_ok:
++ skb_put(skb_ptr, len);
++
++
++
++ if (skb_ptr->dev!=NULL) {
++ priv = netdev_priv(skb_ptr->dev);
++ }
++ else{
++ PDEBUG("skb_ptr->dev==NULL\n");
++ //goto freepacket;
++ }
++
++#ifdef STAR_GSW_RX_HW_CHECKSUM
++ if (rxdesc_ptr->ipf == 1 || rxdesc_ptr->l4f == 1) {
++ if (rxdesc_ptr->prot != 0x11) {
++ skb_ptr->ip_summed = CHECKSUM_NONE;
++ } else {
++ // CheckSum Fail
++ priv->stats.rx_errors++;
++ goto freepacket;
++ }
++ } else {
++ skb_ptr->ip_summed = CHECKSUM_UNNECESSARY;
++ }
++#else
++ skb_ptr->ip_summed = CHECKSUM_NONE;
++#endif
++
++ // this line must, if no, packet will not send to network layer
++ skb_ptr->protocol = eth_type_trans(skb_ptr, skb_ptr->dev);
++ //skb_ptr->protocol = htons(ETH_P_8021Q);
++
++#ifndef CONFIG_STAR_GSW_BRIDGE
++ // send any packet in bridge mode
++ /*
++ * This is illegality packet so drop it.
++ */
++ if (skb_ptr->protocol == htons(ETH_P_802_2)) {
++ PDEBUG("ETH_P_802_2\n");
++ goto freepacket;
++ }
++#endif
++
++ priv->stats.rx_packets++;
++ priv->stats.rx_bytes += len;
++ skb_ptr->dev->last_rx = jiffies;
++
++
++ //PRINT_PACKET(skb_ptr->data, 32, "RX")
++
++ // if netif_rx any package, will let this driver core dump.
++#ifdef CONFIG_STAR_GSW_NAPI
++ netif_receive_skb(skb_ptr);
++#else
++ netif_rx(skb_ptr);
++#endif
++
++ return 0;
++
++freepacket:
++ dev_kfree_skb_any(skb_ptr);
++ return 0;
++}
++
++#ifdef CONFIG_STAR_GSW_NAPI
++void star_gsw_receive_packet(int mode, int *work_done, int work_to_do)
++#else
++void star_gsw_receive_packet(int mode)
++#endif
++{
++ int fssd_index;
++ int fssd_current;
++ STAR_GSW_RXDESC volatile *rxdesc_ptr = rxring.vir_addr + rxring.cur_index;
++ struct sk_buff *skb_ptr;
++#ifndef CONFIG_STAR_GSW_NAPI
++ int fsqf = 0; // Queue Full Mode =0
++#endif
++ int i, rxcount = 0;
++ GSW_READ_FSSD(fssd_current);
++ fssd_index = (fssd_current - (u32)rxring.phy_addr) >> 4;
++
++ if (fssd_index > rxring.cur_index) {
++ rxcount = fssd_index - rxring.cur_index;
++ } else if (fssd_index < rxring.cur_index) {
++ rxcount = (STAR_GSW_MAX_RFD_NUM - rxring.cur_index) + fssd_index;
++ } else {
++ if (rxdesc_ptr->cown == 0) {
++ goto receive_packet_exit;
++ } else {
++ // Queue Full
++#ifndef CONFIG_STAR_GSW_NAPI
++ fsqf = 1;
++#endif
++ rxcount = STAR_GSW_MAX_RFD_NUM;
++ //set_bit(0, &is_qf);
++ }
++ }
++
++#ifndef CONFIG_STAR_GSW_NAPI
++ if (mode == 1) {
++ fsqf = 1;
++ rxcount = STAR_GSW_MAX_RFD_NUM;
++ }
++#endif
++
++ for (i = 0; i < rxcount; i++) {
++#ifdef CONFIG_STAR_GSW_NAPI
++ if (*work_done >= work_to_do)
++ break;
++ ++(*work_done);
++#endif
++ if (rxdesc_ptr->cown != 0) {
++ // Alloc New skb_buff
++ skb_ptr = star_gsw_alloc_skb();
++ // Check skb_buff
++ if (skb_ptr != NULL) {
++ star_gsw_get_rfd_buff(rxring.cur_index);
++ rxring.skb_ptr[rxring.cur_index] = skb_ptr;
++ rxdesc_ptr->data_ptr = (u32)virt_to_phys(skb_ptr->data);
++ rxdesc_ptr->length = MAX_PACKET_LEN;
++ rxdesc_ptr->cown = 0; // set cbit to 0 for CPU Transfer
++ } else {
++ // TODO:
++ // I will add dev->lp.stats->rx_dropped, it will effect the performance
++ PDEBUG("%s: Alloc sk_buff fail, reuse the buffer\n", __FUNCTION__);
++ rxdesc_ptr->cown = 0; // set cbit to 0 for CPU Transfer
++ return;
++ }
++ }
++
++ if (rxring.cur_index == (STAR_GSW_MAX_RFD_NUM - 1)) {
++ rxring.cur_index = 0;
++ rxdesc_ptr = rxring.vir_addr;
++ } else {
++ rxring.cur_index++;
++ rxdesc_ptr++;
++ }
++ }
++
++#ifndef CONFIG_STAR_GSW_NAPI
++ if (fsqf) {
++ rxring.cur_index = fssd_index;
++ mb();
++ GSW_FS_DMA_START();
++ }
++#endif
++
++receive_packet_exit:
++ return;
++}
++
++#ifdef FREE_TX_SKB_MULTI
++#define MAX_TX_SKB_FREE_NUM 16
++#endif
++
++
++static int star_gsw_send_packet(struct sk_buff *skb, struct net_device *dev)
++{
++ struct star_gsw_private *priv = netdev_priv(dev);
++ STAR_GSW_TXDESC volatile *txdesc_ptr;
++ unsigned long flags;
++ u16 vlan_tag;
++
++#ifdef FREE_TX_SKB_MULTI
++ int i;
++ int tssd_index;
++ int tssd_current;
++ int skb_free_count = 0;
++ struct sk_buff *skb_free[MAX_TX_SKB_FREE_NUM];
++#endif
++
++
++#if defined(MAX_SKB_FRAGS) && defined(STAR_GSW_SG)
++ int org_index;
++ int cur_index;
++
++ unsigned int f;
++ unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
++ unsigned int len = skb->len - skb->data_len;
++ unsigned int offset;
++
++#ifndef FREE_TX_SKB_MULTI
++ int skb_free_count = 0;
++ struct sk_buff *skb_free[MAX_SKB_FRAGS];
++#endif
++#else /* defined(MAX_SKB_FRAGS) && defined(STAR_GSW_SG) */
++#ifndef FREE_TX_SKB_MULTI
++ struct sk_buff *skb_free = NULL;
++#endif
++#endif /* defined(MAX_SKB_FRAGS) && defined(STAR_GSW_SG) */
++
++ HAL_GSW_TS_DMA_STOP();
++ spin_lock_irqsave(&star_gsw_send_lock, flags);
++
++#ifdef FREE_TX_SKB_MULTI
++ HAL_GSW_READ_TSSD(tssd_current);
++ tssd_index = (tssd_current - (u32)txring.phy_addr) >> 4;
++
++ if (tssd_index > txring.to_free_index) {
++ skb_free_count = tssd_index - txring.to_free_index;
++ } else if (tssd_index < txring.to_free_index) {
++ skb_free_count = STAR_GSW_MAX_TFD_NUM + tssd_index - txring.to_free_index;
++ }
++
++ if (skb_free_count >= MAX_TX_SKB_FREE_NUM) {
++ int count = 0;
++ for (i = 0; i < skb_free_count; i++) {
++ txdesc_ptr = txring.vir_addr + txring.to_free_index;
++ if (txdesc_ptr->cown == 0) {
++ break;
++ }
++ if (txring.skb_ptr[txring.to_free_index]) {
++ skb_free[count++] = txring.skb_ptr[txring.to_free_index];
++ txring.skb_ptr[txring.to_free_index] = NULL;
++ }
++ txring.to_free_index++;
++ if (txring.to_free_index == STAR_GSW_MAX_TFD_NUM) {
++ txring.to_free_index = 0;
++ }
++ if (count == MAX_TX_SKB_FREE_NUM) {
++ break;
++ }
++ }
++ skb_free_count = count;
++ } else {
++ skb_free_count = 0;
++ }
++#endif
++
++
++
++#if defined(MAX_SKB_FRAGS) && defined(STAR_GSW_SG)
++ org_index = txring.cur_index;
++ cur_index = txring.cur_index;
++ //printk("nr_frags: %d\n", nr_frags);
++ for (f = 0; f < (nr_frags + 1); f++) {
++ txdesc_ptr = txring.vir_addr + cur_index;
++
++ if (txdesc_ptr->cown == 0) {
++ spin_unlock_irqrestore(&star_gsw_send_lock, flags);
++ // re-queue the skb
++ return 1;
++ }
++
++#ifndef FREE_TX_SKB_MULTI
++ if (txring.skb_ptr[cur_index]) {
++ skb_free[skb_free_count++] = txring.skb_ptr[cur_index];
++#ifdef STAR_GSW_TIMER
++ txring.to_free_index = cur_index + 1;
++ if (txring.to_free_index == STAR_GSW_MAX_TFD_NUM) {
++ txring.to_free_index = 0;
++ }
++#endif
++ }
++#endif
++
++ if (f == 0) {
++ txdesc_ptr->fs = 1;
++ } else {
++ txdesc_ptr->fs = 0;
++ }
++ if (f == nr_frags) {
++ txdesc_ptr->ls = 1;
++ } else {
++ txdesc_ptr->ls = 0;
++ }
++
++#if 0
++ if (skb->protocol == __constant_htons(ETH_P_IP)) {
++ txdesc_ptr->ico = 1;
++ if (skb->nh.iph->protocol == IPPROTO_UDP) {
++ txdesc_ptr->uco = 1;
++ txdesc_ptr->tco = 0;
++ } else if (skb->nh.iph->protocol == IPPROTO_TCP) {
++ txdesc_ptr->uco = 0;
++ txdesc_ptr->tco = 1;
++ } else {
++ txdesc_ptr->uco = 0;
++ txdesc_ptr->tco = 0;
++ }
++ } else {
++ txdesc_ptr->ico = 0;
++ txdesc_ptr->uco = 0;
++ txdesc_ptr->tco = 0;
++ }
++#endif
++
++ txdesc_ptr->interrupt = 0;
++ txdesc_ptr->fr = 1;
++
++
++
++#ifdef CONFIG_STR9100_VLAN_BASE
++ if (priv->pmap==-1) {
++ txdesc_ptr->insv = 1;
++ txdesc_ptr->pmap = 1; // MAC0
++ if (dev == STAR_GSW_WAN_DEV) {
++ txdesc_ptr->vid = VLAN0_GROUP_ID;
++ } else {
++ txdesc_ptr->vid = VLAN1_GROUP_ID;
++ }
++ }
++#endif // CONFIG_STR9100_VLAN_BASE
++
++#ifdef CONFIG_STR9100_PORT_BASE
++ if (priv->pmap != -1) {
++ txdesc_ptr->insv = 0;
++ txdesc_ptr->pmap = priv->pmap;
++ }
++#endif
++
++ cur_index++;
++ if (cur_index == STAR_GSW_MAX_TFD_NUM) {
++ cur_index = 0;
++ }
++ } // end for (f = 0; f < (nr_frags + 1); f++)
++
++ txdesc_ptr = (txring.vir_addr + txring.cur_index);
++ txdesc_ptr->data_ptr = virt_to_phys(skb->data);
++ if ((nr_frags == 0) && (len < MIN_PACKET_LEN)) {
++ txdesc_ptr->length = MIN_PACKET_LEN;
++ memset(skb->data + len, 0x00, MIN_PACKET_LEN - len);
++ } else {
++ txdesc_ptr->length = len;
++ }
++ if (nr_frags) {
++ txring.skb_ptr[txring.cur_index] = NULL;
++ } else {
++ txring.skb_ptr[txring.cur_index] = skb;
++ }
++ dma_cache_maint(skb->data, txdesc_ptr->length, PCI_DMA_TODEVICE);
++
++#if 0
++ printk("txdesc_ptr : %x\n", txdesc_ptr);
++ printk("txdesc_ptr->length: %d\n", txdesc_ptr->length);
++ printk("txdesc_ptr->insv : %d\n", txdesc_ptr->insv);
++ printk("txdesc_ptr->pmap : %d\n", txdesc_ptr->pmap);
++ printk("txdesc_ptr->vid : %d\n", txdesc_ptr->vid);
++#endif
++
++ txring.cur_index++;
++ if (txring.cur_index == STAR_GSW_MAX_TFD_NUM) {
++ txring.cur_index = 0;
++ }
++
++ for (f = 0; f < nr_frags; f++) {
++ struct skb_frag_struct *frag;
++ txdesc_ptr = txring.vir_addr + txring.cur_index;
++ frag = &skb_shinfo(skb)->frags[f];
++ len = frag->size;
++ offset = frag->page_offset;
++
++ txdesc_ptr->data_ptr = virt_to_phys(page_address(frag->page) + offset);
++ txdesc_ptr->length = len;
++ if (f == (nr_frags - 1)) {
++ txring.skb_ptr[txring.cur_index] = skb;
++ } else {
++ txring.skb_ptr[txring.cur_index] = NULL;
++ }
++ dma_cache_maint(page_address(frag->page) + offset, txdesc_ptr->length, PCI_DMA_TODEVICE);
++
++ txring.cur_index++;
++ if (txring.cur_index == STAR_GSW_MAX_TFD_NUM) {
++ txring.cur_index = 0;
++ }
++ }
++
++ for (f = 0; f < (nr_frags + 1); f++) {
++ txdesc_ptr = txring.vir_addr + org_index;
++
++ txdesc_ptr->cown = 0;
++
++ org_index++;
++ if (org_index == STAR_GSW_MAX_TFD_NUM) {
++ org_index = 0;
++ }
++ }
++
++#else // defined(MAX_SKB_FRAGS) && defined(STAR_GSW_SG)
++ txdesc_ptr = txring.vir_addr + txring.cur_index;
++
++
++ if (txdesc_ptr->cown == 0) { // This TFD is busy
++ spin_unlock_irqrestore(&star_gsw_send_lock, flags);
++ // re-queue the skb
++ return 1;
++ }
++
++ if (txdesc_ptr->data_ptr != 0) {
++ // MUST TODO: Free skbuff
++ dev_kfree_skb_any(txring.skb_ptr[txring.cur_index]);
++ }
++
++ /* clean dcache range in order that data synchronization*/
++ txring.skb_ptr[txring.cur_index] = skb;
++ txdesc_ptr->data_ptr = virt_to_phys(skb->data);
++
++ if (skb->len < MIN_PACKET_LEN) {
++ txdesc_ptr->length = MIN_PACKET_LEN;
++ memset(skb->data + skb->len, 0x00, MIN_PACKET_LEN - skb->len);
++ } else {
++ txdesc_ptr->length = skb->len;
++ }
++
++
++
++ /* clean dcache range in order that data synchronization*/
++ dma_cache_maint(skb->data, txdesc_ptr->length, PCI_DMA_TODEVICE);
++
++
++ // 20060922 descent
++ // if NIC MODE on
++ #ifdef CONFIG_NIC_MODE
++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++ // do nothing
++#else
++ if ( ((GSW_SWITCH_CONFIG >> 30) & 0x1) ==1){
++ const char lan_tag[]={0x81, 0x00, 0x00, 0x01};
++ const char wan_tag[]={0x81, 0x00, 0x00, 0x02};
++ unsigned char data; /* Data head pointer */
++
++ // insert vlan tag and move other byte to back
++ memmove(skb->data+16, skb->data + 12, skb->len-12);
++ skb->len+=4;
++
++ txdesc_ptr->length = skb->len;
++
++ if (dev == STAR_GSW_LAN_DEV) {
++ memcpy(skb->data+12, lan_tag, 4);
++ }
++ if (dev == STAR_GSW_WAN_DEV) {
++ memcpy(skb->data+12, wan_tag, 4);
++ }
++ dma_cache_maint(skb->data, txdesc_ptr->length, PCI_DMA_TODEVICE);
++ }
++#endif //defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++ #endif // ifdef CONFIG_NIC_MODE
++ // 20060922 descent end
++
++ /*
++ * Basically, according to the result of the search of the destination
++ * address in the routing table, the specific network interface will be
++ * correctly selected
++ * According to the device entry index value, we can know the packet will
++ * be destined for LAN port (port 0) or WAN port (port 1)
++ *
++ * Note:
++ * device entry index = 0 means local loopback network interface
++ * device entry index = 1 means GSW port 0 for LAN port network interface
++ * device entry index = 2 means GSW port 1 for WAN port network interface
++ * and also note:
++ * Force Route Port Map = 1 : GSW port 0
++ * = 2 : GSW port 1
++ * = 4 : GSW CPU port
++ */
++
++
++ PDEBUG("\n00 priv->pmap: %d\n", priv->pmap);
++
++
++#ifdef CONFIG_STR9100_VLAN_BASE
++ PDEBUG("CONFIG_STR9100_VLAN_BASE\n");
++
++
++
++ if (priv->pmap==-1)
++ {
++ // 20060922 descent
++ // if NIC MODE on
++ #ifdef CONFIG_NIC_MODE
++ if ( ((GSW_SWITCH_CONFIG >> 30) & 0x1) ==1)
++ {
++ txdesc_ptr->insv = 0;
++ }
++ else
++ #endif
++ // 20060922 descent end
++ {
++ txdesc_ptr->insv = 1;
++ }
++
++
++ PDEBUG("txdesc_ptr->insv = 1;\n");
++
++
++
++
++ txdesc_ptr->pmap = 1; // MAC0
++
++
++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++ // let 8021Q insert vlan tag
++ // so insv set to 0
++ txdesc_ptr->insv = 0;
++ #if 0
++ if (priv->vlgrp && vlan_tx_tag_present(skb)) {
++ //vlan_tag = cpu_to_be16(vlan_tx_tag_get(skb));
++ //vlan_tag = ntohl(vlan_tx_tag_get(skb));
++ //vlan_tag = (vlan_tx_tag_get(skb));
++ vlan_tag = cpu_to_le16(vlan_tx_tag_get(skb));
++ //printk("vlan_tag : %x\n", vlan_tag);
++ if (vlan_tag == 1) {
++ txdesc_ptr->vid = VLAN1_GROUP_ID; // lan
++ }
++ if (vlan_tag == 2) {
++ txdesc_ptr->vid = VLAN0_GROUP_ID; // wan
++ }
++ }
++ #endif
++#else // #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++
++
++
++ PDEBUG("txdesc_ptr->pmap = 1\n");
++ if (dev == STAR_GSW_WAN_DEV) {
++ txdesc_ptr->vid = VLAN0_GROUP_ID;
++ PDEBUG("VLAN0_GROUP_ID: %d\n", VLAN0_GROUP_ID);
++ } else {
++ txdesc_ptr->vid = VLAN1_GROUP_ID;
++ PDEBUG("VLAN1_GROUP_ID: %d\n", VLAN1_GROUP_ID);
++ }
++
++#endif // end #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++
++ }
++
++#endif // CONFIG_STR9100_VLAN_BASE
++
++#ifdef CONFIG_STR9100_PORT_BASE
++ if (priv->pmap != -1)
++ {
++ txdesc_ptr->insv = 0;
++ PDEBUG("txdesc_ptr->insv = 0;\n");
++ txdesc_ptr->pmap = priv->pmap;
++ PDEBUG("txdesc_ptr->pmap = priv->pmap;\n");
++ }
++ PDEBUG("CONFIG_STR9100_PORT_BASE\n");
++#endif
++ PDEBUG("txdesc_ptr->pmap: %d\n", txdesc_ptr->pmap);
++
++ txdesc_ptr->fr = 1;
++
++#ifdef CONFIG_STAR9100_SHNAT_PCI_FASTPATH
++ if (star9100_shnat_pci_fp_forward_skb_ptr == 0)
++ goto SEND_PACKET;
++ if(priv->pmap == PORT_BASE_PMAP_TUN_PORT){
++
++ struct iphdr *iph = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
++ star9100_arp_table volatile *arp_table;
++ u32 fp_gvid = 0;
++
++ arp_table = star9100_shnat_getarptable_hook(iph->saddr);
++ if(arp_table != NULL){
++ fp_gvid = arp_table->unused &= 0x7;
++ }
++#if 0
++ printk("[SEND PACKET] FP Path send_packet\n");
++#endif
++ txdesc_ptr->fr = 0;
++ txdesc_ptr->insv = 1;
++ txdesc_ptr->vid = fp_gvid;
++#if 0
++ print_packet(skb->data,128);
++#endif
++ }
++#endif /* CONFIG_STAR9100_SHNAT_PCI_FASTPATH */
++
++SEND_PACKET:
++
++ txdesc_ptr->fs = 1;
++ txdesc_ptr->ls = 1;
++ // Wake interrupt
++ txdesc_ptr->interrupt = 0;
++ txdesc_ptr->cown = 0;
++
++
++ if (txring.cur_index == (STAR_GSW_MAX_TFD_NUM - 1)) {
++ txring.cur_index = 0;
++ } else {
++ txring.cur_index++;
++ }
++
++
++#endif // defined(MAX_SKB_FRAGS) && defined(STAR_GSW_SG)
++ mb();
++ GSW_TS_DMA_START();
++
++
++ priv->stats.tx_packets++;
++ priv->stats.tx_bytes += skb->len;
++ dev->trans_start = jiffies;
++
++sendpacket_exit:
++ spin_unlock_irqrestore(&star_gsw_send_lock, flags);
++
++#ifdef FREE_TX_SKB_MULTI
++ for (i = 0; i < skb_free_count; i++) {
++ dev_kfree_skb(skb_free[i]);
++ }
++#else
++#if defined(MAX_SKB_FRAGS) && defined(STAR_GSW_SG)
++ for (f = 0; f < skb_free_count; f++) {
++ dev_kfree_skb(skb_free[f]);
++ }
++#else
++ if (skb_free) {
++ dev_kfree_skb(skb_free);
++ }
++#endif
++#endif
++
++#ifdef STAR_GSW_TIMER
++ mod_timer(&star_gsw_timer, jiffies + 10);
++#endif
++
++
++
++
++ return 0;
++}
++
++// modify parameter type by descent.
++// move dev->dev_addr to set mac function.
++static void star_gsw_set_mac_addr(int index, struct net_device *dev, void *addr)
++{
++ const char *mac = ((struct sockaddr *)addr)->sa_data;
++ int mac_len = dev->addr_len;
++ gsw_arl_table_entry_t arl_table_entry;
++
++ memcpy(dev->dev_addr, mac, 6);
++
++ //printk("addr: %x:%x:%x:%x:%x:%x\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
++
++ // erase old mac
++ arl_table_entry.filter = 0;
++ arl_table_entry.vlan_mac = 1;
++ arl_table_entry.vlan_gid = star_gsw_info.vlan[index].vlan_gid;
++ arl_table_entry.age_field = 0x0; // invalid mean erase this entry
++ arl_table_entry.port_map = star_gsw_info.vlan[index].vlan_group;
++ memcpy(arl_table_entry.mac_addr, star_gsw_info.vlan[index].vlan_mac, 6);
++ star_gsw_write_arl_table_entry(&arl_table_entry);
++
++ // copy new mac to star_gsw_info
++ memcpy(star_gsw_info.vlan[index].vlan_mac, mac, mac_len);
++ arl_table_entry.filter = 0;
++ arl_table_entry.vlan_mac = 1;
++ arl_table_entry.vlan_gid = star_gsw_info.vlan[index].vlan_gid;
++ arl_table_entry.age_field = 0x7;
++ arl_table_entry.port_map = star_gsw_info.vlan[index].vlan_group;
++ memcpy(arl_table_entry.mac_addr, star_gsw_info.vlan[index].vlan_mac, 6);
++ star_gsw_write_arl_table_entry(&arl_table_entry);
++}
++
++#if 0
++static void star_gsw_set_mac_addr(int index, const char *mac, int mac_len)
++{
++ gsw_arl_table_entry_t arl_table_entry;
++
++ // erase old mac
++ arl_table_entry.filter = 0;
++ arl_table_entry.vlan_mac = 1;
++ arl_table_entry.vlan_gid = star_gsw_info.vlan[index].vlan_gid;
++ arl_table_entry.age_field = 0x0; // invalid mean erase this entry
++ arl_table_entry.port_map = star_gsw_info.vlan[index].vlan_group;
++ memcpy(arl_table_entry.mac_addr, star_gsw_info.vlan[index].vlan_mac, 6);
++ star_gsw_write_arl_table_entry(&arl_table_entry);
++
++ // copy new mac to star_gsw_info
++ memcpy(star_gsw_info.vlan[index].vlan_mac, mac, mac_len);
++ arl_table_entry.filter = 0;
++ arl_table_entry.vlan_mac = 1;
++ arl_table_entry.vlan_gid = star_gsw_info.vlan[index].vlan_gid;
++ arl_table_entry.age_field = 0x7;
++ arl_table_entry.port_map = star_gsw_info.vlan[index].vlan_group;
++ memcpy(arl_table_entry.mac_addr, star_gsw_info.vlan[index].vlan_mac, 6);
++ star_gsw_write_arl_table_entry(&arl_table_entry);
++}
++#endif
++
++
++static int star_gsw_set_lan_mac_addr(struct net_device *dev, void *addr)
++{
++ struct sockaddr *sock_addr = addr;
++ struct star_gsw_private *priv = netdev_priv(dev);
++
++ spin_lock_irq(&priv->lock);
++ star_gsw_set_mac_addr(LAN_GID, dev, addr);
++ //star_gsw_set_mac_addr(LAN_GID, sock_addr->sa_data, dev->addr_len);
++ //star_gsw_set_mac_addr(0, sock_addr->sa_data, dev->addr_len);
++ spin_unlock_irq(&priv->lock);
++
++ return 0;
++}
++
++static int star_gsw_set_wan_mac_addr(struct net_device *dev, void *addr)
++{
++ struct sockaddr *sock_addr = addr;
++ struct star_gsw_private *priv = netdev_priv(dev);
++
++ spin_lock_irq(&priv->lock);
++ star_gsw_set_mac_addr(WAN_GID, dev, addr);
++ spin_unlock_irq(&priv->lock);
++
++ return 0;
++}
++
++// current dorado2 use this function
++static int star_gsw_set_ewc_mac_addr(struct net_device *dev, void *addr)
++{
++ struct sockaddr *sock_addr = addr;
++ struct star_gsw_private *priv = netdev_priv(dev);
++
++ spin_lock_irq(&priv->lock);
++ //star_gsw_set_mac_addr(2, sock_addr->sa_data, dev->addr_len);
++ star_gsw_set_mac_addr(2, dev, addr);
++ spin_unlock_irq(&priv->lock);
++
++ return 0;
++}
++
++static void __init star_gsw_hw_init(void)
++{
++ u32 mac_port_config;
++ int i;
++ u32 cfg_reg = 0;
++
++ cfg_reg = PWRMGT_SOFTWARE_RESET_CONTROL;
++ // set reset bit to HIGH active;
++ cfg_reg |=0x10;
++ PWRMGT_SOFTWARE_RESET_CONTROL = cfg_reg;
++
++ //pulse delay
++ udelay(100);
++
++ // set reset bit to LOW active;
++ cfg_reg &=~0x10;
++ PWRMGT_SOFTWARE_RESET_CONTROL = cfg_reg;
++
++ //pulse delay
++ udelay(100);
++
++ // set reset bit to HIGH active;
++ cfg_reg |= 0x10;
++ PWRMGT_SOFTWARE_RESET_CONTROL = cfg_reg;
++
++ for (i = 0; i < 1000; i++) {
++ cfg_reg = GSW_BIST_RESULT_TEST_0;
++ if ((cfg_reg & BIT(17))) {
++ break;
++ } else {
++ udelay(10);
++ }
++ }
++ // Set to defaule value
++ GSW_SWITCH_CONFIG = 0x007AA7A1;
++
++ // Set Mac port 0 to default value
++ GSW_MAC_PORT_0_CONFIG = 0x00423D80;
++
++ // Set Mac port 1 to default value
++ GSW_MAC_PORT_1_CONFIG = 0x00423D80;
++
++ // Set CPU port to default Value
++ GSW_CPU_PORT_CONFIG = 0x004C0000;
++
++ // Disable Port 0
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;
++ mac_port_config |= ((0x1 << 18));
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;
++
++ // Disable Port 1
++ mac_port_config = GSW_MAC_PORT_1_CONFIG;
++ mac_port_config |= ((0x1 << 18));
++ GSW_MAC_PORT_1_CONFIG = mac_port_config;
++}
++
++#ifdef CONFIG_STAR9100_SHNAT_PCI_FASTPATH
++static int tundev_close(struct net_device *dev){
++ netif_stop_queue(dev);
++ printk("Close Orion Fast Path Tunnel Device \n");
++ return 0;
++}
++static int tundev_open(struct net_device *dev){
++ netif_start_queue(dev);
++ printk("Open Orion Fast Path Tunnel Device \n");
++ return 0;
++}
++static void tundev_init(struct net_device *dev){
++ return;
++}
++static int __init star_gsw_probe_tun(void){
++ struct net_device *netdev;
++ struct star_gsw_private *priv;
++ int err=0;
++
++ //netdev = alloc_netdev(sizeof(struct star_gsw_private),"fp",tundev_init);
++ netdev = alloc_etherdev(sizeof(struct star_gsw_private));
++ if (!netdev) {
++ err = -ENOMEM;
++ goto progend;
++ }
++
++ sprintf(netdev->name,"fp"); // force name
++
++ priv = netdev_priv(netdev);
++ memset(priv, 0, sizeof(struct star_gsw_private));
++ spin_lock_init(&priv->lock);
++
++ //netdev->base_addr = IO_ADDRESS(GSW_BASE_ADDR);
++ netdev->base_addr = 0;
++ netdev->stop = tundev_close;
++ netdev->hard_start_xmit = star_gsw_send_packet;
++ netdev->open = tundev_open;
++ netdev->do_ioctl = gsw_do_ioctl;
++
++ //netdev->set_mac_address = star_gsw_set_lan_mac_addr;
++
++ netdev->features = NETIF_F_NO_CSUM;
++ netdev->hard_header = NULL;
++ netdev->rebuild_header = NULL;
++ netdev->hard_header_cache = NULL;
++ netdev->header_cache_update = NULL;
++ netdev->hard_header_parse = NULL;
++ netdev->flags = 0; // Don't need any flags
++ priv->pmap = PORT_BASE_PMAP_TUN_PORT;
++
++
++
++ err = register_netdev(netdev);
++ if (err) {
++ free_netdev(netdev);
++ err = -ENOMEM;
++ }
++
++progend:
++ return err;
++}
++#endif
++
++
++static int __init star_gsw_probe(int port_type)
++{
++ struct net_device *netdev;
++ struct star_gsw_private *priv;
++ int err;
++ struct sockaddr sock_addr;
++
++
++ netdev = alloc_etherdev(sizeof(struct star_gsw_private));
++ if (!netdev) {
++ err = -ENOMEM;
++ goto err_alloc_etherdev;
++ }
++
++ SET_NETDEV_DEV(netdev, NULL);
++
++ priv = netdev_priv(netdev);
++ memset(priv, 0, sizeof(struct star_gsw_private));
++ spin_lock_init(&priv->lock);
++
++
++ //netdev->base_addr = IO_ADDRESS(GSW_BASE_ADDR);
++ netdev->base_addr = 0;
++ netdev->open = star_gsw_open;
++ netdev->stop = star_gsw_close;
++ netdev->hard_start_xmit = star_gsw_send_packet;
++ netdev->tx_timeout = star_gsw_timeout;
++ netdev->get_stats = star_gsw_get_stats;
++#if defined(MAX_SKB_FRAGS) && defined(STAR_GSW_SG)
++ netdev->features = NETIF_F_IP_CSUM | NETIF_F_SG;
++#elif defined(STAR_GSW_TX_HW_CHECKSUM)
++ netdev->features = NETIF_F_IP_CSUM;
++#endif
++
++#ifdef CONFIG_STAR_GSW_NAPI
++ netif_napi_add(netdev, &priv->napi, star_gsw_poll, 64);
++#endif
++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++ // do not let 8021Q module insert vlan tag
++ // can use the snippet code to get vlan tage
++ // if (priv->vlgrp && vlan_tx_tag_present(skb)) {
++ // vlan_tag = cpu_to_be16(vlan_tx_tag_get(skb));
++ //netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
++ netdev->features |= NETIF_F_HW_VLAN_RX; // remove NETIF_F_HW_VLAN_TX flag that 8021Q module to insert vlan tag.
++
++ netdev->vlan_rx_register = gsw_vlan_rx_register;
++ netdev->vlan_rx_kill_vid = gsw_vlan_rx_kill_vid;
++#endif
++
++
++
++ switch (port_type) {
++ case LAN_PORT:
++ netdev->set_mac_address = star_gsw_set_lan_mac_addr;
++ memcpy(sock_addr.sa_data, star_gsw_info.vlan[LAN_GID].vlan_mac, 6);
++ star_gsw_set_lan_mac_addr(netdev, &sock_addr);
++ //priv->pmap = PMAP_PORT0;
++ //priv->pmap = PORT_BASE_PORT0;
++ priv->pmap = PORT_BASE_PMAP_LAN_PORT;
++ break;
++
++ case WAN_PORT:
++ //netdev->open = star_gsw_wan_open;
++ netdev->set_mac_address = star_gsw_set_wan_mac_addr;
++ memcpy(sock_addr.sa_data, star_gsw_info.vlan[WAN_GID].vlan_mac, 6);
++ star_gsw_set_wan_mac_addr(netdev, &sock_addr);
++ //priv->pmap = PMAP_PORT1;
++ priv->pmap = PORT_BASE_PMAP_WAN_PORT;
++ break;
++
++ case EWC_PORT:
++ //netdev->open = star_gsw_ewc_open;
++ netdev->set_mac_address = star_gsw_set_ewc_mac_addr;
++ //memcpy(sock_addr.sa_data, star_gsw_info.vlan[WAN_GID].vlan_mac, 6);
++ //priv->pmap = PMAP_PORT1;
++ priv->pmap = PORT_BASE_PMAP_EWC_PORT;
++ break;
++
++ default:
++ break;
++ }
++
++ err = register_netdev(netdev);
++ if (err) {
++ printk("Register network dev :%s failed \n", netdev->name);
++ goto err_register_netdev;
++ }
++
++
++
++ switch (port_type) {
++ case LAN_PORT:
++ STAR_GSW_LAN_DEV = netdev;
++ break;
++
++ case WAN_PORT:
++ STAR_GSW_WAN_DEV = netdev;
++
++
++ break;
++
++ case EWC_PORT:
++ PDEBUG("create ewc port\n");
++ STAR_GSW_EWC_DEV = netdev;
++ break;
++
++ default:
++ break;
++ }
++
++#if 0
++ if (net_dev_array[0] == 0) {
++ net_dev_array[0] = netdev;
++ }
++#endif
++ ++all_netdevice;
++ return 0;
++
++err_register_netdev:
++ free_netdev(netdev);
++
++err_alloc_etherdev:
++ return err;
++}
++
++#ifdef LINUX26
++extern struct proc_dir_entry *str9100_proc_dir;
++static int __init star_gsw_proc_init(void)
++{
++ star_gsw_proc_entry = create_proc_entry("gsw", S_IFREG | S_IRUGO, str9100_proc_dir);
++ if (star_gsw_proc_entry) {
++ star_gsw_proc_entry->read_proc = star_gsw_read_proc;
++ star_gsw_proc_entry->write_proc = star_gsw_write_proc;
++ }
++ return 1;
++}
++#endif
++
++
++#ifdef LINUX24
++static int __init star_gsw_proc_init(void)
++{
++ struct proc_dir_entry *procdir=0;
++
++ const char proc_str[]="str9100";
++
++ //str9100_gsw_procdir=proc_mkdir(proc_str, NULL);
++
++ procdir=create_proc_str9100(PROC_STR);
++
++ if (procdir)
++ {
++ star_gsw_proc_entry = create_proc_entry("gsw", S_IFREG | S_IRUGO, procdir);
++ if (star_gsw_proc_entry) {
++ star_gsw_proc_entry->read_proc = star_gsw_read_proc;
++ star_gsw_proc_entry->write_proc = star_gsw_write_proc;
++ }
++ return 1;
++ }
++ else
++ return -1;
++
++
++
++}
++#endif
++
++static int star_gsw_notify_reboot(struct notifier_block *nb, unsigned long event, void *ptr)
++{
++ u32 mac_port_config;
++
++ /* stop the DMA engine */
++ GSW_TS_DMA_STOP();
++ GSW_FS_DMA_STOP();
++
++ // disable Port 0
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;
++ mac_port_config |= ((0x1 << 18));
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;
++
++ // disable Port 1
++ mac_port_config = GSW_MAC_PORT_1_CONFIG;
++ mac_port_config |= ((0x1 << 18));
++ GSW_MAC_PORT_1_CONFIG = mac_port_config;
++
++ // disable all interrupt status sources
++ GSW_DISABLE_ALL_INTERRUPT_STATUS_SOURCES();
++
++ // clear previous interrupt sources
++ GSW_CLEAR_ALL_INTERRUPT_STATUS_SOURCES();
++
++ // disable all DMA-related interrupt sources
++ INTC_DISABLE_INTERRUPT_SOURCE(INTC_GSW_TSTC_BIT_INDEX);
++ INTC_DISABLE_INTERRUPT_SOURCE(INTC_GSW_FSRC_BIT_INDEX);
++ INTC_DISABLE_INTERRUPT_SOURCE(INTC_GSW_TSQE_BIT_INDEX);
++ INTC_DISABLE_INTERRUPT_SOURCE(INTC_GSW_FSQF_BIT_INDEX);
++
++ // clear previous interrupt sources
++ INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GSW_TSTC_BIT_INDEX);
++ INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GSW_FSRC_BIT_INDEX);
++ INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GSW_TSQE_BIT_INDEX);
++ INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GSW_FSQF_BIT_INDEX);
++
++ return NOTIFY_DONE;
++}
++
++
++
++
++
++static int __init star_gsw_init_module(void)
++{
++ int err = 0;
++ u8 mac_num[6]; // get from flash
++
++ spin_lock_init(&star_gsw_send_lock);
++
++
++//#define CONFIG_GET_FLASH_MAC
++#ifdef CONFIG_GET_FLASH_MAC
++ char *mac_addr;
++
++ PRINT_INFO(KERN_INFO "%s", star_gsw_driver_version);
++ mac_addr=get_flash_env("ethaddr");
++ if (mac_addr)
++ {
++ printk("mac addr: %s\n", mac_addr);
++ printk("mac len: %d\n", strlen(mac_addr) );
++
++ }
++ sscanf(mac_addr ,"%x:%x:%x:%x:%x:%x", (unsigned int *)&mac_num[0], (unsigned int *)&mac_num[1], (unsigned int *)&mac_num[2], (unsigned int *)&mac_num[3], (unsigned int *)&mac_num[4], (unsigned int *)&mac_num[5]);
++ printk("flash mac : %x:%x:%x:%x:%x:%x\n", *mac_num,*(mac_num+1),*(mac_num+2), *(mac_num+3), *(mac_num+4), *(mac_num+5) );
++
++
++ memcpy(my_vlan0_mac, mac_num, 6);
++ ++mac_num[5];
++ memcpy(my_vlan1_mac, mac_num, 6);
++ ++mac_num[5];
++ memcpy(my_vlan2_mac, mac_num, 6);
++ ++mac_num[5];
++ memcpy(my_vlan3_mac, mac_num, 6);
++
++
++
++#endif
++
++
++
++ star_gsw_hw_init();
++ err = star_gsw_buffer_alloc();
++ if (err != 0) {
++ return err;
++ }
++ star_gsw_vlan_init();
++ star_gsw_config_cpu_port();
++ init_switch();
++
++//#if 0
++ CREATE_NET_DEV0
++ CREATE_NET_DEV1
++ CREATE_NET_DEV2
++#ifdef CONFIG_STAR9100_SHNAT_PCI_FASTPATH
++ CREATE_NET_DEV_AD
++#endif
++
++ str9100_gsw_config_mac_port0();
++ str9100_gsw_config_mac_port1();
++
++#ifdef CONFIG_STAR_GSW_NAPI
++ {
++ struct star_gsw_private *priv;
++ STAR_NAPI_DEV = alloc_etherdev(sizeof(struct star_gsw_private));
++ if (!STAR_NAPI_DEV) {
++ printk("Cannot allocate NAPI virtual device \n");
++ BUG();
++ }
++
++ priv = netdev_priv(STAR_NAPI_DEV);
++ memset(priv, 0, sizeof(struct star_gsw_private));
++
++ netif_napi_add(STAR_NAPI_DEV, &priv->napi , star_gsw_poll, 64);
++ dev_hold(STAR_NAPI_DEV);
++ set_bit(__LINK_STATE_START, &STAR_NAPI_DEV->state);
++ }
++#endif
++//#endif
++
++#if 0
++ star_gsw_lan_init();
++
++#ifndef CONFIG_STAR_GSW_TYPE_9109
++ star_gsw_wan_init();
++#endif
++#ifdef CONFIG_STAR_GSW_TYPE_EWC
++ star_gsw_ewc_init();
++#endif
++#endif
++
++ star_gsw_proc_init();
++
++ register_reboot_notifier(&star_gsw_notifier_reboot);
++#ifdef STAR_GSW_TIMER
++ init_timer(&star_gsw_timer);
++ star_gsw_timer.function = &star_gsw_timer_func;
++ star_gsw_timer.data = (unsigned long)NULL;
++#endif
++
++
++ return 0;
++}
++
++static void __exit star_gsw_exit_module(void)
++{
++ int i=0;
++
++#if 1
++ for (i=0 ; i < all_netdevice ; ++i) {
++ char netdev_name[20];
++ struct net_device * netdev=0;
++
++ sprintf(netdev_name, "eth%d", i);
++ //printk("net_dev_array[0]: %x\n", net_dev_array[0]);
++ netdev=__dev_get_by_name(&init_net, netdev_name);
++ // if no unregister_netdev and free_netdev,
++ // after remove module, ifconfig will hang.
++ #if 1
++ if (netdev) {
++ unregister_netdev(netdev);
++ free_netdev(netdev);
++ }
++ #endif
++ }
++#endif
++
++#ifdef CONFIG_STAR_GSW_NAPI
++ free_netdev(STAR_NAPI_DEV);
++#endif
++
++#if 0
++ unregister_netdev(STAR_GSW_LAN_DEV);
++ free_netdev(STAR_GSW_LAN_DEV);
++
++ unregister_netdev(STAR_GSW_WAN_DEV);
++ free_netdev(STAR_GSW_WAN_DEV);
++#endif
++ //unregister_netdev(STAR_GSW_EWC_DEV);
++ //free_netdev(STAR_GSW_EWC_DEV);
++
++ unregister_reboot_notifier(&star_gsw_notifier_reboot);
++ star_gsw_buffer_free();
++}
++
++
++// this snippet code ref 8139cp.c
++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++void gsw_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
++{
++ struct star_gsw_private *priv = netdev_priv(dev);
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ printk("gsw_vlan_rx_register\n");
++ priv->vlgrp = grp;
++ spin_unlock_irqrestore(&priv->lock, flags);
++}
++
++void gsw_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
++{
++ struct star_gsw_private *priv = netdev_priv(dev);
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ if (priv->vlgrp)
++ priv->vlgrp->vlan_devices[vid] = NULL;
++ spin_unlock_irqrestore(&priv->lock, flags);
++}
++
++#endif
++
++//#define CONFIG_SWITCH_IOCTL
++#ifdef CONFIG_SWITCH_IOCTL
++
++/* ADD MAC into ARL */
++/***
++ * add_mac_into_arl - add extra(without hnat support) my mac in ARL table.
++ *
++ * INPUTS:
++ * gid - vlan group (0-7)
++ * mac - mac address
++ *
++ * OUTPUTS:
++ * None
++ *
++ * RETURNS:
++ * void
++ ***/
++int add_mac_into_arl(u16 gid, u8 *mac)
++{
++ gsw_arl_table_entry_t arl_table_entry;
++
++ arl_table_entry.filter = 0;
++ arl_table_entry.vlan_mac = 1; // the MAC in this table entry is MY VLAN MAC
++ arl_table_entry.vlan_gid = gid;
++ arl_table_entry.age_field = 0x7; // static entry
++ arl_table_entry.port_map = star_gsw_info.vlan[gid].vlan_group;
++ memcpy(arl_table_entry.mac_addr, mac, 6);
++
++ if (!star_gsw_write_arl_table_entry(&arl_table_entry)) {
++ //DEBUG_MSG(WARNING_MSG, "star_gsw_write_arl_table_entry fail\n");
++ return 1;
++ }
++
++ return 0;
++}
++
++/* DEL MAC from ARL*/
++//void del_my_vlan_mac_2argu(u8 gid, u8 *mac)
++/***
++ * star_gsw_del_arl_table - delete my mac from ARL table
++ *
++ * INPUTS:
++ * mac - mac address
++ * vlan_gid - gid value
++ *
++ * OUTPUTS:
++ * None
++ *
++ * RETURNS:
++ * 0 - successful
++ *
++ ***/
++void del_mac_from_arl(u8 gid, u8 *mac)
++{
++ gsw_arl_table_entry_t arl_table_entry;
++
++ // erase old mac
++ arl_table_entry.filter = 0;
++ arl_table_entry.vlan_mac = 1;
++ //arl_table_entry.vlan_gid = star_gsw_info.vlan[gid].vlan_gid;
++ arl_table_entry.vlan_gid = gid;
++ arl_table_entry.age_field = 0x0; // invalid mean erase this entry
++ arl_table_entry.port_map = star_gsw_info.vlan[gid].vlan_group;
++ memcpy(arl_table_entry.mac_addr, mac, 6);
++ star_gsw_write_arl_table_entry(&arl_table_entry);
++}
++
++
++/***
++ * del_my_vlan_mac - delete my mac of default setting from ARL table.
++ *
++ * INPUTS:
++ * gid - vlan group (0-7)
++ *
++ * OUTPUTS:
++ * None
++ *
++ * RETURNS:
++ * void
++ ***/
++void del_my_vlan_mac(u8 gid)
++{
++ gsw_arl_table_entry_t arl_table_entry;
++
++ // erase old mac
++ arl_table_entry.filter = 0;
++ arl_table_entry.vlan_mac = 1;
++ arl_table_entry.vlan_gid = gid;
++ arl_table_entry.age_field = 0x0; // invalidate this entry
++ arl_table_entry.port_map = star_gsw_info.vlan[gid].vlan_group;
++ memcpy(arl_table_entry.mac_addr, star_gsw_info.vlan[gid].vlan_mac, 6);
++ star_gsw_write_arl_table_entry(&arl_table_entry);
++}
++
++/***
++ * config_my_vlan_mac - change my mac default setting, according to
++ * gid and vid value.
++ *
++ * INPUTS:
++ * gid - vlan group (0-7)
++ * vid - vlan id (12 bits)
++ * mac - mac address
++ *
++ * OUTPUTS:
++ * None
++ *
++ * RETURNS:
++ * 0 - successful
++ * 1 - fail
++ ***/
++int config_my_vlan_mac(u16 gid, u16 vid, u8 *mac)
++{
++ gsw_arl_table_entry_t arl_table_entry;
++
++ star_gsw_info.vlan[gid].vlan_gid = gid;
++ star_gsw_info.vlan[gid].vlan_vid = vid;
++ star_gsw_info.vlan[gid].vlan_group = (PORT0 | CPU_PORT); // this case always (PORT0 | CPU_PORT)
++ star_gsw_info.vlan[gid].vlan_tag_flag = 0;
++ memcpy(star_gsw_info.vlan[gid].vlan_mac, mac, 6);
++
++
++
++ arl_table_entry.filter = 0;
++ arl_table_entry.vlan_mac = 1; // the MAC in this table entry is MY VLAN MAC
++ arl_table_entry.vlan_gid = star_gsw_info.vlan[gid].vlan_gid;
++ arl_table_entry.age_field = 0x7; // static entry
++ arl_table_entry.port_map = star_gsw_info.vlan[gid].vlan_group;
++ memcpy(arl_table_entry.mac_addr, star_gsw_info.vlan[gid].vlan_mac, 6);
++
++ if (!star_gsw_write_arl_table_entry(&arl_table_entry)) {
++ //DEBUG_MSG(WARNING_MSG, "star_gsw_write_arl_table_entry fail\n");
++ return 1;
++ }
++
++ return 0;
++}
++
++#endif // end CONFIG_SWITCH_IOCTL
++
++// reference e100.c
++static int gsw_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
++{
++ printk("gsw_do_ioctl\n");
++ return 0;
++}
++
++
++MODULE_AUTHOR("Star Corporation, <tech at starsemi.com>");
++MODULE_DESCRIPTION("Star Switch Driver");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(DRV_VERSION);
++
++
++
++module_init(star_gsw_init_module);
++module_exit(star_gsw_exit_module);
++
+diff -rupN linux-2.6.35.11/drivers/net/str9100/star_gsw_config.h linux-2.6.35.11-ts7500/drivers/net/str9100/star_gsw_config.h
+--- linux-2.6.35.11/drivers/net/str9100/star_gsw_config.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/str9100/star_gsw_config.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,288 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef __STAR_GSW_CONFIG_H__
++#define __STAR_GSW_CONFIG_H__
++
++
++// add by descent 2006/07/05
++// this debug macro reference linux device drivers, 2e
++
++
++// 20060922 descent
++// in dorado, if NIC mode on, and use ARL search, need enable STR9100_GSW_FAST_AGE_OUT
++// NIC mode is experiment, don't recommand use it.
++#define CONFIG_NIC_MODE
++
++// 20060922 descent end
++
++//#define STR9100_GSW_DEBUG
++
++
++#ifdef SHOW_DEBUG_MESSAGE
++
++#define NORMAL_MSG 1
++#define WARNING_MSG (1 << 1)
++#define CRITICAL_MSG (1 << 2)
++
++#define DEBUG_MSG(msg_level, fmt, args...)\
++{ \
++ int i=0; \
++\
++ for(i=0 ; i < 3 ; ++i) { \
++ if ((MSG_LEVEL & msg_level) >> i) \
++ printk (KERN_INFO "*str9100_gsw_debug* " fmt, ## args); \
++ } \
++}
++
++#endif
++
++
++
++// direction is "TX" or "RX"
++#define PRINT_PACKET(data, len, direction) \
++{ \
++ printk(direction); \
++ print_packet(data, len); \
++}
++
++#undef PDEBUG
++ #ifdef STR9100_GSW_DEBUG
++ #ifdef __KERNEL__
++ #define PDEBUG(fmt, args...) printk (KERN_INFO "*str9100_gsw_debug* " fmt, ## args)
++ //#define PDEBUG printk
++ #else
++ #define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
++ #endif // __KERNEL__
++ #else
++ #define PDEBUG(fmt, args...)
++ #endif
++
++#undef PDEBUGG
++#define PDEBUGG(fmt, args...)
++
++// 20061103 descent
++//#define CONFIG_CONF_VID
++// 20061103 descent end
++
++
++// modify by descent 2006/07/05
++// use for print needed message
++#if 1
++#define PRINT_INFO printk
++#else
++#define PRINT_INFO(arg...)
++#endif
++
++
++#define CONFIG_STAR_GSW_NAPI
++
++// add by descent 2006/07/07
++// in star_gsw_get_rfd_buff
++// if define CONFIG_STAR_GSW_BRIDGE drop no packets
++// else drop invalid packets.
++
++
++#include <linux/config.h>
++#ifdef CONFIG_BRIDGE // reference linux config network bridge
++#define CONFIG_STAR_GSW_BRIDGE
++#endif
++
++// add by descent 2006/07/05
++// 1 mean rate controll on
++// 0 mean rate controll off
++#define STR9100_GSW_BROADCAST_RATE_CONTROL 0
++#define STR9100_GSW_MULTICAST_RATE_CONTROL 0
++#define STR9100_GSW_UNKNOW_PACKET_RATE_CONTROL 0
++
++// 1 mean forwarding off
++// 0 mean forwarding on
++#define STR9100_GSW_DISABLE_FORWARDING_BROADCAST_PACKET 0
++#define STR9100_GSW_DISABLE_FORWARDING_MULTICAST_PACKET 0
++#define STR9100_GSW_DISABLE_FORWARDING_UNKNOW_PACKET 0
++
++//#define STR9100_GSW_FAST_AGE_OUT
++
++#define STAR_GSW_TX_HW_CHECKSUM
++#define STAR_GSW_RX_HW_CHECKSUM
++
++
++//#define STAR_GSW_TIMER
++//#define FREE_TX_SKB_MULTI
++#define STAR_GSW_SG
++#if defined(STAR_GSW_SG) && !defined(STAR_GSW_TX_HW_CHECKSUM)
++#define STAR_GSW_TX_HW_CHECKSUM
++#endif
++
++
++//#define ADJUSTMENT_TX_RX_SKEW
++//#define STAR_GSW_STATUS_ISR
++#define STAR_GSW_FSQF_ISR
++
++
++// adjust MAX_PEND_INT_CNT and MAX_PEND_TIME at run time.
++//#define CHANGE_DELAY_INT
++
++#define STAR_GSW_DELAYED_INTERRUPT
++
++#define MAX_PEND_INT_CNT 0x06
++#define MAX_PEND_TIME 0x20
++
++/*
++ * This tag is for 9102 + 9109 Case only, and 9102's MAC0 Connect ot 9102's MAC1
++ */
++#ifdef CONFIG_STAR_GSW_TYPE_EWC
++#define CONFIG_STAR_GSW_TYPE_ONEARM "y"
++#undef CONFIG_SERCOMM_VSC7385
++#endif
++
++#if 0
++
++#define VLAN0_GROUP_ID (0)
++#define VLAN1_GROUP_ID (1)
++#define VLAN2_GROUP_ID (2)
++#define VLAN3_GROUP_ID (3)
++#define VLAN4_GROUP_ID (4)
++#define VLAN5_GROUP_ID (5)
++#define VLAN6_GROUP_ID (6)
++#define VLAN7_GROUP_ID (7)
++
++
++
++
++
++#ifdef CONFIG_STAR_GSW_TYPE_ONEARM
++#ifdef CONFIG_SERCOMM_VSC7385
++#define VLAN0_VID (0x1)
++#define VLAN1_VID (0x2)
++#define VLAN2_VID (0x3)
++#define VLAN3_VID (0x4)
++#define VLAN4_VID (0x5)
++#define VLAN5_VID (0x6)
++#define VLAN6_VID (0x7)
++#define VLAN7_VID (0x8)
++#else
++#define VLAN0_VID (0x2)
++#define VLAN1_VID (0x1)
++#define VLAN2_VID (0x3)
++#define VLAN3_VID (0x4)
++#define VLAN4_VID (0x5)
++#define VLAN5_VID (0x6)
++#define VLAN6_VID (0x7)
++#define VLAN7_VID (0x8)
++#endif
++#else
++#define VLAN0_VID (0x111)
++#define VLAN1_VID (0x222)
++#define VLAN2_VID (0x333)
++#define VLAN3_VID (0x444)
++#define VLAN4_VID (0x555)
++#define VLAN5_VID (0x666)
++#define VLAN6_VID (0x777)
++#define VLAN7_VID (0x888)
++#endif
++
++#define PORT0 (1 << 0) /* bit map : bit 0 */
++#define PORT1 (1 << 1) /* bit map : bit 1 */
++#define CPU_PORT (1 << 2) /* bit map : bit 2 */
++
++#ifdef CONFIG_STAR_GSW_TYPE_ONEARM
++#define VLAN0_GROUP (PORT0 | CPU_PORT)
++#define VLAN1_GROUP (PORT0 | CPU_PORT)
++#ifdef CONFIG_STAR_GSW_TYPE_EWC
++#define VLAN2_GROUP (PORT1 | CPU_PORT)
++#define VLAN3_GROUP (PORT1 | CPU_PORT)
++#else
++#define VLAN2_GROUP (0)
++#define VLAN3_GROUP (0)
++#endif
++#define VLAN4_GROUP (0)
++#define VLAN5_GROUP (0)
++#define VLAN6_GROUP (0)
++#ifdef CONFIG_STAR_GSW_TYPE_EWC
++#define VLAN7_GROUP (PORT1 | CPU_PORT)
++#else
++#define VLAN7_GROUP (0)
++#endif
++
++#else
++#define VLAN0_GROUP (PORT0 | PORT1 | CPU_PORT)
++#define VLAN1_GROUP (PORT0 | CPU_PORT)
++#define VLAN2_GROUP (PORT1 | CPU_PORT)
++#define VLAN3_GROUP (0)
++#define VLAN4_GROUP (0)
++#define VLAN5_GROUP (0)
++#define VLAN6_GROUP (0)
++#define VLAN7_GROUP (0)
++#endif
++
++#ifdef CONFIG_STAR_GSW_TYPE_ONEARM
++
++#ifdef CONFIG_HAVE_VLAN_TAG
++
++#define VLAN0_VLAN_TAG (5) // cpu port and mac 0 port
++#define VLAN1_VLAN_TAG (5) // cpu port and mac 0 port
++
++#else
++#define VLAN0_VLAN_TAG (1) // only mac 0 port
++#define VLAN1_VLAN_TAG (1) // only mac 0 port
++#endif
++
++#define VLAN2_VLAN_TAG (0)
++#define VLAN3_VLAN_TAG (0)
++#define VLAN4_VLAN_TAG (0)
++#define VLAN5_VLAN_TAG (0)
++#define VLAN6_VLAN_TAG (0)
++#ifdef CONFIG_STAR_GSW_TYPE_EWC
++#define VLAN7_VLAN_TAG (0) // MAC1 don't need Tag
++#else
++#define VLAN7_VLAN_TAG (0)
++#endif
++#else
++#define VLAN0_VLAN_TAG (0)
++#define VLAN1_VLAN_TAG (0)
++#define VLAN2_VLAN_TAG (0)
++#define VLAN3_VLAN_TAG (0)
++#define VLAN4_VLAN_TAG (0)
++#define VLAN5_VLAN_TAG (0)
++#define VLAN6_VLAN_TAG (0)
++#define VLAN7_VLAN_TAG (0)
++#endif
++
++
++#define PORT0_PVID (VLAN1_GROUP_ID)
++#define PORT1_PVID (VLAN2_GROUP_ID)
++#define CPU_PORT_PVID (VLAN0_GROUP_ID)
++
++#endif
++
++#define MAX_PACKET_LEN (1536)
++
++/*
++ * Maximum Transmit/Receive Frame Descriptors for GSW's MAC frame
++ * the value of tx/rx set to 40/48 is suggested.
++ */
++#define STAR_GSW_MAX_TFD_NUM 40
++#define STAR_GSW_MAX_RFD_NUM 48
++
++#endif /* __STAR_GSW_CONFIG_H__ */
+diff -rupN linux-2.6.35.11/drivers/net/str9100/star_gsw.h linux-2.6.35.11-ts7500/drivers/net/str9100/star_gsw.h
+--- linux-2.6.35.11/drivers/net/str9100/star_gsw.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/str9100/star_gsw.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,682 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef STAR_GSW_H
++#define STAR_GSW_H
++
++#include "star_gsw_phy.h"
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/bootmem.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/fcntl.h>
++#include <linux/interrupt.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/in.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/proc_fs.h>
++#include <linux/reboot.h>
++#include <asm/bitops.h>
++#include <asm/irq.h>
++#include <asm/io.h>
++#include <asm/hardware.h>
++#include <linux/pci.h>
++#include <linux/errno.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <linux/ip.h>
++#include <linux/if_ether.h>
++#include <linux/icmp.h>
++#include <linux/udp.h>
++#include <linux/tcp.h>
++#include <linux/if_arp.h>
++#include <net/arp.h>
++
++#if defined(LINUX24)
++#include <asm/arch/str9100/star_gsw.h>
++#include <asm/arch/str9100/star_gpio.h>
++#include <asm/arch/str9100/star_powermgt.h>
++#endif
++
++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++#include <linux/if_vlan.h>
++#endif
++
++
++
++
++#include "star_gsw_config.h"
++
++#ifndef BIT
++#define BIT(x) ((1 << (x)))
++#endif
++
++#define LAN_PORT 1
++#define WAN_PORT 2
++#define EWC_PORT 3
++#ifdef CONFIG_STAR9100_SHNAT_PCI_FASTPATH
++
++#define TUN_PORT 4
++#define PMAP_TUN_PORT 8
++#define CREATE_NET_DEV_AD star_gsw_probe_tun();
++#define PORT_BASE_PMAP_TUN_PORT PMAP_TUN_PORT
++#else
++#define CREATE_NET_DEV_AD
++#define PORT_BASE_PMAP_TUN_PORT
++#endif
++
++
++// add by descent 2006/07/10
++#define PMAP_PORT0 1
++#define PMAP_PORT1 2
++#define PMAP_CPU_PORT 4
++
++
++/*
++ * macro declarations
++ */
++#define GSW_SET_PORT0_PVID(port0_pvid) \
++{ \
++ ((GSW_VLAN_PORT_PVID) &= (~(0x7 << 0))); \
++ ((GSW_VLAN_PORT_PVID) |= ((port0_pvid) & 0x07)); \
++}
++
++#define GSW_SET_PORT1_PVID(port1_pvid) \
++{ \
++ ((GSW_VLAN_PORT_PVID) &= (~(0x7 << 4))); \
++ ((GSW_VLAN_PORT_PVID) |= (((port1_pvid) & 0x07) << 4)); \
++}
++
++#define GSW_SET_CPU_PORT_PVID(cpu_port_pvid) \
++{ \
++ ((GSW_VLAN_PORT_PVID) &= (~(0x7 << 8))); \
++ ((GSW_VLAN_PORT_PVID) |= (((cpu_port_pvid) & 0x07) << 8)); \
++}
++
++#define GSW_SET_VLAN_0_VID(vid) \
++{ \
++ ((GSW_VLAN_VID_0_1) &= (~(0xFFF << 0))); \
++ ((GSW_VLAN_VID_0_1) |= (((vid) & 0xFFF) << 0)); \
++}
++
++#define GSW_SET_VLAN_1_VID(vid) \
++{ \
++ ((GSW_VLAN_VID_0_1) &= (~(0xFFF << 12))); \
++ ((GSW_VLAN_VID_0_1) |= (((vid) & 0xFFF) << 12)); \
++}
++
++#define GSW_SET_VLAN_2_VID(vid) \
++{ \
++ ((GSW_VLAN_VID_2_3) &= (~(0xFFF << 0))); \
++ ((GSW_VLAN_VID_2_3) |= (((vid) & 0xFFF) << 0)); \
++}
++
++#define GSW_SET_VLAN_3_VID(vid) \
++{ \
++ ((GSW_VLAN_VID_2_3) &= (~(0xFFF << 12))); \
++ ((GSW_VLAN_VID_2_3) |= (((vid) & 0xFFF) << 12)); \
++}
++
++#define GSW_SET_VLAN_4_VID(vid) \
++{ \
++ ((GSW_VLAN_VID_4_5) &= (~(0xFFF << 0))); \
++ ((GSW_VLAN_VID_4_5) |= (((vid) & 0xFFF) << 0)); \
++}
++
++#define GSW_SET_VLAN_5_VID(vid) \
++{ \
++ ((GSW_VLAN_VID_4_5) &= (~(0xFFF << 12))); \
++ ((GSW_VLAN_VID_4_5) |= (((vid) & 0xFFF) << 12)); \
++}
++
++#define GSW_SET_VLAN_6_VID(vid) \
++{ \
++ ((GSW_VLAN_VID_6_7) &= (~(0xFFF << 0))); \
++ ((GSW_VLAN_VID_6_7) |= (((vid) & 0xFFF) << 0)); \
++}
++
++#define GSW_SET_VLAN_7_VID(vid) \
++{ \
++ ((GSW_VLAN_VID_6_7) &= (~(0xFFF << 12))); \
++ ((GSW_VLAN_VID_6_7) |= (((vid) & 0xFFF) << 12)); \
++}
++
++#define GSW_SET_VLAN_0_MEMBER(vlan_member) \
++{ \
++ ((GSW_VLAN_MEMBER_PORT_MAP) &= (~(0x7 << 0))); \
++ ((GSW_VLAN_MEMBER_PORT_MAP) |= (((vlan_member) & 0x7) << 0)); \
++}
++
++#define GSW_SET_VLAN_1_MEMBER(vlan_member) \
++{ \
++ ((GSW_VLAN_MEMBER_PORT_MAP) &= (~(0x7 << 3))); \
++ ((GSW_VLAN_MEMBER_PORT_MAP) |= (((vlan_member) & 0x7) << 3)); \
++}
++
++#define GSW_SET_VLAN_2_MEMBER(vlan_member) \
++{ \
++ ((GSW_VLAN_MEMBER_PORT_MAP) &= (~(0x7 << 6))); \
++ ((GSW_VLAN_MEMBER_PORT_MAP) |= (((vlan_member) & 0x7) << 6)); \
++}
++
++#define GSW_SET_VLAN_3_MEMBER(vlan_member) \
++{ \
++ ((GSW_VLAN_MEMBER_PORT_MAP) &= (~(0x7 << 9))); \
++ ((GSW_VLAN_MEMBER_PORT_MAP) |= (((vlan_member) & 0x7) << 9)); \
++}
++
++#define GSW_SET_VLAN_4_MEMBER(vlan_member) \
++{ \
++ ((GSW_VLAN_MEMBER_PORT_MAP) &= (~(0x7 << 12))); \
++ ((GSW_VLAN_MEMBER_PORT_MAP) |= (((vlan_member) & 0x7) << 12)); \
++}
++
++#define GSW_SET_VLAN_5_MEMBER(vlan_member) \
++{ \
++ ((GSW_VLAN_MEMBER_PORT_MAP) &= (~(0x7 << 15))); \
++ ((GSW_VLAN_MEMBER_PORT_MAP) |= (((vlan_member) & 0x7) << 15)); \
++}
++
++#define GSW_SET_VLAN_6_MEMBER(vlan_member) \
++{ \
++ ((GSW_VLAN_MEMBER_PORT_MAP) &= (~(0x7 << 18))); \
++ ((GSW_VLAN_MEMBER_PORT_MAP) |= (((vlan_member) & 0x7) << 18)); \
++}
++
++#define GSW_SET_VLAN_7_MEMBER(vlan_member) \
++{ \
++ ((GSW_VLAN_MEMBER_PORT_MAP) &= (~(0x7 << 21))); \
++ ((GSW_VLAN_MEMBER_PORT_MAP) |= (((vlan_member) & 0x7) << 21)); \
++}
++
++#define GSW_SET_VLAN_0_TAG(vlan_tag) \
++{ \
++ ((GSW_VLAN_TAG_PORT_MAP) &= (~(0x7 << 0))); \
++ ((GSW_VLAN_TAG_PORT_MAP) |= (((vlan_tag) & 0x7) << 0)); \
++}
++
++#define GSW_SET_VLAN_1_TAG(vlan_tag) \
++{ \
++ ((GSW_VLAN_TAG_PORT_MAP) &= (~(0x7 << 3))); \
++ ((GSW_VLAN_TAG_PORT_MAP) |= (((vlan_tag) & 0x7) << 3)); \
++}
++
++#define GSW_SET_VLAN_2_TAG(vlan_tag) \
++{ \
++ ((GSW_VLAN_TAG_PORT_MAP) &= (~(0x7 << 6))); \
++ ((GSW_VLAN_TAG_PORT_MAP) |= (((vlan_tag) & 0x7) << 6)); \
++}
++
++#define GSW_SET_VLAN_3_TAG(vlan_tag) \
++{ \
++ ((GSW_VLAN_TAG_PORT_MAP) &= (~(0x7 << 9))); \
++ ((GSW_VLAN_TAG_PORT_MAP) |= (((vlan_tag) & 0x7) << 9)); \
++}
++
++#define GSW_SET_VLAN_4_TAG(vlan_tag) \
++{ \
++ ((GSW_VLAN_TAG_PORT_MAP) &= (~(0x7 << 12))); \
++ ((GSW_VLAN_TAG_PORT_MAP) |= (((vlan_tag) & 0x7) << 12)); \
++}
++
++#define GSW_SET_VLAN_5_TAG(vlan_tag) \
++{ \
++ ((GSW_VLAN_TAG_PORT_MAP) &= (~(0x7 << 15))); \
++ ((GSW_VLAN_TAG_PORT_MAP) |= (((vlan_tag) & 0x7) << 15)); \
++}
++
++#define GSW_SET_VLAN_6_TAG(vlan_tag) \
++{ \
++ ((GSW_VLAN_TAG_PORT_MAP) &= (~(0x7 << 18))); \
++ ((GSW_VLAN_TAG_PORT_MAP) |= (((vlan_tag) & 0x7) << 18)); \
++}
++
++#define GSW_SET_VLAN_7_TAG(vlan_tag) \
++{ \
++ ((GSW_VLAN_TAG_PORT_MAP) &= (~(0x7 << 21))); \
++ ((GSW_VLAN_TAG_PORT_MAP) |= (((vlan_tag) & 0x7) << 21)); \
++}
++
++#define GSW_SET_PPPOE_SESSION_0_ID(session_id) \
++{ \
++ ((GSW_PPPOE_SESSION_ID_0_1) &= (~(0xFFFF << 0))); \
++ ((GSW_PPPOE_SESSION_ID_0_1) |= (((session_id) & 0xFFFF) << 0)); \
++}
++
++#define GSW_SET_PPPOE_SESSION_1_ID(session_id) \
++{ \
++ ((GSW_PPPOE_SESSION_ID_0_1) &= (~(0xFFFF << 16))); \
++ ((GSW_PPPOE_SESSION_ID_0_1) |= (((session_id) & 0xFFFF) << 16)); \
++}
++
++#define GSW_SET_PPPOE_SESSION_2_ID(session_id) \
++{ \
++ ((GSW_PPPOE_SESSION_ID_2_3) &= (~(0xFFFF << 0))); \
++ ((GSW_PPPOE_SESSION_ID_2_3) |= (((session_id) & 0xFFFF) << 0)); \
++}
++
++#define GSW_SET_PPPOE_SESSION_3_ID(session_id) \
++{ \
++ ((GSW_PPPOE_SESSION_ID_2_3) &= (~(0xFFFF << 16))); \
++ ((GSW_PPPOE_SESSION_ID_2_3) |= (((session_id) & 0xFFFF) << 16)); \
++}
++
++#define GSW_SET_PPPOE_SESSION_4_ID(session_id) \
++{ \
++ ((GSW_PPPOE_SESSION_ID_4_5) &= (~(0xFFFF << 0))); \
++ ((GSW_PPPOE_SESSION_ID_4_5) |= (((session_id) & 0xFFFF) << 0)); \
++}
++
++#define GSW_SET_PPPOE_SESSION_5_ID(session_id) \
++{ \
++ ((GSW_PPPOE_SESSION_ID_4_5) &= (~(0xFFFF << 16))); \
++ ((GSW_PPPOE_SESSION_ID_4_5) |= (((session_id) & 0xFFFF) << 16)); \
++}
++
++#define GSW_SET_PPPOE_SESSION_6_ID(session_id) \
++{ \
++ ((GSW_PPPOE_SESSION_ID_6_7) &= (~(0xFFFF << 0))); \
++ ((GSW_PPPOE_SESSION_ID_6_7) |= (((session_id) & 0xFFFF) << 0)); \
++}
++
++#define GSW_SET_PPPOE_SESSION_7_ID(session_id) \
++{ \
++ ((GSW_PPPOE_SESSION_ID_6_7) &= (~(0xFFFF << 16))); \
++ ((GSW_PPPOE_SESSION_ID_6_7) |= (((session_id) & 0xFFFF) << 16)); \
++}
++
++#define GSW_READ_INTERRUPT_STATUS(int_status) \
++ ((int_status) = (GSW_INTERRUPT_STATUS))
++
++#define GSW_CLEAR_ALL_INTERRUPT_STATUS_SOURCES()\
++ ((GSW_INTERRUPT_STATUS) = (0x00001FFF))
++
++#define GSW_CLEAR_INTERRUPT_STATUS_SOURCES(source) \
++ ((GSW_INTERRUPT_STATUS) |= (source))
++
++#define GSW_CLEAR_INTERRUPT_STATUS_SOURCE_BIT(source_bit_index) \
++ ((GSW_INTERRUPT_STATUS) |= (1 << (source_bit_index)))
++
++#define GSW_DISABLE_ALL_INTERRUPT_STATUS_SOURCES() \
++ ((GSW_INTERRUPT_MASK) = (0x00001FFF))
++
++#define GSW_ENABLE_ALL_INTERRUPT_STATUS_SOURCES() \
++ ((GSW_INTERRUPT_MASK) = (0x00000000))
++
++#define GSW_DISABLE_INTERRUPT_STATUS_SOURCE_BIT(source_bit_index) \
++ ((GSW_INTERRUPT_MASK) |= (1 << (source_bit_index)))
++
++#define GSW_ENABLE_INTERRUPT_STATUS_SOURCE_BIT(source_bit_index) \
++ ((GSW_INTERRUPT_MASK) &= ~(1 << (source_bit_index)))
++
++#define GSW_TS_DMA_START() \
++ ((GSW_TS_DMA_CONTROL) = (1))
++
++#define GSW_TS_DMA_STOP() \
++ ((GSW_TS_DMA_CONTROL) = (0))
++
++#define GSW_READ_TS_DMA_STATE(state) \
++ ((state) = (GSW_TS_DMA_CONTROL))
++
++#define GSW_FS_DMA_START() \
++ ((GSW_FS_DMA_CONTROL) = (1))
++
++#define GSW_FS_DMA_STOP() \
++ ((GSW_FS_DMA_CONTROL) = (0))
++
++#define GSW_WRITE_TSSD(tssd_value) \
++ ((GSW_TS_DESCRIPTOR_POINTER) = (tssd_value))
++
++#define GSW_READ_TSSD(tssd_value) \
++ ((tssd_value) = (GSW_TS_DESCRIPTOR_POINTER))
++
++#define GSW_WRITE_FSSD(fssd_value) \
++ ((GSW_FS_DESCRIPTOR_POINTER) = (fssd_value))
++
++#define GSW_READ_FSSD(fssd_value) \
++ ((fssd_value) = (GSW_FS_DESCRIPTOR_POINTER))
++
++#define GSW_WRITE_TS_BASE(ts_base_value) \
++ ((GSW_TS_DESCRIPTOR_BASE_ADDR) = (ts_base_value))
++
++#define GSW_READ_TS_BASE(ts_base_value) \
++ ((ts_base_value) = (GSW_TS_DESCRIPTOR_BASE_ADDR))
++
++#define GSW_WRITE_FS_BASE(fs_base_value) \
++ ((GSW_FS_DESCRIPTOR_BASE_ADDR) = (fs_base_value))
++
++#define GSW_READ_FS_BASE(fs_base_value) \
++ ((fs_base_value) = (GSW_FS_DESCRIPTOR_BASE_ADDR))
++
++/*
++ * HNAT macros defines
++ */
++#define GSW_WRITE_HNAT_CONFIGURATION(hnat_config) \
++ ((GSW_HNAT_CONFIG) = (hnat_config))
++
++#define GSW_READ_HNAT_CONFIGURATION(hnat_config) \
++ ((hnat_config) = (GSW_HNAT_CONFIG))
++
++#define GSW_WRITE_PRIVATE_IP_BASE(ip_base) \
++ ((GSW_HNAT_PRIVATE_IP_BASE) = (ip_base & 0x000FFFFF))
++
++#define GSW_WRITE_HNAT_FW_RULE_START_INDEX(rule_start_index) \
++ ((GSW_HNAT_FW_RULE_START_ADDR) = (rule_start_index & 0x1FF))
++
++#define GSW_WRITE_HNAT_FW_RULE_END_INDEX(rule_end_index) \
++ ((GSW_HNAT_FW_RULE_END_ADDR) = (rule_end_index & 0x1FF))
++
++#define GSW_READ_HNAT_FW_RULE_START_INDEX(rule_start_index) \
++ ((rule_start_index) = ((GSW_HNAT_FW_RULE_START_ADDR) & 0x1FF))
++
++#define GSW_READ_HNAT_FW_RULE_END_INDEX(rule_end_index) \
++ ((rule_end_index) = ((GSW_HNAT_FW_RULE_END_ADDR) & 0x1FF))
++
++#define GSW_WRITE_HNAT_FL_RULE_START_INDEX(rule_start_index) \
++ ((GSW_HNAT_FL_RULE_START_ADDR) = (rule_start_index & 0x1FF))
++
++#define GSW_WRITE_HNAT_FL_RULE_END_INDEX(rule_end_index) \
++ ((GSW_HNAT_FL_RULE_END_ADDR) = (rule_end_index & 0x1FF))
++
++#define GSW_READ_HNAT_FL_RULE_START_INDEX(rule_start_index) \
++ ((rule_start_index) = ((GSW_HNAT_FL_RULE_START_ADDR) & 0x1FF))
++
++#define GSW_READ_HNAT_FL_RULE_END_INDEX(rule_end_index) \
++ ((rule_end_index) = ((GSW_HNAT_FL_RULE_END_ADDR) & 0x1FF))
++
++#define GSW_WRITE_HNAT_ALG_START_INDEX(rule_start_index) \
++ ((GSW_HNAT_ALG_START_ADDR) = (rule_start_index & 0x1FF))
++
++#define GSW_WRITE_HNAT_ALG_END_INDEX(rule_end_index) \
++ ((GSW_HNAT_ALG_END_ADDR) = (rule_end_index & 0x1FF))
++
++#define GSW_READ_HNAT_ALG_START_INDEX(rule_start_index) \
++ ((rule_start_index) = ((GSW_HNAT_ALG_START_ADDR) & 0x1FF))
++
++#define GSW_READ_HNAT_ALG_END_INDEX(rule_end_index) \
++ ((rule_end_index) = ((GSW_HNAT_ALG_END_ADDR) & 0x1FF))
++
++#define GSW_WRITE_HNAT_SIP_START_INDEX(rule_start_index) \
++ ((GSW_HNAT_SIP_BASE_ADDR) = (rule_start_index & 0x1FF))
++
++#define GSW_READ_HNAT_SIP_START_INDEX(rule_start_index) \
++ ((rule_start_index) = ((GSW_HNAT_SIP_BASE_ADDR) & 0x1FF))
++
++#define GSW_WRITE_HNAT_NAPT_BASE_ADDR(base_addr) \
++ ((GSW_HNAT_NAPT_BASE_ADDR) = (base_addr))
++
++#define GSW_READ_HNAT_NAPT_BASE_ADDR(base_addr) \
++ ((base_addr) = (GSW_HNAT_NAPT_BASE_ADDR))
++
++#define GSW_WRITE_HNAT_NAPT_PORT_BASE(port_base) \
++ ((GSW_HNAT_NAPT_PORT_BASE) = (port_base & 0xFFFF))
++
++#define GSW_WRITE_HNAT_ARP_BASE_ADDR(base_addr) \
++ ((GSW_HNAT_ARP_BASE_ADDR) = (base_addr))
++
++#define GSW_READ_HNAT_ARP_BASE_ADDR(base_addr) \
++ ((base_addr) = (GSW_HNAT_ARP_BASE_ADDR))
++
++//---------------------------------------------------
++// STAR9100 INTC macro define
++//---------------------------------------------------
++/*
++ * macro declarations
++ */
++#define INTC_ENABLE_INTERRUPT_SOURCE(source_bit_index) \
++ (INTC_INTERRUPT_MASK) &= (~(1 << source_bit_index))
++
++#define INTC_DISABLE_INTERRUPT_SOURCE(source_bit_index) \
++ (INTC_INTERRUPT_MASK) |= ((1 << source_bit_index))
++
++#define INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(source_bit_index) \
++ (INTC_INTERRUPT_CLEAR_EDGE_TRIGGER) |= ((1 << source_bit_index))
++
++#define INTC_SET_INTERRUPT_EDGE_TRIGGER(source_bit_index) \
++ (INTC_INTERRUPT_TRIGGER_MODE) |= ((1 << source_bit_index))
++
++#define INTC_SET_INTERRUPT_LEVEL_TRIGGER(source_bit_index) \
++ (INTC_INTERRUPT_TRIGGER_MODE) &= (~(1 << source_bit_index))
++
++#define INTC_SET_INTERRUPT_RISING_EDGE_TRIGGER(source_bit_index) \
++ (INTC_INTERRUPT_TRIGGER_LEVEL) &= (~(1 << source_bit_index))
++
++#define INTC_SET_INTERRUPT_FALLING_EDGE_TRIGGER(source_bit_index) \
++ (INTC_INTERRUPT_TRIGGER_LEVEL) |= ((1 << source_bit_index))
++
++#define INTC_SET_INTERRUPT_ACTIVE_HIGH_LEVEL_TRIGGER(source_bit_index) \
++ (INTC_INTERRUPT_TRIGGER_LEVEL) &= (~(1 << source_bit_index))
++
++#define INTC_SET_INTERRUPT_ACTIVE_LOW_LEVEL_TRIGGER(source_bit_index) \
++ (INTC_INTERRUPT_TRIGGER_LEVEL) |= ((1 << source_bit_index))
++
++#define INTC_ASSIGN_INTERRUPT_TO_IRQ(source_bit_index) \
++ (INTC_FIQ_MODE_SELECT) &= (~(1 << source_bit_index))
++
++#define INTC_ASSIGN_INTERRUPT_TO_FIQ(source_bit_index) \
++ (INTC_FIQ_MODE_SELECT) |= ((1 << source_bit_index))
++
++/*-------------------------------------------------*/
++// PHY define
++/*-------------------------------------------------*/
++#define PHY_CONTROL_REG_ADDR 0x00
++#define PHY_STATUA_REG_ADDR 0x01
++#define PHY_ID1_REG_ADDR 0x02
++#define PHY_ID2_REG_ADDR 0x03
++#define PHY_AN_ADVERTISEMENT_REG_ADDR 0x04
++#define PHY_AN_REAMOTE_CAP_REG_ADDR 0x05
++#define PHY_RESERVED1_REG_ADDR 0x10
++#define PHY_RESERVED2_REG_ADDR 0x11
++#define PHY_CH_STATUS_OUTPUT_REG_ADDR 0x12
++#define PHY_RESERVED3_REG_ADDR 0x13
++#define PHY_RESERVED4_REG_ADDR 0x14
++
++#define PHY_LSI_L84225_ID1 0x0016
++#define PHY_LSI_L84225_ID2 0xF840 // 0xF870????
++
++//--------------------------------------------------------
++// STAR9100 Hnat related define
++//--------------------------------------------------------
++/*Define for status print for Inerrrupt Status Register */
++#define INT_PORT0_Q_FULL BIT(0)
++#define INT_PORT1_Q_FULL BIT(1)
++#define INT_CPU_Q_FULL BIT(2)
++#define INT_HNAT_Q_FULL BIT(3)
++#define INT_GLOBAL_Q_FULL BIT(4)
++#define INT_BUFFER_FULL BIT(5)
++#define INT_PORT_STATUS_CHG BIT(6)
++#define INT_INTRUDER0 BIT(7)
++#define INT_INTRUDER1 BIT(8)
++#define INT_CPU_HOLD BIT(9)
++#define INT_PORT0_UNKNOWN_VLAN BIT(10)
++#define INT_PORT1_UNKNOWN_VLAN BIT(11)
++#define INT_CPU_UNKNOWN_VLAN BIT(12)
++#define INT_PORT0_NO_LINK_DROP BIT(16)
++#define INT_PORT0_BCS_DROP BIT(17)
++#define INT_PORT0_RX_CRC_DROP BIT(18)
++#define INT_PORT0_JAMED_DROP BIT(19)
++#define INT_PORT0_QUEUE_DROP BIT(20)
++#define INT_PORT0_RMC_DROP BIT(21)
++#define INT_PORT0_LOCAL_DROP BIT(22)
++#define INT_PORT0_INGRESS_DROP BIT(23)
++#define INT_PORT1_NO_LINK_DROP BIT(24)
++#define INT_PORT1_BCS_DROP BIT(25)
++#define INT_PORT1_RX_CRC_DROP BIT(26)
++#define INT_PORT1_JAMED_DROP BIT(27)
++#define INT_PORT1_QUEUE_DROP BIT(28)
++#define INT_PORT1_RMC_DROP BIT(29)
++#define PORT1_LOCAL_DROP BIT(30)
++#define PORT1_INGRESS_DROP 0x80000000
++
++#define MAX_VLAN_NUM (8)
++#define MAX_PORT_NUM (3) /* including port 0, port 1, and CPU port */
++
++typedef struct _vlan_config_ {
++ u32 vlan_gid; /* 3-bit VLAN group ID */
++ u32 vlan_vid; /* 12-bit VLAN ID */
++ u32 vlan_group; /* 3-bit VLAN group port map */
++ u32 vlan_tag_flag; /* 3-bit VLAN tag port map */
++ u8 vlan_mac[6];
++ u8 pad[2];
++} vlan_config_t;
++
++typedef struct _port_config_ {
++ u32 pvid; /* 3-bit Port PVID */
++ u32 config_flag;
++ u32 status_flag;
++} port_config_t;
++
++typedef struct _gsw_info_ {
++ vlan_config_t vlan[MAX_VLAN_NUM];
++ port_config_t port[MAX_PORT_NUM];
++} gsw_info_t;
++
++/* store this information for the driver.. */
++struct star_gsw_private {
++ struct net_device_stats stats;
++ spinlock_t lock;
++ /* Note:
++ * device entry pmap = 0 means local loopback network interface
++ * device entry pmap = 1 means GSW port 0 for LAN port network interface
++ * device entry pmap = 2 means GSW port 1 for WAN port network interface
++ * device entry pmap = 4 means GSW cpu port
++ */
++ int pmap;
++ struct napi_struct napi;
++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
++ struct vlan_group *vlgrp;
++#endif
++
++};
++
++#define __REG(reg) (*(u32 volatile *)(reg))
++
++/*
++ * Network Driver, Receive/Send and Initial Buffer Function
++ */
++typedef struct {
++ // 1st 32Bits
++ u32 data_ptr;
++
++ // 2nd 32Bits
++ u32 length:16;
++ u32 tco:1;
++ u32 uco:1;
++ u32 ico:1;
++ u32 pmap:3;
++ u32 fr:1;
++ u32 pri:3;
++ u32 fp:1;
++ u32 interrupt:1;
++ u32 ls:1;
++ u32 fs:1;
++ u32 eor:1;
++ u32 cown:1;
++
++ // 3rd 32Bits
++ u32 vid:3;
++ u32 insv:1;
++ u32 sid:3;
++ u32 inss:1;
++ u32 unused:24;
++
++ // 4th 32Bits
++ u32 unused2;
++
++} __attribute__((packed)) STAR_GSW_TXDESC;
++
++typedef struct {
++ // 1st 32Bits
++ u32 data_ptr;
++
++ // 2nd 32Bits
++ u32 length:16;
++ u32 l4f:1;
++ u32 ipf:1;
++ u32 prot:2;
++ u32 hr:6;
++ u32 sp:2;
++ u32 ls:1;
++ u32 fs:1;
++ u32 eor:1;
++ u32 cown:1;
++
++ // 3rd 32Bits
++ u32 unused;
++
++ // 4th 32Bits
++ u32 unused2;
++
++} __attribute__((packed)) STAR_GSW_RXDESC;
++
++/*
++ * Transmit Frame Descriptor Ring for TFDS
++ */
++
++typedef struct {
++ u32 phy_addr;
++ STAR_GSW_TXDESC *vir_addr;
++ unsigned int cur_index; // TX's current will point to Free Descriptors
++ struct sk_buff *skb_ptr[STAR_GSW_MAX_TFD_NUM]; // TX's sk_buff ptr
++#if defined(FREE_TX_SKB_MULTI) || defined(STAR_GSW_TIMER)
++ u32 to_free_index;
++#endif
++
++} TXRING_INFO;
++/*
++ * Receive Frame Descriptor Ring for RFDS
++ */
++
++typedef struct {
++ u32 phy_addr;
++ STAR_GSW_RXDESC *vir_addr;
++ u32 cur_index;
++ struct sk_buff *skb_ptr[STAR_GSW_MAX_RFD_NUM]; // RX's sk_buff ptr
++} RXRING_INFO;
++
++extern void str9100_set_interrupt_trigger(unsigned int, unsigned int, unsigned int);
++
++/*
++ * data structure defines
++ */
++typedef struct _gsw_arl_table_entry_
++{
++ u32 filter;
++ u32 vlan_mac;
++ u32 vlan_gid;
++ u32 age_field;
++ u32 port_map;
++ u8 mac_addr[6];
++ u8 pad[2];
++
++} gsw_arl_table_entry_t;
++
++#endif
++
+diff -rupN linux-2.6.35.11/drivers/net/str9100/star_gsw_phy.c linux-2.6.35.11-ts7500/drivers/net/str9100/star_gsw_phy.c
+--- linux-2.6.35.11/drivers/net/str9100/star_gsw_phy.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/str9100/star_gsw_phy.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,1224 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include "star_gsw_phy.h"
++#include "star_gsw.h"
++#include "star_gsw_config.h"
++
++
++#if 0
++void init_switch()
++{
++ u32 sw_config;
++
++ PDEBUG("init_switch\n");
++ /*
++ * Configure GSW configuration
++ */
++ sw_config = GSW_SWITCH_CONFIG;
++
++#if 0
++ // orignal virgon configuration
++ // enable fast aging
++ sw_config |= (0xF);
++
++ // CRC stripping
++ sw_config |= (0x1 << 21);
++
++ // IVL learning
++ sw_config |= (0x1 << 22);
++
++ // HNAT disable
++ sw_config &= ~(0x1 << 23);
++
++ GSW_SWITCH_CONFIG = sw_config;
++
++ sw_config = GSW_SWITCH_CONFIG;
++#endif
++
++ /* configure switch */
++ sw_config = GSW_SWITCH_CONFIG;
++
++ sw_config &= ~0xF; /* disable aging */
++ sw_config |= 0x1; /* disable aging */
++
++#ifdef JUMBO_ENABLE
++
++ // CRC stripping and GSW_CFG_MAX_LEN_JMBO
++ sw_config |= (GSW_CFG_CRC_STRP | GSW_CFG_MAX_LEN_JMBO);
++#else
++ // CRC stripping and 1536 bytes
++ sw_config |= (GSW_CFG_CRC_STRP | GSW_CFG_MAX_LEN_1536);
++#endif
++
++ /* IVL */
++ sw_config |= GSW_CFG_IVL;
++
++ /* disable HNAT */
++ sw_config &= ~GSW_CFG_HNAT_EN;
++
++ GSW_SWITCH_CONFIG = sw_config;
++}
++#endif
++
++
++
++
++
++
++// add by descent 2006/07/05
++// for configure packet forward and rate control
++void init_packet_forward(int port)
++{
++ u32 mac_port_config;
++
++ PDEBUG("port%d configure\n", port);
++ if (port==0)
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;
++ if (port==1)
++ mac_port_config = GSW_MAC_PORT_1_CONFIG;
++ if (STR9100_GSW_BROADCAST_RATE_CONTROL)
++ mac_port_config |= (0x1 << 31); // STR9100_GSW_BROADCAST_RATE_CONTROLL on
++ else
++ mac_port_config &= (~(0x1 << 31)); // STR9100_GSW_BROADCAST_RATE_CONTROLL off
++
++ if (STR9100_GSW_MULTICAST_RATE_CONTROL)
++ mac_port_config |= (0x1 << 30); // STR9100_GSW_MULTICAST_RATE_CONTROLL on
++ else
++ mac_port_config &= (~(0x1 << 30)); // STR9100_GSW_MULTICAST_RATE_CONTROLL off
++
++ if (STR9100_GSW_UNKNOW_PACKET_RATE_CONTROL)
++ mac_port_config |= (0x1 << 29); // STR9100_GSW_UNKNOW_PACKET_RATE_CONTROLL on
++ else
++ mac_port_config &= (~(0x1 << 29)); // STR9100_GSW_UNKNOW_PACKET_RATE_CONTROLL off
++
++
++ if (STR9100_GSW_DISABLE_FORWARDING_BROADCAST_PACKET)
++ mac_port_config |= (0x1 << 27); // STR9100_GSW_DISABLE_FORWARDING_BROADCAST_PACKET on
++ else
++ mac_port_config &= (~(0x1 << 27)); // STR9100_GSW_DISABLE_FORWARDING_BROADCAST_PACKET off
++
++ if(STR9100_GSW_DISABLE_FORWARDING_MULTICAST_PACKET)
++ {
++ mac_port_config |= (0x1 << 26); // STR9100_GSW_DISABLE_FORWARDING_MULTICAST_PACKET on
++ PDEBUG("STR9100_GSW_DISABLE_FORWARDING_MULTICAST_PACKET on\n");
++ }
++ else
++ {
++ mac_port_config &= (~(0x1 << 26)); // STR9100_GSW_DISABLE_FORWARDING_MULTICAST_PACKET off
++ PDEBUG("STR9100_GSW_DISABLE_FORWARDING_MULTICAST_PACKET off\n");
++ }
++
++ if(STR9100_GSW_DISABLE_FORWARDING_UNKNOW_PACKET)
++ mac_port_config |= (0x1 << 25); // STR9100_GSW_DISABLE_FORWARDING_UNKNOW_PACKET on
++ else
++ mac_port_config &= (~(0x1 << 25)); // STR9100_GSW_DISABLE_FORWARDING_UNKNOW_PACKET off
++
++ //GSW_MAC_PORT_0_CONFIG = mac_port_config;
++ if (port==0)
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;
++ if (port==1)
++ GSW_MAC_PORT_1_CONFIG = mac_port_config;
++}
++
++static int star_gsw_set_phy_addr(u8 mac_port, u8 phy_addr)
++{
++ u32 status = 0; /* for failure indication */
++
++ if ((mac_port > 1) || (phy_addr > 31)) {
++ return status;
++ }
++
++ if (mac_port == 0) {
++ GSW_PORT_MIRROR &= ~(0x3 << 0); /* clear bit[1:0] for PHY_ADDR[1:0] */
++ GSW_PORT_MIRROR &= ~(0x3 << 4); /* clear bit[5:4] for PHY_ADDR[3:2] */
++ GSW_QUEUE_STATUS_TEST_1 &= ~(0x1 << 25); /* clear bit[25] for PHY_ADDR[4] */
++ GSW_PORT_MIRROR |= (((phy_addr >> 0) & 0x3) << 0);
++ GSW_PORT_MIRROR |= (((phy_addr >> 2) & 0x3) << 4);
++ GSW_QUEUE_STATUS_TEST_1 |= (((phy_addr >> 4) & 0x1) << 25);
++ status = 1; /* for ok indication */
++ } else if (mac_port == 1) {
++ GSW_PORT_MIRROR &= ~(0x1 << 6); /* clear bit[6] for PHY_ADDR[0] */
++ GSW_PORT_MIRROR &= ~(0x7 << 8); /* clear bit[10:8] for PHY_ADDR[3:1] */
++ GSW_QUEUE_STATUS_TEST_1 &= ~(0x1 << 26); /* clear bit[26] for PHY_ADDR[4] */
++ GSW_PORT_MIRROR |= (((phy_addr >> 0) & 0x1) << 6);
++ GSW_PORT_MIRROR |= (((phy_addr >> 1) & 0x7) << 8);
++ GSW_QUEUE_STATUS_TEST_1 |= (((phy_addr >> 4) & 0x1) << 26);
++ status = 1; /* for ok indication */
++ }
++
++ return status;
++}
++
++static int star_gsw_read_phy(u8 phy_addr, u8 phy_reg, u16 *read_data)
++{
++ u32 status;
++ int i;
++
++ // clear previous rw_ok status
++ GSW_PHY_CONTROL = (0x1 << 15);
++
++ // 20061013 descent
++ // for ORION EOC
++ GSW_QUEUE_STATUS_TEST_1 &= ~( 0XF << 16);
++
++ GSW_PHY_CONTROL &= ~(0x1<<0);
++
++ GSW_QUEUE_STATUS_TEST_1 |= (((phy_addr >> 1) & 0xF) << 16);
++ // 20061013 descent end
++
++
++ GSW_PHY_CONTROL = ((phy_addr & 0x1) | ((phy_reg & 0x1F) << 8) | (0x1 << 14));
++
++ for (i = 0; i < 0x1000; i++) {
++ status = GSW_PHY_CONTROL;
++ if (status & (0x1 << 15)) {
++ // clear the rw_ok status, and clear other bits value
++ GSW_PHY_CONTROL = (0x1 << 15);
++ *read_data = (u16) ((status >> 16) & 0xFFFF);
++ return (1);
++ } else {
++ udelay(10);
++ }
++ }
++
++ return (0);
++}
++
++static int star_gsw_write_phy(u8 phy_addr, u8 phy_reg, u16 write_data)
++{
++ int i;
++
++ // clear previous rw_ok status
++ GSW_PHY_CONTROL = (0x1 << 15);
++
++ // 20061013 descent
++ // for ORION EOC
++ GSW_QUEUE_STATUS_TEST_1 &= ~( 0XF << 16);
++
++ GSW_PHY_CONTROL &= ~(0x1<<0);
++
++ GSW_QUEUE_STATUS_TEST_1 |= (((phy_addr >> 1) & 0xF) << 16);
++ // 20061013 descent end
++
++
++ GSW_PHY_CONTROL = ((phy_addr & 0x1) |
++ ((phy_reg & 0x1F) << 8) |
++ (0x1 << 13) | ((write_data & 0xFFFF) << 16));
++
++ for (i = 0; i < 0x1000; i++) {
++ if ((GSW_PHY_CONTROL) & (0x1 << 15)) {
++ // clear the rw_ok status, and clear other bits value
++ GSW_PHY_CONTROL = (0x1 << 15);
++ return (1);
++ } else {
++ udelay(10);
++ }
++ }
++
++ return (0);
++}
++
++#ifdef DORADO2_PCI_FASTPATH_MAC_PORT1_LOOPBACK
++static int star_gsw_config_mac_port1_loopback(void)
++{
++ u32 mac_port_base;
++ u32 mac_port_config;
++ int i;
++
++ PRINT_INFO("\nconfigure mac port1 loopback\n");
++
++ mac_port_base = GSW_PORT1_CFG_REG;
++
++ mac_port_config = __REG(mac_port_base);
++
++ // disable PHY's AN
++ mac_port_config &= ~(0x1 << 7);
++
++ // enable RGMII-PHY mode
++ mac_port_config |= (0x1 << 15);
++
++ // reversed RGMII mode
++ mac_port_config |= (0x1 << 14);
++
++ // enable GSW MAC port 0
++ mac_port_config &= ~(0x1 << 18);
++
++ __REG(mac_port_base) = mac_port_config;
++
++ // SA learning disable
++ mac_port_config |= (0x1 << 19);
++
++ // disable TX flow control
++ mac_port_config &= ~(0x1 << 12);
++
++ // disable RX flow control
++ mac_port_config &= ~(0x1 << 11);
++
++ // force duplex
++ mac_port_config |= (0x1 << 10);
++
++ // force speed at 1000Mbps
++ mac_port_config &= ~(0x3 << 8);
++ mac_port_config |= (0x2 << 8);
++
++ __REG(mac_port_base) = mac_port_config;
++
++ // adjust MAC port 1 RX/TX clock skew
++ GSW_BIST_RESULT_TEST_0 &= ~((0x3 << 28) | (0x3 << 30));
++ //GSW_BIST_RESULT_TEST_0 |= ((0x2 << 28) | (0x2 << 30));
++ GSW_BIST_RESULT_TEST_0 |= (0x2 << 30);
++
++ return 0;
++}
++#endif
++
++int VSC8201_phy_power_down(int phy_addr, int y)
++{
++ u16 phy_data = 0;
++ // power-down or up the PHY
++ star_gsw_read_phy(phy_addr, 0, &phy_data);
++ if (y==1) // down
++ phy_data |= (0x1 << 11);
++ if (y==0) // up
++ phy_data |= (~(0x1 << 11));
++ star_gsw_write_phy(phy_addr, 0, phy_data);
++ return 0;
++
++}
++
++static int star_gsw_config_VSC8201(u8 mac_port, u8 phy_addr) // include cicada 8201
++{
++ u32 mac_port_base = 0;
++ u32 mac_port_config;
++ u16 phy_reg;
++ int i;
++
++ PRINT_INFO("\nconfigure VSC8201\n");
++ PDEBUG("mac port : %d phy addr : %d\n", mac_port, phy_addr);
++ /*
++ * Configure MAC port 0
++ * For Cicada CIS8201 single PHY
++ */
++ if (mac_port == 0) {
++ PDEBUG("port 0\n");
++ mac_port_base = GSW_PORT0_CFG_REG;
++ }
++ if (mac_port == 1) {
++ PDEBUG("port 1\n");
++ mac_port_base = GSW_PORT1_CFG_REG;
++ }
++
++ star_gsw_set_phy_addr(mac_port, phy_addr);
++ //star_gsw_set_phy_addr(1, 1);
++
++ mac_port_config = __REG(mac_port_base);
++
++ // enable PHY's AN
++ mac_port_config |= (0x1 << 7);
++
++ // enable RGMII-PHY mode
++ mac_port_config |= (0x1 << 15);
++
++ // enable GSW MAC port 0
++ mac_port_config &= ~(0x1 << 18);
++
++ __REG(mac_port_base)= mac_port_config;
++
++ /*
++ * Configure Cicada's CIS8201 single PHY
++ */
++ /* 2007.04.24 Richard.Liu Marked, we don't need VSC8201 lookback mode */
++#if 0
++#ifdef CONFIG_STAR9100_SHNAT_PCI_FASTPATH
++ /* near-end loopback mode */
++ star_gsw_read_phy(phy_addr, 0x0, &phy_reg);
++ phy_reg |= (0x1 << 14);
++ star_gsw_write_phy(phy_addr, 0x0, phy_reg);
++#endif
++#endif
++
++ star_gsw_read_phy(phy_addr, 0x1C, &phy_reg);
++
++ // configure SMI registers have higher priority over MODE/FRC_DPLX, and ANEG_DIS pins
++ phy_reg |= (0x1 << 2);
++
++ star_gsw_write_phy(phy_addr, 0x1C, phy_reg);
++
++ star_gsw_read_phy(phy_addr, 0x17, &phy_reg);
++
++ // enable RGMII MAC interface mode
++ phy_reg &= ~(0xF << 12);
++ phy_reg |= (0x1 << 12);
++
++ // enable RGMII I/O pins operating from 2.5V supply
++ phy_reg &= ~(0x7 << 9);
++ phy_reg |= (0x1 << 9);
++
++ star_gsw_write_phy(phy_addr, 0x17, phy_reg);
++
++ star_gsw_read_phy(phy_addr, 0x4, &phy_reg);
++
++ // Enable symmetric Pause capable
++ phy_reg |= (0x1 << 10);
++
++ star_gsw_write_phy(phy_addr, 0x4, phy_reg);
++
++ mac_port_config = __REG(mac_port_base);
++
++ /* 2007.04.24 Richard.Liu Marked, we don't need VSC8201 lookback mode */
++//#ifdef CONFIG_STAR9100_SHNAT_PCI_FASTPATH
++#if 0
++ // near-end loopback mode, must disable AN
++ mac_port_config &= ~(0x1 << 7);
++
++ // SA learning disable
++ mac_port_config |= (0x1 << 19);
++
++ // disable TX flow control
++ mac_port_config &= ~(0x1 << 12);
++
++ // disable RX flow control
++ mac_port_config &= ~(0x1 << 11);
++
++ // force duplex
++ mac_port_config |= (0x1 << 10);
++
++ // force speed at 1000Mpbs
++ mac_port_config &= ~(0x3 << 8);
++ mac_port_config |= (0x2 << 8);
++#else
++ // enable PHY's AN
++ mac_port_config |= (0x1 << 7);
++#endif
++
++ __REG(mac_port_base) = mac_port_config;
++
++ /*
++ * Enable PHY1 AN restart bit to restart PHY1 AN
++ */
++ star_gsw_read_phy(phy_addr, 0x0, &phy_reg);
++
++ phy_reg |= (0x1 << 9) | (0x1 << 12);
++
++ star_gsw_write_phy(phy_addr, 0x0, phy_reg);
++
++ /*
++ * Polling until PHY0 AN restart is complete
++ */
++ for (i = 0; i < 0x1000; i++) {
++ star_gsw_read_phy(phy_addr, 0x1, &phy_reg);
++
++ if ((phy_reg & (0x1 << 5)) && (phy_reg & (0x1 << 2))) {
++ printk("0x1 phy reg: %x\n", phy_reg);
++ break;
++ } else {
++ udelay(100);
++ }
++ }
++
++ mac_port_config = __REG(mac_port_base);
++
++ if (((mac_port_config & 0x1) == 0) || (mac_port_config & 0x2)) {
++ printk("Check MAC/PHY%s Link Status : DOWN!\n", (mac_port == 0 ? "0" : "1"));
++ } else {
++ printk("Check MAC/PHY%s Link Status : UP!\n", (mac_port == 0 ? "0" : "1"));
++ /*
++ * There is a bug for CIS8201 PHY operating at 10H mode, and we use the following
++ * code segment to work-around
++ */
++ star_gsw_read_phy(phy_addr, 0x05, &phy_reg);
++
++ if ((phy_reg & (0x1 << 5)) && (!(phy_reg & (0x1 << 6))) && (!(phy_reg & (0x1 << 7))) && (!(phy_reg & (0x1 << 8)))) { /* 10H,10F/100F/100H off */
++ star_gsw_read_phy(phy_addr, 0x0a, &phy_reg);
++
++ if ((!(phy_reg & (0x1 << 10))) && (!(phy_reg & (0x1 << 11)))) { /* 1000F/1000H off */
++ star_gsw_read_phy(phy_addr, 0x16, &phy_reg);
++
++ phy_reg |= (0x1 << 13) | (0x1 << 15); // disable "Link integrity check(B13)" & "Echo mode(B15)"
++
++ star_gsw_write_phy(phy_addr, 0x16, phy_reg);
++ }
++ }
++ }
++
++ if (mac_port == 0) {
++ // adjust MAC port 0 RX/TX clock skew
++ GSW_BIST_RESULT_TEST_0 &= ~((0x3 << 24) | (0x3 << 26));
++ GSW_BIST_RESULT_TEST_0 |= ((0x2 << 24) | (0x2 << 26));
++ }
++
++ if (mac_port == 1) {
++ // adjust MAC port 1 RX/TX clock skew
++ GSW_BIST_RESULT_TEST_0 &= ~((0x3 << 28) | (0x3 << 30));
++ GSW_BIST_RESULT_TEST_0 |= ((0x2 << 28) | (0x2 << 30));
++ }
++
++ return 0;
++}
++
++// add by descent 2006/07/10
++// port : 0 => port0 ; port : 1 => port1
++// y = 1 ; disable AN
++int disable_AN(int port, int y)
++{
++ u32 mac_port_config;
++ if (port==0)
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;
++ if (port==1)
++ mac_port_config = GSW_MAC_PORT_1_CONFIG;
++ // disable PHY's AN
++ if (y==1)
++ {
++ PDEBUG("disable AN\n");
++ mac_port_config &= ~(0x1 << 7);
++ }
++
++ // enable PHY's AN
++ if (y==0)
++ {
++ PDEBUG("enable AN\n");
++ mac_port_config |= (0x1 << 7);
++ }
++
++ if (port==0)
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;
++ if (port==1)
++ GSW_MAC_PORT_1_CONFIG = mac_port_config;
++ return 0;
++}
++
++int disable_AN_VSC7385(int y)
++{
++ u32 mac_port_config;
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;
++
++ // disable PHY's AN
++ if (y==1)
++ {
++ PDEBUG("disable AN\n");
++ mac_port_config &= ~(0x1 << 7);
++ }
++
++ // enable PHY's AN
++ if (y==0)
++ {
++ PDEBUG("enable AN\n");
++ mac_port_config |= (0x1 << 7);
++ }
++
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;
++ return 0;
++}
++
++void star_gsw_config_VSC7385(void)
++{
++ u32 mac_port_config;
++
++
++ printk("\nconfigure VSC7385\n");
++ /*
++ * Configure GSW's MAC port 0
++ * For ASIX's 5-port GbE Switch setting
++ * 1. No SMI (MDC/MDIO) connection between Orion's MAC port 0 and ASIX's MAC port 4
++ * 2. Force Orion's MAC port 0 to be 1000Mbps, and full-duplex, and flow control on
++ */
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;
++
++
++ // enable RGMII-PHY mode
++ mac_port_config |= (0x1 << 15);
++
++ // force speed = 1000Mbps
++ mac_port_config &= ~(0x3 << 8);
++ mac_port_config |= (0x2 << 8);
++
++ // force full-duplex
++ mac_port_config |= (0x1 << 10);
++
++ // force Tx/Rx flow-control on
++ mac_port_config |= (0x1 << 11) | (0x1 << 12);
++
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;
++
++ udelay(1000);
++
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;
++
++ if (((mac_port_config & 0x1) == 0) || (mac_port_config & 0x2)) {
++ printk("Check MAC/PHY 0 Link Status : DOWN!\n");
++ } else {
++ printk("Check MAC/PHY 0 Link Status : UP!\n");
++ }
++
++ /* adjust MAC port 0 /RX/TX clock skew */
++ GSW_BIST_RESULT_TEST_0 &= ~((0x3 << 24) | (0x3 << 26));
++ GSW_BIST_RESULT_TEST_0 |= ((0x2 << 24) | (0x2 << 26));
++}
++
++
++
++void star_gsw_config_ASIX()
++{
++ u32 mac_port_config;
++
++ printk("configure port0 ASIX\n");
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;
++
++ //Disable AN
++ mac_port_config &= (~(0x1 << 7));
++
++ //force speed to 1000Mbps
++ mac_port_config &= (~(0x3 << 8));
++ mac_port_config |= (0x2 << 8); //jacky
++
++ //force tx and rx follow control
++ mac_port_config |= (0x1 << 11) | (0x1 << 12);
++
++ //force full deplex
++ mac_port_config |= 0x1 << 10;
++
++ //RGMII ENABLR
++ mac_port_config |= 0x1 << 15;
++
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;
++
++ udelay(1000);
++
++ /* adjust MAC port 0 RX/TX clock skew */
++ GSW_BIST_RESULT_TEST_0 &= ~((0x3 << 24) | (0x3 << 26));
++ GSW_BIST_RESULT_TEST_0 |= ((0x2 << 24) | (0x2 << 26));
++
++ // configure MAC port 0 pad drive strength = 10/100 mode
++ *(u32 volatile *) (0xf770001C) |= (0x1 << 2);
++}
++
++
++
++// agere power down/up
++int AGERE_phy_power_down(int phy_addr, int y)
++{
++ u16 phy_data = 0;
++ // power-down or up the PHY
++ star_gsw_read_phy(phy_addr, 0, &phy_data);
++ if (y==1) // down
++ phy_data |= (0x1 << 11);
++ if (y==0) // up
++ phy_data &= (~(0x1 << 11));
++ star_gsw_write_phy(phy_addr, 0, phy_data);
++ return 0;
++}
++
++// add by descent 2006/07/31
++// standard phy register 0 and offset is 11 is power down
++int std_phy_power_down(int phy_addr, int y)
++{
++ u16 phy_data = 0;
++ // power-down or up the PHY
++ star_gsw_read_phy(phy_addr, 0, &phy_data);
++ if (y==1) // down
++ phy_data |= (0x1 << 11);
++ if (y==0) // up
++ phy_data &= (~(0x1 << 11));
++ star_gsw_write_phy(phy_addr, 0, phy_data);
++ return 0;
++}
++
++
++/*
++ * AGERE PHY is attached to MAC PORT 1
++ * with phy_addr 1
++ */
++void star_gsw_config_AGERE()
++{
++ u32 mac_port_config;
++ u16 phy_data = 0;
++ int i;
++
++ printk("configure port1 AGERE\n");
++
++ /*
++ * Configure MAC port 1
++ * For Agere Systems's ET1011 single PHY
++ */
++ mac_port_config = GSW_MAC_PORT_1_CONFIG;
++
++ // disable PHY's AN
++ mac_port_config &= ~(0x1 << 7);
++
++ // enable RGMII-PHY mode
++ mac_port_config |= (0x1 << 15);
++
++ GSW_MAC_PORT_1_CONFIG = mac_port_config;
++
++#if 1
++ /*
++ * configure Agere's ET1011 Single PHY
++ */
++ /* Configure Agere's ET1011 by Agere's programming note */
++ //1. power-down the PHY
++ star_gsw_read_phy(1, 0, &phy_data);
++ phy_data |= (0x1 << 11);
++ star_gsw_write_phy(1, 0, phy_data);
++
++ //2. Enable PHY programming mode
++ star_gsw_read_phy(1, 18, &phy_data);
++ phy_data |= (0x1 << 0);
++ phy_data |= (0x1 << 2);
++ star_gsw_write_phy(1, 18, phy_data);
++
++ //3.Perform some PHY register with the Agere-specfic value
++ star_gsw_write_phy(1, 16, 0x880e);
++ star_gsw_write_phy(1, 17, 0xb4d3);
++
++ star_gsw_write_phy(1, 16, 0x880f);
++ star_gsw_write_phy(1, 17, 0xb4d3);
++
++ star_gsw_write_phy(1, 16, 0x8810);
++ star_gsw_write_phy(1, 17, 0xb4d3);
++
++ star_gsw_write_phy(1, 16, 0x8817);
++ star_gsw_write_phy(1, 17, 0x1c00);
++
++ star_gsw_write_phy(1, 16, 0x8805);
++ star_gsw_write_phy(1, 17, 0xb03e);
++
++ star_gsw_write_phy(1, 16, 0x8806);
++ star_gsw_write_phy(1, 17, 0xb03e);
++
++ star_gsw_write_phy(1, 16, 0x8807);
++ star_gsw_write_phy(1, 17, 0xff00);
++
++ star_gsw_write_phy(1, 16, 0x8808);
++ star_gsw_write_phy(1, 17, 0xe110);
++
++ star_gsw_write_phy(1, 16, 0x300d);
++ star_gsw_write_phy(1, 17, 0x0001);
++
++ //4. Disable PHY programming mode
++ star_gsw_read_phy(1, 18, &phy_data);
++ phy_data &= ~(0x1 << 0);
++ phy_data &= ~(0x1 << 2);
++ star_gsw_write_phy(1, 18, phy_data);
++
++ //5. power-up the PHY
++ star_gsw_read_phy(1, 0, &phy_data);
++ phy_data &= ~(0x1 << 11);
++ star_gsw_write_phy(1, 0, phy_data);
++
++ star_gsw_read_phy(1, 22, &phy_data);
++
++ // enable RGMII MAC interface mode : RGMII/RMII (dll delay or trace delay) mode
++ phy_data &= ~(0x7 << 0);
++
++ // phy_data |= (0x6 << 0); // RGMII/RMII dll delay mode : not work!!
++ phy_data |= (0x4 << 0); // RGMII/RMII trace delay mode
++
++ star_gsw_write_phy(1, 22, phy_data);
++#endif
++
++ mac_port_config = GSW_MAC_PORT_1_CONFIG;
++
++ // enable PHY's AN
++ mac_port_config |= (0x1 << 7);
++
++ GSW_MAC_PORT_1_CONFIG = mac_port_config;
++
++ /*
++ * Enable flow-control on (Symmetric PAUSE frame)
++ */
++ star_gsw_read_phy(1, 0x4, &phy_data);
++
++ phy_data |= (0x1 << 10);
++
++ star_gsw_write_phy(1, 0x4, phy_data);
++
++ /*
++ * Enable PHY1 AN restart bit to restart PHY1 AN
++ */
++ star_gsw_read_phy(1, 0x0, &phy_data);
++
++ phy_data |= (0x1 << 9) | (0x1 << 12);
++
++ star_gsw_write_phy(1, 0x0, phy_data);
++
++ /*
++ * Polling until PHY1 AN restart is complete and PHY1 link status is UP
++ */
++ for (i = 0; i < 0x2000; i++) {
++ star_gsw_read_phy(1, 0x1, &phy_data);
++ if ((phy_data & (0x1 << 5)) && (phy_data & (0x1 << 2))) {
++ break;
++ }
++ }
++
++ // adjust MAC port 1 RX/TX clock skew
++ GSW_BIST_RESULT_TEST_0 &= ~((0x3 << 28) | (0x3 << 30));
++ GSW_BIST_RESULT_TEST_0 |= ((0x2 << 28) | (0x3 << 30));
++
++ udelay(100);
++
++ mac_port_config = GSW_MAC_PORT_1_CONFIG;
++ if (!(mac_port_config & 0x1) || (mac_port_config & 0x2)) {
++ /*
++ * Port 1 PHY link down or no TXC in Port 1
++ */
++ PDEBUG("PHY1: Link Down, 0x%08x!\n", mac_port_config);
++ return;
++ }
++
++}
++
++
++
++int str9100_gsw_config_mac_port0()
++{
++ PDEBUG("str9100_gsw_config_mac_port0\n");
++ INIT_PORT0_PHY
++ INIT_PORT0_MAC
++ PORT0_LINK_DOWN
++ return 0;
++}
++
++int str9100_gsw_config_mac_port1()
++{
++ INIT_PORT1_PHY
++ INIT_PORT1_MAC
++ PORT1_LINK_DOWN
++ //PORT1_LINK_UP
++ return 0;
++}
++
++
++#define PHY_CONTROL_REG_ADDR 0x00
++#define PHY_AN_ADVERTISEMENT_REG_ADDR 0x04
++
++
++int icp_101a_init (int port)
++{
++ u32 mac_port_config;
++ u16 phy_data = 0;
++
++
++ PRINT_INFO("init IC+101A\n");
++
++ if (port == 0) // port 0
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;
++ if (port == 1) // port 1
++ mac_port_config = GSW_MAC_PORT_1_CONFIG;
++
++ if (!(mac_port_config & (0x1 << 5))) {
++ if (!star_gsw_read_phy (port, PHY_AN_ADVERTISEMENT_REG_ADDR, &phy_data))
++ {
++ PDEBUG("\n PORT%d, enable local flow control capability Fail\n", port);
++ return (1);
++ }
++ else
++ {
++ // enable PAUSE frame capability
++ phy_data |= (0x1 << 10);
++
++ if (!star_gsw_write_phy (port, PHY_AN_ADVERTISEMENT_REG_ADDR, phy_data))
++ {
++ PDEBUG("\nPORT%d, enable PAUSE frame capability Fail\n", port);
++ return (1);
++ }
++ }
++ }
++
++
++ // restart PHY0 AN
++ if (!star_gsw_read_phy (port, PHY_CONTROL_REG_ADDR, &phy_data)) {
++ PDEBUG ("\n restart PHY%d AN Fail \n", port);
++ return (1);
++ }
++ else {
++ // enable PHY0 AN restart
++ phy_data |= (0x1 << 9);
++
++ if (!star_gsw_write_phy (port, PHY_CONTROL_REG_ADDR, phy_data)) {
++ PDEBUG ("\n enable PHY0 AN restart \n");
++ return (1);
++ }
++ }
++
++
++
++ while (1)
++ {
++ PDEBUG ("\n Polling PHY%d AN \n", port);
++ star_gsw_read_phy (port, PHY_CONTROL_REG_ADDR, &phy_data);
++
++ if (phy_data & (0x1 << 9)) {
++ continue;
++ }
++ else {
++ PDEBUG ("\n PHY%d AN restart is complete \n", port);
++ break;
++ }
++ }
++
++ return 0;
++}
++
++#ifdef CONFIG_LIBRA
++void icp_175c_all_phy_power_down(int y)
++{
++ int i=0;
++
++ for (i=0 ; i < 5 ; ++i)
++ std_phy_power_down(i, y);
++
++}
++
++#define CONFIG_PORT0_5
++
++void configure_icplus_175c_phy(void)
++{
++ u32 volatile II, jj;
++ u32 volatile mac_port_config;
++ u16 volatile reg;
++ u32 volatile reg2;
++ int i=0;
++
++ //star_gsw_set_phy_addr(0, 0);
++ //star_gsw_set_phy_addr(1, 1);
++
++ printk("\n ICPLUS175C_PHY,enable PORT0 local flow control capability \n");
++ /* adjust MAC port 0 /RX/TX clock skew */
++ GSW_BIST_RESULT_TEST_0 &= ~((0x3 << 24) | (0x3 << 26));
++ GSW_BIST_RESULT_TEST_0 |= ((0x2 << 24) | (0x2 << 26));
++
++// 20061117 descent
++ // auto polling default phy address is 0
++ // so set phy address to not exist address to avoid auto polling
++ // in STAR library board if no these code, port 0 link state will get half duplex
++ // port 1-4 get full duplex
++ if (star_gsw_set_phy_addr(0, 15))
++ printk ("star_gsw_set_phy_addr(0,2) is successful\n");
++ else
++ printk ("star_gsw_set_phy_addr(0,2) is fail\n");
++
++ if (star_gsw_set_phy_addr(1, 16))
++ printk ("star_gsw_set_phy_addr(1,3) is successful\n");
++ else
++ printk ("star_gsw_set_phy_addr(1,3) is fail\n");
++
++
++
++ #if 0
++ // for PHY_AN_ADVERTISEMENT_REG_ADDR
++ // in this case needn't this code, only for reference
++ star_gsw_read_phy(i, 4, &phy_data);
++ phy_data |= (0x1 << 10); // Enable PAUSE frame capability of PHY 0
++ phy_data |= (0x1 << 5) | (0x1 << 6) | (0x1 << 7) | (0x1 << 8);
++ star_gsw_write_phy(i, 4, phy_data);
++ star_gsw_read_phy(i, 0, &phy_data);
++ phy_data |= (0x1 << 9) | (0x1 << 12); // Enable AN and Restart-AN
++ star_gsw_write_phy(i, 0, phy_data);
++ #endif
++// 20061117 descent end
++
++
++#if 0
++ for (i=0 ; i < 10; ++i)
++ {
++ star_gsw_read_phy(i, 2, ®);
++ printk("addr: %d, phyid: %x\n", i, reg);
++ }
++
++
++
++
++ /*
++ * Configure GSW's MAC port 0
++ * For ASIX's 5-port GbE Switch setting
++ * 1. No SMI (MDC/MDIO) connection between Orion's MAC port 0 and ASIX's MAC port 4
++ * 2. Force Orion's MAC port 0 to be 1000Mbps, and full-duplex, and flow control on
++ */
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;
++
++
++
++ // enable RGMII-PHY mode
++ mac_port_config &= ~(0x1 << 15);
++
++ // force speed = 100Mbps
++ mac_port_config &= ~(0x3 << 8);
++ mac_port_config |= (0x1 << 8);
++
++ // force full-duplex
++ mac_port_config |= (0x1 << 10);
++
++ // force Tx/Rx flow-control on
++ mac_port_config |= (0x1 << 11) | (0x1 << 12);
++
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;
++ star_gsw_write_phy(29, 31, 0x175C);
++ //star_gsw_write_phy(30, 9, 0x1089);
++ star_gsw_write_phy(29, 23, 0x2);
++
++ star_gsw_write_phy(29, 24, 0x2);
++ star_gsw_write_phy(29, 25, 0x1);
++ star_gsw_write_phy(29, 26, 0x1);
++ star_gsw_write_phy(29, 27, 0x1);
++ star_gsw_write_phy(29, 28, 0x1);
++ star_gsw_write_phy(29, 29, 0x2);
++
++ star_gsw_write_phy(30, 1, (0x3e << 8) );
++ star_gsw_write_phy(30, 2, 0x21);
++ star_gsw_write_phy(30, 9, 0x80);
++
++ udelay(1000);
++
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;
++
++ if (((mac_port_config & 0x1) == 0) || (mac_port_config & 0x2)) {
++ printk("Check MAC/PHY 0 Link Status : DOWN!\n");
++ } else {
++ printk("Check MAC/PHY 0 Link Status : UP!\n");
++ }
++
++ /* adjust MAC port 0 /RX/TX clock skew */
++ GSW_BIST_RESULT_TEST_0 &= ~((0x3 << 24) | (0x3 << 26));
++ GSW_BIST_RESULT_TEST_0 |= ((0x2 << 24) | (0x2 << 26));
++
++
++#endif
++
++
++
++#if 1
++
++
++#if 1
++ reg2 = __REG(PWR_PAD_DRV_REG);
++ PDEBUG("[PWR_PAD_DRV_REG = %x]\n", reg2);
++ reg2 = reg2 | 0x4;
++
++ __REG(PWR_PAD_DRV_REG) = reg2;
++
++ reg2 = __REG(PWR_PAD_DRV_REG);
++ PDEBUG("[PWR_PAD_DRV_REG = %x]\n", reg2);
++#endif
++
++ star_gsw_write_phy(29, 31, 0x175C);
++
++
++ star_gsw_read_phy(0, 2, ®);
++ PDEBUG("[0,%d,%x]\n", 2, reg);
++ star_gsw_read_phy(29, 31, ®);
++ PDEBUG("[29,%d,%x]\n", 31, reg);
++
++ star_gsw_write_phy(29, 23, 0x7C2);
++ star_gsw_write_phy(29, 24, 0x1);
++ star_gsw_write_phy(29, 25, 0x1);
++ star_gsw_write_phy(29, 26, 0x1);
++
++#ifdef CONFIG_PORT0_5
++ star_gsw_write_phy(29, 27, 0x1);
++#else
++ star_gsw_write_phy(29, 27, 0x2);
++#endif
++ star_gsw_write_phy(29, 28, 0x2);
++ star_gsw_write_phy(29, 30, 0x2);
++
++#ifdef CONFIG_PORT0_5
++ printk("CONFIG_PORT0_5\n");
++ star_gsw_write_phy(30, 1, 0x2f00);
++ star_gsw_write_phy(30, 2, 0x30);
++#else // port0_4
++ printk("not CONFIG_PORT0_5\n");
++
++
++ //star_gsw_write_phy(30, 1, 0x2f00);
++ star_gsw_write_phy(30, 1, 0x2700);
++ //star_gsw_write_phy(30, 2, 0x30);
++ star_gsw_write_phy(30, 2, 0x38);
++
++#endif
++
++
++ star_gsw_write_phy(30, 9, 0x80);
++
++// 20061115 descent
++// If no these code,
++// in STAR libra board, will get crc drop
++ // configure port 4 (MII 0)
++ // configure port 4 (MII 0)
++
++ // P4_FORCE
++ star_gsw_read_phy(29, 22, ®);
++ reg |= (0x1 << 15);
++ star_gsw_write_phy(29, 22, reg);
++
++
++ // MAC_X_EN, flow control enable of MII0 and MII2
++ star_gsw_read_phy(29, 18, ®);
++ reg |= (0x1 << 10);
++ star_gsw_write_phy(29, 18, reg);
++
++
++ // P4_FORCE 100 Mbps
++ star_gsw_read_phy(29, 22, ®);
++ reg |= (0x1 << 10);
++ star_gsw_write_phy(29, 22, reg);
++
++
++ // P4_FORCE_FULL duplex
++ star_gsw_read_phy(29, 22, ®);
++ reg |= (0x1 << 5);
++ star_gsw_write_phy(29, 22, reg);
++
++// 20061115 descent end
++
++
++
++
++
++
++ #if 0
++ // enable flow control
++ star_gsw_read_phy(29, 18, ®);
++ reg |= (0x1 < 13);
++ star_gsw_write_phy(29, 18, reg);
++ star_gsw_read_phy(29, 18, ®);
++ printk("[29,%d,%x]\n", 18, reg);
++ #endif
++#if 0
++ //star_gsw_read_phy(29, 23, ®);
++ //reg = reg & 0xF800;
++ //reg = reg | 0x7C2;
++
++
++ star_gsw_write_phy(29, 24, 0x1);
++
++ star_gsw_read_phy(29, 24, ®);
++ PDEBUG("[ 29, 24, %x]\n", reg);
++
++ star_gsw_write_phy(29, 25, 0x2);
++ udelay(1000);
++
++ star_gsw_read_phy(29, 25, ®);
++ PDEBUG("[ 29, 25, %x]\n", reg);
++
++ star_gsw_write_phy(29, 26, 0x1);
++ star_gsw_write_phy(29, 27, 0x1);
++ star_gsw_write_phy(29, 28, 0x1);
++ star_gsw_write_phy(29, 30, 0x2);
++
++ // tag vlan mask
++
++ star_gsw_write_phy(30, 1, 0x3F3D);
++
++ star_gsw_write_phy(30, 2, 0x3F22);
++ star_gsw_write_phy(30, 9, 0x1089);
++ // star_gsw_write_phy(30, 1, 0x3D22);
++ // star_gsw_write_phy(30, 9, 0x028A);
++#endif
++
++#if 0
++
++ for(II=18;II<=30;II++)
++ {
++ star_gsw_read_phy(29, II, ®);
++ PDEBUG("[29,%d,%x]\n", II, reg);
++ }
++
++ for(II=1;II<=10;II++)
++ {
++ star_gsw_read_phy(30, II, ®);
++ PDEBUG("[30,%d,%x]\n", II, reg);
++ }
++
++#endif
++
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;
++
++ // disable PHY's AN
++ mac_port_config &= ~(0x1 << 7);
++
++ // disable RGMII-PHY mode
++ mac_port_config &= ~(0x1 << 15);
++
++ // force speed = 100Mbps
++ mac_port_config &= ~(0x3 << 8);
++ mac_port_config |= (0x1 << 8);
++
++ // force full-duplex
++ mac_port_config |= (0x1 << 10);
++
++ // force Tx/Rx flow-control on
++ mac_port_config |= (0x1 << 11) | (0x1 << 12);
++
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;
++
++
++#if 0
++ for (II = 0; II < 0x2000; II++)
++ {
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;
++
++ if ((mac_port_config & 0x1) && !(mac_port_config & 0x2))
++ {
++
++ /* enable MAC port 0
++ */
++ mac_port_config &= ~(0x1 << 18);
++
++
++ /*
++ * enable the forwarding of unknown, multicast and broadcast packets to CPU
++ */
++ mac_port_config &= ~((0x1 << 25) | (0x1 << 26) | (0x1 << 27));
++
++ /*
++ * include unknown, multicast and broadcast packets into broadcast storm
++ */
++ mac_port_config |= ((0x1 << 29) | (0x1 << 30) | ((u32)0x1 << 31));
++ // mac_port_config |= ( (0x1 << 30) | ((u32)0x1 << 31));
++
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;
++
++ break;
++ }
++ }
++#endif
++
++ if (!(mac_port_config & 0x1) || (mac_port_config & 0x2))
++ {
++ /*
++ * Port 0 PHY link down or no TXC in Port 0
++ */
++ printk("\rCheck MAC/PHY 0 Link Status : DOWN!\n");
++
++ }
++ else
++ {
++ printk("\rCheck MAC/PHY 0 Link Status : UP!\n");
++ }
++#endif
++
++ //printk("Found ICPLUS175C_PHY\n");
++}
++#endif
+diff -rupN linux-2.6.35.11/drivers/net/str9100/star_gsw_phy.h linux-2.6.35.11-ts7500/drivers/net/str9100/star_gsw_phy.h
+--- linux-2.6.35.11/drivers/net/str9100/star_gsw_phy.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/str9100/star_gsw_phy.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,160 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef __STAR_GSW_PHY_H__
++#define __STAR_GSW_PHY_H__
++
++#include <linux/version.h>
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,32)
++#define LINUX24 1
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++#define LINUX26 1
++#endif
++
++#include <linux/types.h>
++
++
++//#define CONFIG_VIRGO
++//#define CONFIG_DORADO
++//#define CONFIG_DORADO2
++//#define CONFIG_LEO
++//#undef CONFIG_VIRGO
++//#undef CONFIG_DORADO
++//#undef CONFIG_DORADO2
++//#undef CONFIG_LEO
++
++#ifdef CONFIG_LIBRA
++#include "libra.h"
++#endif
++
++#ifdef CONFIG_VELA
++#include "vela.h"
++#endif
++
++#ifdef CONFIG_DORADO2
++#include "dorado2.h"
++#endif
++
++#ifdef CONFIG_DORADO
++#include "dorado.h"
++#endif
++
++#ifdef CONFIG_LEO
++#include "leo.h"
++#endif
++
++#ifdef CONFIG_VIRGO
++#include "virgo.h"
++#endif
++
++
++void star_gsw_config_ASIX(void);
++void star_gsw_config_AGERE(void);
++int AGERE_phy_power_down(int phy_addr, int y);
++int disable_AN_VSC7385(int y);
++void star_gsw_config_VSC7385(void);
++
++
++
++
++void star_gsw_config_AGERE(void);
++
++int str9100_gsw_config_mac_port0(void);
++int str9100_gsw_config_mac_port1(void);
++
++
++
++#define PORT0 (1 << 0) /* bit map : bit 0 */
++#define PORT1 (1 << 1) /* bit map : bit 1 */
++#define CPU_PORT (1 << 2) /* bit map : bit 2 */
++
++#define VLAN0_GROUP_ID (0)
++#define VLAN1_GROUP_ID (1)
++#define VLAN2_GROUP_ID (2)
++#define VLAN3_GROUP_ID (3)
++#define VLAN4_GROUP_ID (4)
++#define VLAN5_GROUP_ID (5)
++#define VLAN6_GROUP_ID (6)
++#define VLAN7_GROUP_ID (7)
++
++#define PORT0_PVID (VLAN1_GROUP_ID)
++#define PORT1_PVID (VLAN2_GROUP_ID)
++#define CPU_PORT_PVID (VLAN0_GROUP_ID)
++
++#define INVALID_PORT_BASE_PMAP_PORT -1
++
++
++#ifdef LINUX26
++#define GSW_MAC_PORT_0_CONFIG GSW_MAC_PORT_0_CONFIG_REG
++#define GSW_MAC_PORT_1_CONFIG GSW_MAC_PORT_1_CONFIG_REG
++#define GSW_PORT_MIRROR GSW_PORT_MIRROR_REG
++#define GSW_QUEUE_STATUS_TEST_1 GSW_QUEUE_STATUS_TEST_1_REG
++#define GSW_PHY_CONTROL GSW_PHY_CONTROL_REG
++#define GSW_BIST_RESULT_TEST_0 GSW_BIST_RESULT_TEST_0_REG
++#define GSW_PORT0_CFG_REG (SYSVA_GSW_BASE_ADDR + 0x08)
++#define GSW_PORT1_CFG_REG (SYSVA_GSW_BASE_ADDR + 0x0C)
++#define GSW_SWITCH_CONFIG GSW_SWITCH_CONFIG_REG
++#define GSW_ARL_TABLE_ACCESS_CONTROL_0 GSW_ARL_TABLE_ACCESS_CONTROL_0_REG
++#define GSW_ARL_TABLE_ACCESS_CONTROL_1 GSW_ARL_TABLE_ACCESS_CONTROL_1_REG
++#define GSW_ARL_TABLE_ACCESS_CONTROL_2 GSW_ARL_TABLE_ACCESS_CONTROL_2_REG
++#define GSW_VLAN_PORT_PVID GSW_VLAN_PORT_PVID_REG
++#define GSW_VLAN_VID_0_1 GSW_VLAN_VID_0_1_REG
++#define GSW_VLAN_VID_2_3 GSW_VLAN_VID_2_3_REG
++#define GSW_VLAN_VID_4_5 GSW_VLAN_VID_4_5_REG
++#define GSW_VLAN_VID_6_7 GSW_VLAN_VID_6_7_REG
++#define GSW_VLAN_MEMBER_PORT_MAP GSW_VLAN_MEMBER_PORT_MAP_REG
++#define GSW_VLAN_TAG_PORT_MAP GSW_VLAN_TAG_PORT_MAP_REG
++#define GSW_INTERRUPT_MASK GSW_INTERRUPT_MASK_REG
++#define GSW_INTERRUPT_STATUS GSW_INTERRUPT_STATUS_REG
++#define INTC_INTERRUPT_CLEAR_EDGE_TRIGGER INTC_INTERRUPT_CLEAR_EDGE_TRIGGER_REG
++#define GSW_TS_DMA_CONTROL GSW_TS_DMA_CONTROL_REG
++#define GSW_FS_DMA_CONTROL GSW_FS_DMA_CONTROL_REG
++#define GSW_TS_DESCRIPTOR_POINTER GSW_TS_DESCRIPTOR_POINTER_REG
++#define GSW_TS_DESCRIPTOR_BASE_ADDR GSW_TS_DESCRIPTOR_BASE_ADDR_REG
++#define GSW_FS_DESCRIPTOR_POINTER GSW_FS_DESCRIPTOR_POINTER_REG
++#define GSW_FS_DESCRIPTOR_BASE_ADDR GSW_FS_DESCRIPTOR_BASE_ADDR_REG
++#define GSW_CPU_PORT_CONFIG GSW_CPU_PORT_CONFIG_REG
++#define INTC_INTERRUPT_MASK INTC_INTERRUPT_MASK_REG
++#define GSW_DELAYED_INTERRUPT_CONFIG GSW_DELAYED_INTERRUPT_CONFIG_REG
++#define GSW_HNAT_SOURCE_MAC_0_HIGH GSW_HNAT_SOURCE_MAC_0_HIGH_REG
++#define GSW_HNAT_SOURCE_MAC_0_LOW GSW_HNAT_SOURCE_MAC_0_LOW_REG
++#define GSW_HNAT_SOURCE_MAC_1_HIGH GSW_HNAT_SOURCE_MAC_1_HIGH_REG
++#define GSW_HNAT_SOURCE_MAC_1_LOW GSW_HNAT_SOURCE_MAC_1_LOW_REG
++#define GSW_HNAT_SOURCE_MAC_2_HIGH GSW_HNAT_SOURCE_MAC_2_HIGH_REG
++#define GSW_HNAT_SOURCE_MAC_2_LOW GSW_HNAT_SOURCE_MAC_2_LOW_REG
++#define GSW_HNAT_SOURCE_MAC_3_HIGH GSW_HNAT_SOURCE_MAC_3_HIGH_REG
++#define GSW_HNAT_SOURCE_MAC_3_LOW GSW_HNAT_SOURCE_MAC_3_LOW_REG
++#define GSW_HNAT_SOURCE_MAC_4_HIGH GSW_HNAT_SOURCE_MAC_4_HIGH_REG
++#define GSW_HNAT_SOURCE_MAC_4_LOW GSW_HNAT_SOURCE_MAC_4_LOW_REG
++#define GSW_HNAT_SOURCE_MAC_5_HIGH GSW_HNAT_SOURCE_MAC_5_HIGH_REG
++#define GSW_HNAT_SOURCE_MAC_5_LOW GSW_HNAT_SOURCE_MAC_5_LOW_REG
++#define GSW_HNAT_SOURCE_MAC_6_HIGH GSW_HNAT_SOURCE_MAC_6_HIGH_REG
++#define GSW_HNAT_SOURCE_MAC_6_LOW GSW_HNAT_SOURCE_MAC_6_LOW_REG
++#define GSW_HNAT_SOURCE_MAC_7_HIGH GSW_HNAT_SOURCE_MAC_7_HIGH_REG
++#define GSW_HNAT_SOURCE_MAC_7_LOW GSW_HNAT_SOURCE_MAC_7_LOW_REG
++#define PWRMGT_SOFTWARE_RESET_CONTROL PWRMGT_SOFTWARE_RESET_CONTROL_REG
++
++#endif
++
++#endif /* __STAR_GSW_PHY_H__ */
+diff -rupN linux-2.6.35.11/drivers/net/str9100/vela.h linux-2.6.35.11-ts7500/drivers/net/str9100/vela.h
+--- linux-2.6.35.11/drivers/net/str9100/vela.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/str9100/vela.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,167 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef VELA_H
++#define VELA_H
++
++// add by descent 2006/07/07
++#define VELA
++#ifdef VELA
++// init phy or switch chip
++#define INIT_PORT0_PHY icp_101a_init(0);
++#define INIT_PORT1_PHY icp_101a_init(1);
++
++// configure mac0/mac1 register
++#define INIT_PORT0_MAC init_packet_forward(0);
++#define INIT_PORT1_MAC init_packet_forward(1);
++
++#define PORT0_LINK_DOWN std_phy_power_down(0, 1);
++#define PORT0_LINK_UP std_phy_power_down(0, 0);
++
++#define PORT1_LINK_DOWN std_phy_power_down(1, 1);
++#define PORT1_LINK_UP std_phy_power_down(1, 0);
++
++#define CREATE_NET_DEV0 star_gsw_probe(LAN_PORT);
++#define CREATE_NET_DEV1 star_gsw_probe(WAN_PORT);
++#define CREATE_NET_DEV2
++
++
++#undef CONFIG_STR9100_VLAN_BASE
++#undef CONFIG_HAVE_VLAN_TAG
++
++#define CONFIG_STR9100_PORT_BASE
++// for port base, port base max is 2 port.
++// NET_DEV0 : rx->sp 0 (port 0)
++#define NET_DEV0 STAR_GSW_LAN_DEV
++// NET_DEV1 : rx->sp 1 (port 1)
++#define NET_DEV1 STAR_GSW_WAN_DEV
++
++// for star_gsw_send_packet
++// port base and vlan base packet flow
++#define PORT_BASE_PMAP_LAN_PORT PORT0
++#define PORT_BASE_PMAP_WAN_PORT PORT1
++#define PORT_BASE_PMAP_EWC_PORT INVALID_PORT_BASE_PMAP_PORT
++
++
++// OPEN_PORT include 2 actions
++// 1. enable mac port
++// 2. link up port
++#define OPEN_PORT(dev) \
++{ \
++ u32 mac_port_config; \
++ \
++ if (dev == STAR_GSW_LAN_DEV) { \
++ memcpy(dev->dev_addr, star_gsw_info.vlan[LAN_GID].vlan_mac, 6);\
++ PRINT_INFO("open mac port 0\n");\
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;\
++ /* enable port 0 */ \
++ mac_port_config &= (~(0x1 << 18));\
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;\
++ PORT0_LINK_UP\
++ } \
++ if(dev == STAR_GSW_WAN_DEV) { \
++ memcpy(dev->dev_addr, star_gsw_info.vlan[WAN_GID].vlan_mac, 6);\
++ PRINT_INFO("open mac port 1\n");\
++ mac_port_config = GSW_MAC_PORT_1_CONFIG;\
++ /* enable port 0 */ \
++ mac_port_config &= (~(0x1 << 18));\
++ GSW_MAC_PORT_1_CONFIG = mac_port_config;\
++ PORT1_LINK_UP\
++ } \
++}
++
++// CLOSE_PORT include 2 actions
++// 1. disable mac port
++// 2. link down port
++#define CLOSE_PORT(dev) \
++{ \
++ u32 mac_port_config; \
++ \
++ if (dev == STAR_GSW_LAN_DEV) { \
++ PRINT_INFO("close mac port 0\n");\
++ PORT0_LINK_DOWN\
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;\
++ /* disable port 0 */ \
++ mac_port_config |= ((0x1 << 18));\
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;\
++ } \
++ if(dev == STAR_GSW_WAN_DEV) { \
++ PRINT_INFO("close mac port 1\n");\
++ PORT1_LINK_DOWN\
++ mac_port_config = GSW_MAC_PORT_1_CONFIG;\
++ /* disable port 1 */ \
++ mac_port_config |= ((0x1 << 18));\
++ GSW_MAC_PORT_1_CONFIG = mac_port_config;\
++ } \
++}
++
++
++#define VLAN0_VID (0x111)
++#define VLAN1_VID (0x222)
++#define VLAN2_VID (0x333)
++#define VLAN3_VID (0x444)
++#define VLAN4_VID (0x555)
++#define VLAN5_VID (0x666)
++#define VLAN6_VID (0x777)
++#define VLAN7_VID (0x888)
++
++
++#define VLAN0_GROUP (PORT0 | PORT1 | CPU_PORT)
++#define VLAN1_GROUP (PORT0 | CPU_PORT)
++#define VLAN2_GROUP (PORT1 | CPU_PORT)
++#define VLAN3_GROUP (0)
++#define VLAN4_GROUP (0)
++#define VLAN5_GROUP (0)
++#define VLAN6_GROUP (0)
++#define VLAN7_GROUP (0)
++
++#define VLAN0_VLAN_TAG (0)
++#define VLAN1_VLAN_TAG (0)
++#define VLAN2_VLAN_TAG (0)
++#define VLAN3_VLAN_TAG (0)
++#define VLAN4_VLAN_TAG (0)
++#define VLAN5_VLAN_TAG (0)
++#define VLAN6_VLAN_TAG (0)
++#define VLAN7_VLAN_TAG (0)
++
++//#define PORT0_PVID (VLAN0_GROUP_ID)
++//#define PORT1_PVID (VLAN2_GROUP_ID)
++//#define CPU_PORT_PVID (VLAN1_GROUP_ID)
++
++static u8 my_vlan0_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xcc, 0x11};
++static u8 my_vlan1_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xcc, 0x21};
++static u8 my_vlan2_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xcc, 0x31};
++static u8 my_vlan3_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xcc, 0x41};
++
++// this value is for hnat
++// GID is vlan group id
++#define LAN_GID 1
++#define WAN_GID 2
++
++
++#define MODEL "VELA"
++
++#endif // VELA
++
++#endif
++
+diff -rupN linux-2.6.35.11/drivers/net/str9100/virgo.h linux-2.6.35.11-ts7500/drivers/net/str9100/virgo.h
+--- linux-2.6.35.11/drivers/net/str9100/virgo.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/net/str9100/virgo.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,167 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef VIRGO_H
++#define VIRGO_H
++
++// add by descent 2006/07/07
++#define VIRGO
++#ifdef VIRGO
++// init phy or switch chip
++#define INIT_PORT0_PHY star_gsw_config_ASIX();
++#define INIT_PORT1_PHY star_gsw_config_AGERE();
++
++// configure mac0/mac1 register
++#define INIT_PORT0_MAC init_packet_forward(0);
++#define INIT_PORT1_MAC init_packet_forward(1);
++
++#define PORT0_LINK_DOWN disable_AN_VSC7385(0);
++#define PORT0_LINK_UP disable_AN_VSC7385(1);
++
++#define PORT1_LINK_DOWN AGERE_phy_power_down(1,1);
++#define PORT1_LINK_UP AGERE_phy_power_down(1,0);
++
++#define CREATE_NET_DEV0 star_gsw_probe(LAN_PORT);
++#define CREATE_NET_DEV1 star_gsw_probe(WAN_PORT);
++#define CREATE_NET_DEV2
++
++
++#undef CONFIG_STR9100_VLAN_BASE
++#undef CONFIG_HAVE_VLAN_TAG
++
++#define CONFIG_STR9100_PORT_BASE
++// for port base, port base max is 2 port.
++// NET_DEV0 : rx->sp 0 (port 0)
++#define NET_DEV0 STAR_GSW_LAN_DEV
++// NET_DEV1 : rx->sp 1 (port 1)
++#define NET_DEV1 STAR_GSW_WAN_DEV
++
++// for star_gsw_send_packet
++// port base and vlan base packet flow
++#define PORT_BASE_PMAP_LAN_PORT PORT0
++#define PORT_BASE_PMAP_WAN_PORT PORT1
++#define PORT_BASE_PMAP_EWC_PORT INVALID_PORT_BASE_PMAP_PORT
++
++#define MODEL "VIRGO"
++
++// OPEN_PORT include 2 actions
++// 1. enable mac port
++// 2. link up port
++#define OPEN_PORT(dev) \
++{ \
++ u32 mac_port_config; \
++ \
++ if (dev == STAR_GSW_LAN_DEV) { \
++ memcpy(dev->dev_addr, star_gsw_info.vlan[LAN_GID].vlan_mac, 6);\
++ PRINT_INFO("open mac port 0\n");\
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;\
++ /* enable port 0 */ \
++ mac_port_config &= (~(0x1 << 18));\
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;\
++ PORT0_LINK_UP\
++ } \
++ if(dev == STAR_GSW_WAN_DEV) { \
++ memcpy(dev->dev_addr, star_gsw_info.vlan[WAN_GID].vlan_mac, 6);\
++ PRINT_INFO("open mac port 1\n");\
++ mac_port_config = GSW_MAC_PORT_1_CONFIG;\
++ /* enable port 0 */ \
++ mac_port_config &= (~(0x1 << 18));\
++ GSW_MAC_PORT_1_CONFIG = mac_port_config;\
++ PORT1_LINK_UP\
++ } \
++}
++
++// CLOSE_PORT include 2 actions
++// 1. disable mac port
++// 2. link down port
++#define CLOSE_PORT(dev) \
++{ \
++ u32 mac_port_config; \
++ \
++ if (dev == STAR_GSW_LAN_DEV) { \
++ PRINT_INFO("close mac port 0\n");\
++ PORT0_LINK_DOWN\
++ mac_port_config = GSW_MAC_PORT_0_CONFIG;\
++ /* disable port 0 */ \
++ mac_port_config |= ((0x1 << 18));\
++ GSW_MAC_PORT_0_CONFIG = mac_port_config;\
++ } \
++ if(dev == STAR_GSW_WAN_DEV) { \
++ PRINT_INFO("close mac port 1\n");\
++ PORT1_LINK_DOWN\
++ mac_port_config = GSW_MAC_PORT_1_CONFIG;\
++ /* disable port 1 */ \
++ mac_port_config |= ((0x1 << 18));\
++ GSW_MAC_PORT_1_CONFIG = mac_port_config;\
++ } \
++}
++
++
++#define VLAN0_VID (0x111)
++#define VLAN1_VID (0x222)
++#define VLAN2_VID (0x333)
++#define VLAN3_VID (0x444)
++#define VLAN4_VID (0x555)
++#define VLAN5_VID (0x666)
++#define VLAN6_VID (0x777)
++#define VLAN7_VID (0x888)
++
++
++#define VLAN0_GROUP (PORT0 | PORT1 | CPU_PORT)
++#define VLAN1_GROUP (PORT0 | CPU_PORT)
++#define VLAN2_GROUP (PORT1 | CPU_PORT)
++#define VLAN3_GROUP (0)
++#define VLAN4_GROUP (0)
++#define VLAN5_GROUP (0)
++#define VLAN6_GROUP (0)
++#define VLAN7_GROUP (0)
++
++#define VLAN0_VLAN_TAG (0)
++#define VLAN1_VLAN_TAG (0)
++#define VLAN2_VLAN_TAG (0)
++#define VLAN3_VLAN_TAG (0)
++#define VLAN4_VLAN_TAG (0)
++#define VLAN5_VLAN_TAG (0)
++#define VLAN6_VLAN_TAG (0)
++#define VLAN7_VLAN_TAG (0)
++
++//#define PORT0_PVID (VLAN0_GROUP_ID)
++//#define PORT1_PVID (VLAN2_GROUP_ID)
++//#define CPU_PORT_PVID (VLAN1_GROUP_ID)
++
++static u8 my_vlan0_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x11};
++static u8 my_vlan1_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x21};
++static u8 my_vlan2_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x31};
++static u8 my_vlan3_mac[6] = {0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0x41};
++
++// this value is for hnat
++// GID is vlan group id
++#define LAN_GID 1
++#define WAN_GID 2
++
++
++
++#endif // VIRGO
++
++#endif
++
+diff -rupN linux-2.6.35.11/drivers/pci/setup-bus.c linux-2.6.35.11-ts7500/drivers/pci/setup-bus.c
+--- linux-2.6.35.11/drivers/pci/setup-bus.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/pci/setup-bus.c 2011-03-14 11:18:24.000000000 -0400
+@@ -76,6 +76,21 @@ static void __dev_sort_resources(struct
+ {
+ u16 class = dev->class >> 8;
+
++#if defined(CONFIG_ARCH_STR9100) || defined(CONFIG_ARCH_STR8100)
++ {
++ u16 cmd;
++
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ cmd |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x8); //configure cache line size
++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40); //configure latency timer
++ }
++
++ if (dev->vendor == 0xeeee)
++ return;
++#endif
++
+ /* Don't touch classless devices or host bridges or ioapics. */
+ if (class == PCI_CLASS_NOT_DEFINED || class == PCI_CLASS_BRIDGE_HOST)
+ return;
+diff -rupN linux-2.6.35.11/drivers/serial/8250.c linux-2.6.35.11-ts7500/drivers/serial/8250.c
+--- linux-2.6.35.11/drivers/serial/8250.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/serial/8250.c 2011-03-14 11:18:24.000000000 -0400
+@@ -45,6 +45,16 @@
+
+ #include "8250.h"
+
++#ifdef CONFIG_SERIAL_8250_CTSRTS
++#include <asm/arch/star_gpio.h>
++extern int __init_or_module gpio_direction_input(unsigned int);
++extern int __init_or_module gpio_direction_output(unsigned int, unsigned int);
++extern void gpio_set_value(unsigned int, unsigned int);
++extern int gpio_get_value(unsigned int);
++unsigned int gpio_cts = 0;
++unsigned int gpio_rts;
++#endif
++
+ #ifdef CONFIG_SPARC
+ #include "suncore.h"
+ #endif
+@@ -622,6 +632,7 @@ static void serial_icr_write(struct uart
+ serial_out(up, UART_ICR, value);
+ }
+
++#if !defined(CONFIG_ARCH_STR9100) && !defined(CONFIG_ARCH_STR8100)
+ static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
+ {
+ unsigned int value;
+@@ -633,6 +644,7 @@ static unsigned int serial_icr_read(stru
+
+ return value;
+ }
++#endif
+
+ /*
+ * FIFO support.
+@@ -738,6 +750,13 @@ static void disable_rsa(struct uart_8250
+ }
+ #endif /* CONFIG_SERIAL_8250_RSA */
+
++#if defined(CONFIG_ARCH_STR9100) || defined(CONFIG_ARCH_STR8100)
++static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
++{
++ up->port.type = PORT_16550A;
++ return;
++}
++#else
+ /*
+ * This is a quickie test to see how big the FIFO is.
+ * It doesn't work at all the time, more's the pity.
+@@ -1253,6 +1272,7 @@ static void autoconfig(struct uart_8250_
+ spin_unlock_irqrestore(&up->port.lock, flags);
+ DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
+ }
++#endif
+
+ static void autoconfig_irq(struct uart_8250_port *up)
+ {
+@@ -1447,6 +1467,15 @@ receive_chars(struct uart_8250_port *up,
+ ignore_char:
+ lsr = serial_inp(up, UART_LSR);
+ } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
++
++#ifdef CONFIG_SERIAL_8250_CTSRTS
++ if (gpio_rts)
++ {
++ gpio_set_value(CONFIG_GPIO_RTS,0); /* assert RTS */
++ gpio_rts = 0;
++ }
++#endif
++
+ spin_unlock(&up->port.lock);
+ tty_flip_buffer_push(tty);
+ spin_lock(&up->port.lock);
+@@ -1465,6 +1494,10 @@ static void transmit_chars(struct uart_8
+ return;
+ }
+ if (uart_tx_stopped(&up->port)) {
++#ifdef CONFIG_SERIAL_8250_CTSRTS
++ if (gpio_cts)
++ return;
++#endif
+ serial8250_stop_tx(&up->port);
+ return;
+ }
+@@ -1495,6 +1528,22 @@ static unsigned int check_modem_status(s
+ {
+ unsigned int status = serial_in(up, UART_MSR);
+
++#ifdef CONFIG_SERIAL_8250_CTSRTS
++ unsigned int gpio_new_cts = gpio_get_value(CONFIG_GPIO_CTS);
++
++ if (!gpio_new_cts)
++ status |= UART_MSR_CTS; /* Assert CTS */
++ else
++ status &= ~UART_MSR_CTS; /* Deassert CTS */
++
++ /* CTS pin has been changed */
++ if (gpio_new_cts != gpio_cts)
++ {
++ status |= UART_MSR_DCTS;
++ gpio_cts = gpio_new_cts;
++ }
++#endif
++
+ status |= up->msr_saved_flags;
+ up->msr_saved_flags = 0;
+ if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
+@@ -1521,10 +1570,24 @@ static void serial8250_handle_port(struc
+ {
+ unsigned int status;
+ unsigned long flags;
++#ifdef CONFIG_SERIAL_8250_CTSRTS
++ unsigned int iir;
++#endif
+
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ status = serial_inp(up, UART_LSR);
++#ifdef CONFIG_SERIAL_8250_CTSRTS
++ iir = serial_in(up, UART_IIR);
++
++ if ((iir & 0x6) == 0x6)
++ printk("Overrun error!\n");
++ else if (iir & 0x4)
++ {
++ gpio_set_value(CONFIG_GPIO_RTS,1);
++ gpio_rts = 1;
++ }
++#endif
+
+ DEBUG_INTR("status = %x...", status);
+
+@@ -1819,7 +1882,19 @@ static void serial8250_set_mctrl(struct
+ unsigned char mcr = 0;
+
+ if (mctrl & TIOCM_RTS)
++#ifdef CONFIG_SERIAL_8250_CTSRTS
++ {
+ mcr |= UART_MCR_RTS;
++ gpio_set_value(CONFIG_GPIO_RTS,0); /* assert RTS */
++ }
++ else
++ {
++ mcr &= ~UART_MCR_RTS;
++ gpio_set_value(CONFIG_GPIO_RTS,1); /* deassert RTS */
++ }
++#else
++ mcr |= UART_MCR_RTS;
++#endif
+ if (mctrl & TIOCM_DTR)
+ mcr |= UART_MCR_DTR;
+ if (mctrl & TIOCM_OUT1)
+@@ -1938,6 +2013,9 @@ static int serial8250_startup(struct uar
+ {
+ struct uart_8250_port *up = (struct uart_8250_port *)port;
+ unsigned long flags;
++#if !defined(CONFIG_ARCH_STR9100) && !defined(CONFIG_ARCH_STR8100)
++ unsigned char lsr;
++#endif
+ unsigned char lsr, iir;
+ int retval;
+
+@@ -2107,6 +2185,7 @@ static int serial8250_startup(struct uar
+ if (skip_txen_test || up->port.flags & UPF_NO_TXEN_TEST)
+ goto dont_test_tx_en;
+
++#if !defined(CONFIG_ARCH_STR9100) && !defined(CONFIG_ARCH_STR8100)
+ /*
+ * Do a quick test to see if we receive an
+ * interrupt when we enable the TX irq.
+@@ -2125,6 +2204,7 @@ static int serial8250_startup(struct uar
+ } else {
+ up->bugs &= ~UART_BUG_TXEN;
+ }
++#endif
+
+ dont_test_tx_en:
+ spin_unlock_irqrestore(&up->port.lock, flags);
+@@ -2812,7 +2892,11 @@ serial8250_console_write(struct console
+ static int __init serial8250_console_setup(struct console *co, char *options)
+ {
+ struct uart_port *port;
++#if defined(CONFIG_ARCH_STR9100) || defined(CONFIG_ARCH_STR8100)
++ int baud = CONFIG_CONSOLE_BAUD_RATE;
++#else
+ int baud = 9600;
++#endif
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+@@ -3023,6 +3107,7 @@ static int __devexit serial8250_remove(s
+ return 0;
+ }
+
++#if !defined(CONFIG_ARCH_STR9100) && !defined(CONFIG_ARCH_STR8100)
+ static int serial8250_suspend(struct platform_device *dev, pm_message_t state)
+ {
+ int i;
+@@ -3050,12 +3135,15 @@ static int serial8250_resume(struct plat
+
+ return 0;
+ }
++#endif
+
+ static struct platform_driver serial8250_isa_driver = {
+ .probe = serial8250_probe,
+ .remove = __devexit_p(serial8250_remove),
++#if !defined(CONFIG_ARCH_STR9100) && !defined(CONFIG_ARCH_STR8100)
+ .suspend = serial8250_suspend,
+ .resume = serial8250_resume,
++#endif
+ .driver = {
+ .name = "serial8250",
+ .owner = THIS_MODULE,
+@@ -3197,6 +3285,31 @@ static int __init serial8250_init(void)
+ {
+ int ret;
+
++#ifdef CONFIG_SERIAL_8250_CTSRTS
++ /* enable GPIO pin function */
++ MISC_GPIOB_PIN_ENABLE_REG &= ~(1 << CONFIG_GPIO_CTS | 1 << CONFIG_GPIO_RTS | 1 << CONFIG_GPIO_DCD \
++ | 1<<CONFIG_GPIO_DTR | 1<<CONFIG_GPIO_DSR | 1<<CONFIG_GPIO_RI);
++
++ /* configure CTS pin (input) */
++ gpio_direction_input(CONFIG_GPIO_CTS);
++ gpio_cts = gpio_get_value(CONFIG_GPIO_CTS);
++
++ /* configure RTS pin (output) and set to high */
++ gpio_direction_output(CONFIG_GPIO_RTS,1);
++
++ /* configure DCD pin (input) */
++ gpio_direction_input(CONFIG_GPIO_DCD);
++
++ /* configure DTR pin (ouput) and set to low */
++ gpio_direction_output(CONFIG_GPIO_DTR,0);
++
++ /* configure DSR pin (input) */
++ gpio_direction_input(CONFIG_GPIO_DSR);
++
++ /* configure RI pin (input) */
++ gpio_direction_input(CONFIG_GPIO_RI);
++#endif
++
+ if (nr_uarts > UART_NR)
+ nr_uarts = UART_NR;
+
+diff -rupN linux-2.6.35.11/drivers/serial/8250.c.orig linux-2.6.35.11-ts7500/drivers/serial/8250.c.orig
+--- linux-2.6.35.11/drivers/serial/8250.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/serial/8250.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,3290 @@
++/*
++ * linux/drivers/char/8250.c
++ *
++ * Driver for 8250/16550-type serial ports
++ *
++ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
++ *
++ * Copyright (C) 2001 Russell King.
++ *
++ * 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.
++ *
++ * A note about mapbase / membase
++ *
++ * mapbase is the physical address of the IO port.
++ * membase is an 'ioremapped' cookie.
++ */
++
++#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
++#define SUPPORT_SYSRQ
++#endif
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/ioport.h>
++#include <linux/init.h>
++#include <linux/console.h>
++#include <linux/sysrq.h>
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++#include <linux/serial_reg.h>
++#include <linux/serial_core.h>
++#include <linux/serial.h>
++#include <linux/serial_8250.h>
++#include <linux/nmi.h>
++#include <linux/mutex.h>
++#include <linux/slab.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++
++#include "8250.h"
++
++#ifdef CONFIG_SPARC
++#include "suncore.h"
++#endif
++
++/*
++ * Configuration:
++ * share_irqs - whether we pass IRQF_SHARED to request_irq(). This option
++ * is unsafe when used on edge-triggered interrupts.
++ */
++static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
++
++static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
++
++static struct uart_driver serial8250_reg;
++
++static int serial_index(struct uart_port *port)
++{
++ return (serial8250_reg.minor - 64) + port->line;
++}
++
++static unsigned int skip_txen_test; /* force skip of txen test at init time */
++
++/*
++ * Debugging.
++ */
++#if 0
++#define DEBUG_AUTOCONF(fmt...) printk(fmt)
++#else
++#define DEBUG_AUTOCONF(fmt...) do { } while (0)
++#endif
++
++#if 0
++#define DEBUG_INTR(fmt...) printk(fmt)
++#else
++#define DEBUG_INTR(fmt...) do { } while (0)
++#endif
++
++#define PASS_LIMIT 256
++
++#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
++
++
++/*
++ * We default to IRQ0 for the "no irq" hack. Some
++ * machine types want others as well - they're free
++ * to redefine this in their header file.
++ */
++#define is_real_interrupt(irq) ((irq) != 0)
++
++#ifdef CONFIG_SERIAL_8250_DETECT_IRQ
++#define CONFIG_SERIAL_DETECT_IRQ 1
++#endif
++#ifdef CONFIG_SERIAL_8250_MANY_PORTS
++#define CONFIG_SERIAL_MANY_PORTS 1
++#endif
++
++/*
++ * HUB6 is always on. This will be removed once the header
++ * files have been cleaned.
++ */
++#define CONFIG_HUB6 1
++
++#include <asm/serial.h>
++/*
++ * SERIAL_PORT_DFNS tells us about built-in ports that have no
++ * standard enumeration mechanism. Platforms that can find all
++ * serial ports via mechanisms like ACPI or PCI need not supply it.
++ */
++#ifndef SERIAL_PORT_DFNS
++#define SERIAL_PORT_DFNS
++#endif
++
++static const struct old_serial_port old_serial_port[] = {
++ SERIAL_PORT_DFNS /* defined in asm/serial.h */
++};
++
++#define UART_NR CONFIG_SERIAL_8250_NR_UARTS
++
++#ifdef CONFIG_SERIAL_8250_RSA
++
++#define PORT_RSA_MAX 4
++static unsigned long probe_rsa[PORT_RSA_MAX];
++static unsigned int probe_rsa_count;
++#endif /* CONFIG_SERIAL_8250_RSA */
++
++struct uart_8250_port {
++ struct uart_port port;
++ struct timer_list timer; /* "no irq" timer */
++ struct list_head list; /* ports on this IRQ */
++ unsigned short capabilities; /* port capabilities */
++ unsigned short bugs; /* port bugs */
++ unsigned int tx_loadsz; /* transmit fifo load size */
++ unsigned char acr;
++ unsigned char ier;
++ unsigned char lcr;
++ unsigned char mcr;
++ unsigned char mcr_mask; /* mask of user bits */
++ unsigned char mcr_force; /* mask of forced bits */
++ unsigned char cur_iotype; /* Running I/O type */
++
++ /*
++ * Some bits in registers are cleared on a read, so they must
++ * be saved whenever the register is read but the bits will not
++ * be immediately processed.
++ */
++#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS
++ unsigned char lsr_saved_flags;
++#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
++ unsigned char msr_saved_flags;
++
++ /*
++ * We provide a per-port pm hook.
++ */
++ void (*pm)(struct uart_port *port,
++ unsigned int state, unsigned int old);
++};
++
++struct irq_info {
++ struct hlist_node node;
++ int irq;
++ spinlock_t lock; /* Protects list not the hash */
++ struct list_head *head;
++};
++
++#define NR_IRQ_HASH 32 /* Can be adjusted later */
++static struct hlist_head irq_lists[NR_IRQ_HASH];
++static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */
++
++/*
++ * Here we define the default xmit fifo size used for each type of UART.
++ */
++static const struct serial8250_config uart_config[] = {
++ [PORT_UNKNOWN] = {
++ .name = "unknown",
++ .fifo_size = 1,
++ .tx_loadsz = 1,
++ },
++ [PORT_8250] = {
++ .name = "8250",
++ .fifo_size = 1,
++ .tx_loadsz = 1,
++ },
++ [PORT_16450] = {
++ .name = "16450",
++ .fifo_size = 1,
++ .tx_loadsz = 1,
++ },
++ [PORT_16550] = {
++ .name = "16550",
++ .fifo_size = 1,
++ .tx_loadsz = 1,
++ },
++ [PORT_16550A] = {
++ .name = "16550A",
++ .fifo_size = 16,
++ .tx_loadsz = 16,
++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
++ .flags = UART_CAP_FIFO,
++ },
++ [PORT_CIRRUS] = {
++ .name = "Cirrus",
++ .fifo_size = 1,
++ .tx_loadsz = 1,
++ },
++ [PORT_16650] = {
++ .name = "ST16650",
++ .fifo_size = 1,
++ .tx_loadsz = 1,
++ .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
++ },
++ [PORT_16650V2] = {
++ .name = "ST16650V2",
++ .fifo_size = 32,
++ .tx_loadsz = 16,
++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
++ UART_FCR_T_TRIG_00,
++ .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
++ },
++ [PORT_16750] = {
++ .name = "TI16750",
++ .fifo_size = 64,
++ .tx_loadsz = 64,
++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
++ UART_FCR7_64BYTE,
++ .flags = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
++ },
++ [PORT_STARTECH] = {
++ .name = "Startech",
++ .fifo_size = 1,
++ .tx_loadsz = 1,
++ },
++ [PORT_16C950] = {
++ .name = "16C950/954",
++ .fifo_size = 128,
++ .tx_loadsz = 128,
++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
++ .flags = UART_CAP_FIFO,
++ },
++ [PORT_16654] = {
++ .name = "ST16654",
++ .fifo_size = 64,
++ .tx_loadsz = 32,
++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
++ UART_FCR_T_TRIG_10,
++ .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
++ },
++ [PORT_16850] = {
++ .name = "XR16850",
++ .fifo_size = 128,
++ .tx_loadsz = 128,
++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
++ .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
++ },
++ [PORT_RSA] = {
++ .name = "RSA",
++ .fifo_size = 2048,
++ .tx_loadsz = 2048,
++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11,
++ .flags = UART_CAP_FIFO,
++ },
++ [PORT_NS16550A] = {
++ .name = "NS16550A",
++ .fifo_size = 16,
++ .tx_loadsz = 16,
++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
++ .flags = UART_CAP_FIFO | UART_NATSEMI,
++ },
++ [PORT_XSCALE] = {
++ .name = "XScale",
++ .fifo_size = 32,
++ .tx_loadsz = 32,
++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
++ .flags = UART_CAP_FIFO | UART_CAP_UUE,
++ },
++ [PORT_RM9000] = {
++ .name = "RM9000",
++ .fifo_size = 16,
++ .tx_loadsz = 16,
++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
++ .flags = UART_CAP_FIFO,
++ },
++ [PORT_OCTEON] = {
++ .name = "OCTEON",
++ .fifo_size = 64,
++ .tx_loadsz = 64,
++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
++ .flags = UART_CAP_FIFO,
++ },
++ [PORT_AR7] = {
++ .name = "AR7",
++ .fifo_size = 16,
++ .tx_loadsz = 16,
++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
++ .flags = UART_CAP_FIFO | UART_CAP_AFE,
++ },
++};
++
++#if defined (CONFIG_SERIAL_8250_AU1X00)
++
++/* Au1x00 UART hardware has a weird register layout */
++static const u8 au_io_in_map[] = {
++ [UART_RX] = 0,
++ [UART_IER] = 2,
++ [UART_IIR] = 3,
++ [UART_LCR] = 5,
++ [UART_MCR] = 6,
++ [UART_LSR] = 7,
++ [UART_MSR] = 8,
++};
++
++static const u8 au_io_out_map[] = {
++ [UART_TX] = 1,
++ [UART_IER] = 2,
++ [UART_FCR] = 4,
++ [UART_LCR] = 5,
++ [UART_MCR] = 6,
++};
++
++/* sane hardware needs no mapping */
++static inline int map_8250_in_reg(struct uart_port *p, int offset)
++{
++ if (p->iotype != UPIO_AU)
++ return offset;
++ return au_io_in_map[offset];
++}
++
++static inline int map_8250_out_reg(struct uart_port *p, int offset)
++{
++ if (p->iotype != UPIO_AU)
++ return offset;
++ return au_io_out_map[offset];
++}
++
++#elif defined(CONFIG_SERIAL_8250_RM9K)
++
++static const u8
++ regmap_in[8] = {
++ [UART_RX] = 0x00,
++ [UART_IER] = 0x0c,
++ [UART_IIR] = 0x14,
++ [UART_LCR] = 0x1c,
++ [UART_MCR] = 0x20,
++ [UART_LSR] = 0x24,
++ [UART_MSR] = 0x28,
++ [UART_SCR] = 0x2c
++ },
++ regmap_out[8] = {
++ [UART_TX] = 0x04,
++ [UART_IER] = 0x0c,
++ [UART_FCR] = 0x18,
++ [UART_LCR] = 0x1c,
++ [UART_MCR] = 0x20,
++ [UART_LSR] = 0x24,
++ [UART_MSR] = 0x28,
++ [UART_SCR] = 0x2c
++ };
++
++static inline int map_8250_in_reg(struct uart_port *p, int offset)
++{
++ if (p->iotype != UPIO_RM9000)
++ return offset;
++ return regmap_in[offset];
++}
++
++static inline int map_8250_out_reg(struct uart_port *p, int offset)
++{
++ if (p->iotype != UPIO_RM9000)
++ return offset;
++ return regmap_out[offset];
++}
++
++#else
++
++/* sane hardware needs no mapping */
++#define map_8250_in_reg(up, offset) (offset)
++#define map_8250_out_reg(up, offset) (offset)
++
++#endif
++
++static unsigned int hub6_serial_in(struct uart_port *p, int offset)
++{
++ offset = map_8250_in_reg(p, offset) << p->regshift;
++ outb(p->hub6 - 1 + offset, p->iobase);
++ return inb(p->iobase + 1);
++}
++
++static void hub6_serial_out(struct uart_port *p, int offset, int value)
++{
++ offset = map_8250_out_reg(p, offset) << p->regshift;
++ outb(p->hub6 - 1 + offset, p->iobase);
++ outb(value, p->iobase + 1);
++}
++
++static unsigned int mem_serial_in(struct uart_port *p, int offset)
++{
++ offset = map_8250_in_reg(p, offset) << p->regshift;
++ return readb(p->membase + offset);
++}
++
++static void mem_serial_out(struct uart_port *p, int offset, int value)
++{
++ offset = map_8250_out_reg(p, offset) << p->regshift;
++ writeb(value, p->membase + offset);
++}
++
++static void mem32_serial_out(struct uart_port *p, int offset, int value)
++{
++ offset = map_8250_out_reg(p, offset) << p->regshift;
++ writel(value, p->membase + offset);
++}
++
++static unsigned int mem32_serial_in(struct uart_port *p, int offset)
++{
++ offset = map_8250_in_reg(p, offset) << p->regshift;
++ return readl(p->membase + offset);
++}
++
++#ifdef CONFIG_SERIAL_8250_AU1X00
++static unsigned int au_serial_in(struct uart_port *p, int offset)
++{
++ offset = map_8250_in_reg(p, offset) << p->regshift;
++ return __raw_readl(p->membase + offset);
++}
++
++static void au_serial_out(struct uart_port *p, int offset, int value)
++{
++ offset = map_8250_out_reg(p, offset) << p->regshift;
++ __raw_writel(value, p->membase + offset);
++}
++#endif
++
++static unsigned int tsi_serial_in(struct uart_port *p, int offset)
++{
++ unsigned int tmp;
++ offset = map_8250_in_reg(p, offset) << p->regshift;
++ if (offset == UART_IIR) {
++ tmp = readl(p->membase + (UART_IIR & ~3));
++ return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
++ } else
++ return readb(p->membase + offset);
++}
++
++static void tsi_serial_out(struct uart_port *p, int offset, int value)
++{
++ offset = map_8250_out_reg(p, offset) << p->regshift;
++ if (!((offset == UART_IER) && (value & UART_IER_UUE)))
++ writeb(value, p->membase + offset);
++}
++
++static void dwapb_serial_out(struct uart_port *p, int offset, int value)
++{
++ int save_offset = offset;
++ offset = map_8250_out_reg(p, offset) << p->regshift;
++ /* Save the LCR value so it can be re-written when a
++ * Busy Detect interrupt occurs. */
++ if (save_offset == UART_LCR) {
++ struct uart_8250_port *up = (struct uart_8250_port *)p;
++ up->lcr = value;
++ }
++ writeb(value, p->membase + offset);
++ /* Read the IER to ensure any interrupt is cleared before
++ * returning from ISR. */
++ if (save_offset == UART_TX || save_offset == UART_IER)
++ value = p->serial_in(p, UART_IER);
++}
++
++static unsigned int io_serial_in(struct uart_port *p, int offset)
++{
++ offset = map_8250_in_reg(p, offset) << p->regshift;
++ return inb(p->iobase + offset);
++}
++
++static void io_serial_out(struct uart_port *p, int offset, int value)
++{
++ offset = map_8250_out_reg(p, offset) << p->regshift;
++ outb(value, p->iobase + offset);
++}
++
++static void set_io_from_upio(struct uart_port *p)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)p;
++ switch (p->iotype) {
++ case UPIO_HUB6:
++ p->serial_in = hub6_serial_in;
++ p->serial_out = hub6_serial_out;
++ break;
++
++ case UPIO_MEM:
++ p->serial_in = mem_serial_in;
++ p->serial_out = mem_serial_out;
++ break;
++
++ case UPIO_RM9000:
++ case UPIO_MEM32:
++ p->serial_in = mem32_serial_in;
++ p->serial_out = mem32_serial_out;
++ break;
++
++#ifdef CONFIG_SERIAL_8250_AU1X00
++ case UPIO_AU:
++ p->serial_in = au_serial_in;
++ p->serial_out = au_serial_out;
++ break;
++#endif
++ case UPIO_TSI:
++ p->serial_in = tsi_serial_in;
++ p->serial_out = tsi_serial_out;
++ break;
++
++ case UPIO_DWAPB:
++ p->serial_in = mem_serial_in;
++ p->serial_out = dwapb_serial_out;
++ break;
++
++ default:
++ p->serial_in = io_serial_in;
++ p->serial_out = io_serial_out;
++ break;
++ }
++ /* Remember loaded iotype */
++ up->cur_iotype = p->iotype;
++}
++
++static void
++serial_out_sync(struct uart_8250_port *up, int offset, int value)
++{
++ struct uart_port *p = &up->port;
++ switch (p->iotype) {
++ case UPIO_MEM:
++ case UPIO_MEM32:
++#ifdef CONFIG_SERIAL_8250_AU1X00
++ case UPIO_AU:
++#endif
++ case UPIO_DWAPB:
++ p->serial_out(p, offset, value);
++ p->serial_in(p, UART_LCR); /* safe, no side-effects */
++ break;
++ default:
++ p->serial_out(p, offset, value);
++ }
++}
++
++#define serial_in(up, offset) \
++ (up->port.serial_in(&(up)->port, (offset)))
++#define serial_out(up, offset, value) \
++ (up->port.serial_out(&(up)->port, (offset), (value)))
++/*
++ * We used to support using pause I/O for certain machines. We
++ * haven't supported this for a while, but just in case it's badly
++ * needed for certain old 386 machines, I've left these #define's
++ * in....
++ */
++#define serial_inp(up, offset) serial_in(up, offset)
++#define serial_outp(up, offset, value) serial_out(up, offset, value)
++
++/* Uart divisor latch read */
++static inline int _serial_dl_read(struct uart_8250_port *up)
++{
++ return serial_inp(up, UART_DLL) | serial_inp(up, UART_DLM) << 8;
++}
++
++/* Uart divisor latch write */
++static inline void _serial_dl_write(struct uart_8250_port *up, int value)
++{
++ serial_outp(up, UART_DLL, value & 0xff);
++ serial_outp(up, UART_DLM, value >> 8 & 0xff);
++}
++
++#if defined(CONFIG_SERIAL_8250_AU1X00)
++/* Au1x00 haven't got a standard divisor latch */
++static int serial_dl_read(struct uart_8250_port *up)
++{
++ if (up->port.iotype == UPIO_AU)
++ return __raw_readl(up->port.membase + 0x28);
++ else
++ return _serial_dl_read(up);
++}
++
++static void serial_dl_write(struct uart_8250_port *up, int value)
++{
++ if (up->port.iotype == UPIO_AU)
++ __raw_writel(value, up->port.membase + 0x28);
++ else
++ _serial_dl_write(up, value);
++}
++#elif defined(CONFIG_SERIAL_8250_RM9K)
++static int serial_dl_read(struct uart_8250_port *up)
++{
++ return (up->port.iotype == UPIO_RM9000) ?
++ (((__raw_readl(up->port.membase + 0x10) << 8) |
++ (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) :
++ _serial_dl_read(up);
++}
++
++static void serial_dl_write(struct uart_8250_port *up, int value)
++{
++ if (up->port.iotype == UPIO_RM9000) {
++ __raw_writel(value, up->port.membase + 0x08);
++ __raw_writel(value >> 8, up->port.membase + 0x10);
++ } else {
++ _serial_dl_write(up, value);
++ }
++}
++#else
++#define serial_dl_read(up) _serial_dl_read(up)
++#define serial_dl_write(up, value) _serial_dl_write(up, value)
++#endif
++
++/*
++ * For the 16C950
++ */
++static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
++{
++ serial_out(up, UART_SCR, offset);
++ serial_out(up, UART_ICR, value);
++}
++
++static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
++{
++ unsigned int value;
++
++ serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
++ serial_out(up, UART_SCR, offset);
++ value = serial_in(up, UART_ICR);
++ serial_icr_write(up, UART_ACR, up->acr);
++
++ return value;
++}
++
++/*
++ * FIFO support.
++ */
++static void serial8250_clear_fifos(struct uart_8250_port *p)
++{
++ if (p->capabilities & UART_CAP_FIFO) {
++ serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO);
++ serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO |
++ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
++ serial_outp(p, UART_FCR, 0);
++ }
++}
++
++/*
++ * IER sleep support. UARTs which have EFRs need the "extended
++ * capability" bit enabled. Note that on XR16C850s, we need to
++ * reset LCR to write to IER.
++ */
++static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
++{
++ if (p->capabilities & UART_CAP_SLEEP) {
++ if (p->capabilities & UART_CAP_EFR) {
++ serial_outp(p, UART_LCR, 0xBF);
++ serial_outp(p, UART_EFR, UART_EFR_ECB);
++ serial_outp(p, UART_LCR, 0);
++ }
++ serial_outp(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
++ if (p->capabilities & UART_CAP_EFR) {
++ serial_outp(p, UART_LCR, 0xBF);
++ serial_outp(p, UART_EFR, 0);
++ serial_outp(p, UART_LCR, 0);
++ }
++ }
++}
++
++#ifdef CONFIG_SERIAL_8250_RSA
++/*
++ * Attempts to turn on the RSA FIFO. Returns zero on failure.
++ * We set the port uart clock rate if we succeed.
++ */
++static int __enable_rsa(struct uart_8250_port *up)
++{
++ unsigned char mode;
++ int result;
++
++ mode = serial_inp(up, UART_RSA_MSR);
++ result = mode & UART_RSA_MSR_FIFO;
++
++ if (!result) {
++ serial_outp(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
++ mode = serial_inp(up, UART_RSA_MSR);
++ result = mode & UART_RSA_MSR_FIFO;
++ }
++
++ if (result)
++ up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
++
++ return result;
++}
++
++static void enable_rsa(struct uart_8250_port *up)
++{
++ if (up->port.type == PORT_RSA) {
++ if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
++ spin_lock_irq(&up->port.lock);
++ __enable_rsa(up);
++ spin_unlock_irq(&up->port.lock);
++ }
++ if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
++ serial_outp(up, UART_RSA_FRR, 0);
++ }
++}
++
++/*
++ * Attempts to turn off the RSA FIFO. Returns zero on failure.
++ * It is unknown why interrupts were disabled in here. However,
++ * the caller is expected to preserve this behaviour by grabbing
++ * the spinlock before calling this function.
++ */
++static void disable_rsa(struct uart_8250_port *up)
++{
++ unsigned char mode;
++ int result;
++
++ if (up->port.type == PORT_RSA &&
++ up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
++ spin_lock_irq(&up->port.lock);
++
++ mode = serial_inp(up, UART_RSA_MSR);
++ result = !(mode & UART_RSA_MSR_FIFO);
++
++ if (!result) {
++ serial_outp(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
++ mode = serial_inp(up, UART_RSA_MSR);
++ result = !(mode & UART_RSA_MSR_FIFO);
++ }
++
++ if (result)
++ up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
++ spin_unlock_irq(&up->port.lock);
++ }
++}
++#endif /* CONFIG_SERIAL_8250_RSA */
++
++/*
++ * This is a quickie test to see how big the FIFO is.
++ * It doesn't work at all the time, more's the pity.
++ */
++static int size_fifo(struct uart_8250_port *up)
++{
++ unsigned char old_fcr, old_mcr, old_lcr;
++ unsigned short old_dl;
++ int count;
++
++ old_lcr = serial_inp(up, UART_LCR);
++ serial_outp(up, UART_LCR, 0);
++ old_fcr = serial_inp(up, UART_FCR);
++ old_mcr = serial_inp(up, UART_MCR);
++ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
++ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
++ serial_outp(up, UART_MCR, UART_MCR_LOOP);
++ serial_outp(up, UART_LCR, UART_LCR_DLAB);
++ old_dl = serial_dl_read(up);
++ serial_dl_write(up, 0x0001);
++ serial_outp(up, UART_LCR, 0x03);
++ for (count = 0; count < 256; count++)
++ serial_outp(up, UART_TX, count);
++ mdelay(20);/* FIXME - schedule_timeout */
++ for (count = 0; (serial_inp(up, UART_LSR) & UART_LSR_DR) &&
++ (count < 256); count++)
++ serial_inp(up, UART_RX);
++ serial_outp(up, UART_FCR, old_fcr);
++ serial_outp(up, UART_MCR, old_mcr);
++ serial_outp(up, UART_LCR, UART_LCR_DLAB);
++ serial_dl_write(up, old_dl);
++ serial_outp(up, UART_LCR, old_lcr);
++
++ return count;
++}
++
++/*
++ * Read UART ID using the divisor method - set DLL and DLM to zero
++ * and the revision will be in DLL and device type in DLM. We
++ * preserve the device state across this.
++ */
++static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
++{
++ unsigned char old_dll, old_dlm, old_lcr;
++ unsigned int id;
++
++ old_lcr = serial_inp(p, UART_LCR);
++ serial_outp(p, UART_LCR, UART_LCR_DLAB);
++
++ old_dll = serial_inp(p, UART_DLL);
++ old_dlm = serial_inp(p, UART_DLM);
++
++ serial_outp(p, UART_DLL, 0);
++ serial_outp(p, UART_DLM, 0);
++
++ id = serial_inp(p, UART_DLL) | serial_inp(p, UART_DLM) << 8;
++
++ serial_outp(p, UART_DLL, old_dll);
++ serial_outp(p, UART_DLM, old_dlm);
++ serial_outp(p, UART_LCR, old_lcr);
++
++ return id;
++}
++
++/*
++ * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
++ * When this function is called we know it is at least a StarTech
++ * 16650 V2, but it might be one of several StarTech UARTs, or one of
++ * its clones. (We treat the broken original StarTech 16650 V1 as a
++ * 16550, and why not? Startech doesn't seem to even acknowledge its
++ * existence.)
++ *
++ * What evil have men's minds wrought...
++ */
++static void autoconfig_has_efr(struct uart_8250_port *up)
++{
++ unsigned int id1, id2, id3, rev;
++
++ /*
++ * Everything with an EFR has SLEEP
++ */
++ up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
++
++ /*
++ * First we check to see if it's an Oxford Semiconductor UART.
++ *
++ * If we have to do this here because some non-National
++ * Semiconductor clone chips lock up if you try writing to the
++ * LSR register (which serial_icr_read does)
++ */
++
++ /*
++ * Check for Oxford Semiconductor 16C950.
++ *
++ * EFR [4] must be set else this test fails.
++ *
++ * This shouldn't be necessary, but Mike Hudson (Exoray at isys.ca)
++ * claims that it's needed for 952 dual UART's (which are not
++ * recommended for new designs).
++ */
++ up->acr = 0;
++ serial_out(up, UART_LCR, 0xBF);
++ serial_out(up, UART_EFR, UART_EFR_ECB);
++ serial_out(up, UART_LCR, 0x00);
++ id1 = serial_icr_read(up, UART_ID1);
++ id2 = serial_icr_read(up, UART_ID2);
++ id3 = serial_icr_read(up, UART_ID3);
++ rev = serial_icr_read(up, UART_REV);
++
++ DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
++
++ if (id1 == 0x16 && id2 == 0xC9 &&
++ (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
++ up->port.type = PORT_16C950;
++
++ /*
++ * Enable work around for the Oxford Semiconductor 952 rev B
++ * chip which causes it to seriously miscalculate baud rates
++ * when DLL is 0.
++ */
++ if (id3 == 0x52 && rev == 0x01)
++ up->bugs |= UART_BUG_QUOT;
++ return;
++ }
++
++ /*
++ * We check for a XR16C850 by setting DLL and DLM to 0, and then
++ * reading back DLL and DLM. The chip type depends on the DLM
++ * value read back:
++ * 0x10 - XR16C850 and the DLL contains the chip revision.
++ * 0x12 - XR16C2850.
++ * 0x14 - XR16C854.
++ */
++ id1 = autoconfig_read_divisor_id(up);
++ DEBUG_AUTOCONF("850id=%04x ", id1);
++
++ id2 = id1 >> 8;
++ if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
++ up->port.type = PORT_16850;
++ return;
++ }
++
++ /*
++ * It wasn't an XR16C850.
++ *
++ * We distinguish between the '654 and the '650 by counting
++ * how many bytes are in the FIFO. I'm using this for now,
++ * since that's the technique that was sent to me in the
++ * serial driver update, but I'm not convinced this works.
++ * I've had problems doing this in the past. -TYT
++ */
++ if (size_fifo(up) == 64)
++ up->port.type = PORT_16654;
++ else
++ up->port.type = PORT_16650V2;
++}
++
++/*
++ * We detected a chip without a FIFO. Only two fall into
++ * this category - the original 8250 and the 16450. The
++ * 16450 has a scratch register (accessible with LCR=0)
++ */
++static void autoconfig_8250(struct uart_8250_port *up)
++{
++ unsigned char scratch, status1, status2;
++
++ up->port.type = PORT_8250;
++
++ scratch = serial_in(up, UART_SCR);
++ serial_outp(up, UART_SCR, 0xa5);
++ status1 = serial_in(up, UART_SCR);
++ serial_outp(up, UART_SCR, 0x5a);
++ status2 = serial_in(up, UART_SCR);
++ serial_outp(up, UART_SCR, scratch);
++
++ if (status1 == 0xa5 && status2 == 0x5a)
++ up->port.type = PORT_16450;
++}
++
++static int broken_efr(struct uart_8250_port *up)
++{
++ /*
++ * Exar ST16C2550 "A2" devices incorrectly detect as
++ * having an EFR, and report an ID of 0x0201. See
++ * http://www.exar.com/info.php?pdf=dan180_oct2004.pdf
++ */
++ if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
++ return 1;
++
++ return 0;
++}
++
++/*
++ * We know that the chip has FIFOs. Does it have an EFR? The
++ * EFR is located in the same register position as the IIR and
++ * we know the top two bits of the IIR are currently set. The
++ * EFR should contain zero. Try to read the EFR.
++ */
++static void autoconfig_16550a(struct uart_8250_port *up)
++{
++ unsigned char status1, status2;
++ unsigned int iersave;
++
++ up->port.type = PORT_16550A;
++ up->capabilities |= UART_CAP_FIFO;
++
++ /*
++ * Check for presence of the EFR when DLAB is set.
++ * Only ST16C650V1 UARTs pass this test.
++ */
++ serial_outp(up, UART_LCR, UART_LCR_DLAB);
++ if (serial_in(up, UART_EFR) == 0) {
++ serial_outp(up, UART_EFR, 0xA8);
++ if (serial_in(up, UART_EFR) != 0) {
++ DEBUG_AUTOCONF("EFRv1 ");
++ up->port.type = PORT_16650;
++ up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
++ } else {
++ DEBUG_AUTOCONF("Motorola 8xxx DUART ");
++ }
++ serial_outp(up, UART_EFR, 0);
++ return;
++ }
++
++ /*
++ * Maybe it requires 0xbf to be written to the LCR.
++ * (other ST16C650V2 UARTs, TI16C752A, etc)
++ */
++ serial_outp(up, UART_LCR, 0xBF);
++ if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
++ DEBUG_AUTOCONF("EFRv2 ");
++ autoconfig_has_efr(up);
++ return;
++ }
++
++ /*
++ * Check for a National Semiconductor SuperIO chip.
++ * Attempt to switch to bank 2, read the value of the LOOP bit
++ * from EXCR1. Switch back to bank 0, change it in MCR. Then
++ * switch back to bank 2, read it from EXCR1 again and check
++ * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2
++ */
++ serial_outp(up, UART_LCR, 0);
++ status1 = serial_in(up, UART_MCR);
++ serial_outp(up, UART_LCR, 0xE0);
++ status2 = serial_in(up, 0x02); /* EXCR1 */
++
++ if (!((status2 ^ status1) & UART_MCR_LOOP)) {
++ serial_outp(up, UART_LCR, 0);
++ serial_outp(up, UART_MCR, status1 ^ UART_MCR_LOOP);
++ serial_outp(up, UART_LCR, 0xE0);
++ status2 = serial_in(up, 0x02); /* EXCR1 */
++ serial_outp(up, UART_LCR, 0);
++ serial_outp(up, UART_MCR, status1);
++
++ if ((status2 ^ status1) & UART_MCR_LOOP) {
++ unsigned short quot;
++
++ serial_outp(up, UART_LCR, 0xE0);
++
++ quot = serial_dl_read(up);
++ quot <<= 3;
++
++ status1 = serial_in(up, 0x04); /* EXCR2 */
++ status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
++ status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
++ serial_outp(up, 0x04, status1);
++
++ serial_dl_write(up, quot);
++
++ serial_outp(up, UART_LCR, 0);
++
++ up->port.uartclk = 921600*16;
++ up->port.type = PORT_NS16550A;
++ up->capabilities |= UART_NATSEMI;
++ return;
++ }
++ }
++
++ /*
++ * No EFR. Try to detect a TI16750, which only sets bit 5 of
++ * the IIR when 64 byte FIFO mode is enabled when DLAB is set.
++ * Try setting it with and without DLAB set. Cheap clones
++ * set bit 5 without DLAB set.
++ */
++ serial_outp(up, UART_LCR, 0);
++ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
++ status1 = serial_in(up, UART_IIR) >> 5;
++ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
++ serial_outp(up, UART_LCR, UART_LCR_DLAB);
++ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
++ status2 = serial_in(up, UART_IIR) >> 5;
++ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
++ serial_outp(up, UART_LCR, 0);
++
++ DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
++
++ if (status1 == 6 && status2 == 7) {
++ up->port.type = PORT_16750;
++ up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
++ return;
++ }
++
++ /*
++ * Try writing and reading the UART_IER_UUE bit (b6).
++ * If it works, this is probably one of the Xscale platform's
++ * internal UARTs.
++ * We're going to explicitly set the UUE bit to 0 before
++ * trying to write and read a 1 just to make sure it's not
++ * already a 1 and maybe locked there before we even start start.
++ */
++ iersave = serial_in(up, UART_IER);
++ serial_outp(up, UART_IER, iersave & ~UART_IER_UUE);
++ if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
++ /*
++ * OK it's in a known zero state, try writing and reading
++ * without disturbing the current state of the other bits.
++ */
++ serial_outp(up, UART_IER, iersave | UART_IER_UUE);
++ if (serial_in(up, UART_IER) & UART_IER_UUE) {
++ /*
++ * It's an Xscale.
++ * We'll leave the UART_IER_UUE bit set to 1 (enabled).
++ */
++ DEBUG_AUTOCONF("Xscale ");
++ up->port.type = PORT_XSCALE;
++ up->capabilities |= UART_CAP_UUE;
++ return;
++ }
++ } else {
++ /*
++ * If we got here we couldn't force the IER_UUE bit to 0.
++ * Log it and continue.
++ */
++ DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
++ }
++ serial_outp(up, UART_IER, iersave);
++}
++
++/*
++ * This routine is called by rs_init() to initialize a specific serial
++ * port. It determines what type of UART chip this serial port is
++ * using: 8250, 16450, 16550, 16550A. The important question is
++ * whether or not this UART is a 16550A or not, since this will
++ * determine whether or not we can use its FIFO features or not.
++ */
++static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
++{
++ unsigned char status1, scratch, scratch2, scratch3;
++ unsigned char save_lcr, save_mcr;
++ unsigned long flags;
++
++ if (!up->port.iobase && !up->port.mapbase && !up->port.membase)
++ return;
++
++ DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ",
++ serial_index(&up->port), up->port.iobase, up->port.membase);
++
++ /*
++ * We really do need global IRQs disabled here - we're going to
++ * be frobbing the chips IRQ enable register to see if it exists.
++ */
++ spin_lock_irqsave(&up->port.lock, flags);
++
++ up->capabilities = 0;
++ up->bugs = 0;
++
++ if (!(up->port.flags & UPF_BUGGY_UART)) {
++ /*
++ * Do a simple existence test first; if we fail this,
++ * there's no point trying anything else.
++ *
++ * 0x80 is used as a nonsense port to prevent against
++ * false positives due to ISA bus float. The
++ * assumption is that 0x80 is a non-existent port;
++ * which should be safe since include/asm/io.h also
++ * makes this assumption.
++ *
++ * Note: this is safe as long as MCR bit 4 is clear
++ * and the device is in "PC" mode.
++ */
++ scratch = serial_inp(up, UART_IER);
++ serial_outp(up, UART_IER, 0);
++#ifdef __i386__
++ outb(0xff, 0x080);
++#endif
++ /*
++ * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
++ * 16C754B) allow only to modify them if an EFR bit is set.
++ */
++ scratch2 = serial_inp(up, UART_IER) & 0x0f;
++ serial_outp(up, UART_IER, 0x0F);
++#ifdef __i386__
++ outb(0, 0x080);
++#endif
++ scratch3 = serial_inp(up, UART_IER) & 0x0f;
++ serial_outp(up, UART_IER, scratch);
++ if (scratch2 != 0 || scratch3 != 0x0F) {
++ /*
++ * We failed; there's nothing here
++ */
++ DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
++ scratch2, scratch3);
++ goto out;
++ }
++ }
++
++ save_mcr = serial_in(up, UART_MCR);
++ save_lcr = serial_in(up, UART_LCR);
++
++ /*
++ * Check to see if a UART is really there. Certain broken
++ * internal modems based on the Rockwell chipset fail this
++ * test, because they apparently don't implement the loopback
++ * test mode. So this test is skipped on the COM 1 through
++ * COM 4 ports. This *should* be safe, since no board
++ * manufacturer would be stupid enough to design a board
++ * that conflicts with COM 1-4 --- we hope!
++ */
++ if (!(up->port.flags & UPF_SKIP_TEST)) {
++ serial_outp(up, UART_MCR, UART_MCR_LOOP | 0x0A);
++ status1 = serial_inp(up, UART_MSR) & 0xF0;
++ serial_outp(up, UART_MCR, save_mcr);
++ if (status1 != 0x90) {
++ DEBUG_AUTOCONF("LOOP test failed (%02x) ",
++ status1);
++ goto out;
++ }
++ }
++
++ /*
++ * We're pretty sure there's a port here. Lets find out what
++ * type of port it is. The IIR top two bits allows us to find
++ * out if it's 8250 or 16450, 16550, 16550A or later. This
++ * determines what we test for next.
++ *
++ * We also initialise the EFR (if any) to zero for later. The
++ * EFR occupies the same register location as the FCR and IIR.
++ */
++ serial_outp(up, UART_LCR, 0xBF);
++ serial_outp(up, UART_EFR, 0);
++ serial_outp(up, UART_LCR, 0);
++
++ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
++ scratch = serial_in(up, UART_IIR) >> 6;
++
++ DEBUG_AUTOCONF("iir=%d ", scratch);
++
++ switch (scratch) {
++ case 0:
++ autoconfig_8250(up);
++ break;
++ case 1:
++ up->port.type = PORT_UNKNOWN;
++ break;
++ case 2:
++ up->port.type = PORT_16550;
++ break;
++ case 3:
++ autoconfig_16550a(up);
++ break;
++ }
++
++#ifdef CONFIG_SERIAL_8250_RSA
++ /*
++ * Only probe for RSA ports if we got the region.
++ */
++ if (up->port.type == PORT_16550A && probeflags & PROBE_RSA) {
++ int i;
++
++ for (i = 0 ; i < probe_rsa_count; ++i) {
++ if (probe_rsa[i] == up->port.iobase &&
++ __enable_rsa(up)) {
++ up->port.type = PORT_RSA;
++ break;
++ }
++ }
++ }
++#endif
++
++ serial_outp(up, UART_LCR, save_lcr);
++
++ if (up->capabilities != uart_config[up->port.type].flags) {
++ printk(KERN_WARNING
++ "ttyS%d: detected caps %08x should be %08x\n",
++ serial_index(&up->port), up->capabilities,
++ uart_config[up->port.type].flags);
++ }
++
++ up->port.fifosize = uart_config[up->port.type].fifo_size;
++ up->capabilities = uart_config[up->port.type].flags;
++ up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
++
++ if (up->port.type == PORT_UNKNOWN)
++ goto out;
++
++ /*
++ * Reset the UART.
++ */
++#ifdef CONFIG_SERIAL_8250_RSA
++ if (up->port.type == PORT_RSA)
++ serial_outp(up, UART_RSA_FRR, 0);
++#endif
++ serial_outp(up, UART_MCR, save_mcr);
++ serial8250_clear_fifos(up);
++ serial_in(up, UART_RX);
++ if (up->capabilities & UART_CAP_UUE)
++ serial_outp(up, UART_IER, UART_IER_UUE);
++ else
++ serial_outp(up, UART_IER, 0);
++
++ out:
++ spin_unlock_irqrestore(&up->port.lock, flags);
++ DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name);
++}
++
++static void autoconfig_irq(struct uart_8250_port *up)
++{
++ unsigned char save_mcr, save_ier;
++ unsigned char save_ICP = 0;
++ unsigned int ICP = 0;
++ unsigned long irqs;
++ int irq;
++
++ if (up->port.flags & UPF_FOURPORT) {
++ ICP = (up->port.iobase & 0xfe0) | 0x1f;
++ save_ICP = inb_p(ICP);
++ outb_p(0x80, ICP);
++ (void) inb_p(ICP);
++ }
++
++ /* forget possible initially masked and pending IRQ */
++ probe_irq_off(probe_irq_on());
++ save_mcr = serial_inp(up, UART_MCR);
++ save_ier = serial_inp(up, UART_IER);
++ serial_outp(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
++
++ irqs = probe_irq_on();
++ serial_outp(up, UART_MCR, 0);
++ udelay(10);
++ if (up->port.flags & UPF_FOURPORT) {
++ serial_outp(up, UART_MCR,
++ UART_MCR_DTR | UART_MCR_RTS);
++ } else {
++ serial_outp(up, UART_MCR,
++ UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
++ }
++ serial_outp(up, UART_IER, 0x0f); /* enable all intrs */
++ (void)serial_inp(up, UART_LSR);
++ (void)serial_inp(up, UART_RX);
++ (void)serial_inp(up, UART_IIR);
++ (void)serial_inp(up, UART_MSR);
++ serial_outp(up, UART_TX, 0xFF);
++ udelay(20);
++ irq = probe_irq_off(irqs);
++
++ serial_outp(up, UART_MCR, save_mcr);
++ serial_outp(up, UART_IER, save_ier);
++
++ if (up->port.flags & UPF_FOURPORT)
++ outb_p(save_ICP, ICP);
++
++ up->port.irq = (irq > 0) ? irq : 0;
++}
++
++static inline void __stop_tx(struct uart_8250_port *p)
++{
++ if (p->ier & UART_IER_THRI) {
++ p->ier &= ~UART_IER_THRI;
++ serial_out(p, UART_IER, p->ier);
++ }
++}
++
++static void serial8250_stop_tx(struct uart_port *port)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++
++ __stop_tx(up);
++
++ /*
++ * We really want to stop the transmitter from sending.
++ */
++ if (up->port.type == PORT_16C950) {
++ up->acr |= UART_ACR_TXDIS;
++ serial_icr_write(up, UART_ACR, up->acr);
++ }
++}
++
++static void transmit_chars(struct uart_8250_port *up);
++
++static void serial8250_start_tx(struct uart_port *port)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++
++ if (!(up->ier & UART_IER_THRI)) {
++ up->ier |= UART_IER_THRI;
++ serial_out(up, UART_IER, up->ier);
++
++ if (up->bugs & UART_BUG_TXEN) {
++ unsigned char lsr;
++ lsr = serial_in(up, UART_LSR);
++ up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
++ if ((up->port.type == PORT_RM9000) ?
++ (lsr & UART_LSR_THRE) :
++ (lsr & UART_LSR_TEMT))
++ transmit_chars(up);
++ }
++ }
++
++ /*
++ * Re-enable the transmitter if we disabled it.
++ */
++ if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
++ up->acr &= ~UART_ACR_TXDIS;
++ serial_icr_write(up, UART_ACR, up->acr);
++ }
++}
++
++static void serial8250_stop_rx(struct uart_port *port)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++
++ up->ier &= ~UART_IER_RLSI;
++ up->port.read_status_mask &= ~UART_LSR_DR;
++ serial_out(up, UART_IER, up->ier);
++}
++
++static void serial8250_enable_ms(struct uart_port *port)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++
++ /* no MSR capabilities */
++ if (up->bugs & UART_BUG_NOMSR)
++ return;
++
++ up->ier |= UART_IER_MSI;
++ serial_out(up, UART_IER, up->ier);
++}
++
++static void
++receive_chars(struct uart_8250_port *up, unsigned int *status)
++{
++ struct tty_struct *tty = up->port.state->port.tty;
++ unsigned char ch, lsr = *status;
++ int max_count = 256;
++ char flag;
++
++ do {
++ if (likely(lsr & UART_LSR_DR))
++ ch = serial_inp(up, UART_RX);
++ else
++ /*
++ * Intel 82571 has a Serial Over Lan device that will
++ * set UART_LSR_BI without setting UART_LSR_DR when
++ * it receives a break. To avoid reading from the
++ * receive buffer without UART_LSR_DR bit set, we
++ * just force the read character to be 0
++ */
++ ch = 0;
++
++ flag = TTY_NORMAL;
++ up->port.icount.rx++;
++
++ lsr |= up->lsr_saved_flags;
++ up->lsr_saved_flags = 0;
++
++ if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
++ /*
++ * For statistics only
++ */
++ if (lsr & UART_LSR_BI) {
++ lsr &= ~(UART_LSR_FE | UART_LSR_PE);
++ up->port.icount.brk++;
++ /*
++ * We do the SysRQ and SAK checking
++ * here because otherwise the break
++ * may get masked by ignore_status_mask
++ * or read_status_mask.
++ */
++ if (uart_handle_break(&up->port))
++ goto ignore_char;
++ } else if (lsr & UART_LSR_PE)
++ up->port.icount.parity++;
++ else if (lsr & UART_LSR_FE)
++ up->port.icount.frame++;
++ if (lsr & UART_LSR_OE)
++ up->port.icount.overrun++;
++
++ /*
++ * Mask off conditions which should be ignored.
++ */
++ lsr &= up->port.read_status_mask;
++
++ if (lsr & UART_LSR_BI) {
++ DEBUG_INTR("handling break....");
++ flag = TTY_BREAK;
++ } else if (lsr & UART_LSR_PE)
++ flag = TTY_PARITY;
++ else if (lsr & UART_LSR_FE)
++ flag = TTY_FRAME;
++ }
++ if (uart_handle_sysrq_char(&up->port, ch))
++ goto ignore_char;
++
++ uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
++
++ignore_char:
++ lsr = serial_inp(up, UART_LSR);
++ } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
++ spin_unlock(&up->port.lock);
++ tty_flip_buffer_push(tty);
++ spin_lock(&up->port.lock);
++ *status = lsr;
++}
++
++static void transmit_chars(struct uart_8250_port *up)
++{
++ struct circ_buf *xmit = &up->port.state->xmit;
++ int count;
++
++ if (up->port.x_char) {
++ serial_outp(up, UART_TX, up->port.x_char);
++ up->port.icount.tx++;
++ up->port.x_char = 0;
++ return;
++ }
++ if (uart_tx_stopped(&up->port)) {
++ serial8250_stop_tx(&up->port);
++ return;
++ }
++ if (uart_circ_empty(xmit)) {
++ __stop_tx(up);
++ return;
++ }
++
++ count = up->tx_loadsz;
++ do {
++ serial_out(up, UART_TX, xmit->buf[xmit->tail]);
++ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
++ up->port.icount.tx++;
++ if (uart_circ_empty(xmit))
++ break;
++ } while (--count > 0);
++
++ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
++ uart_write_wakeup(&up->port);
++
++ DEBUG_INTR("THRE...");
++
++ if (uart_circ_empty(xmit))
++ __stop_tx(up);
++}
++
++static unsigned int check_modem_status(struct uart_8250_port *up)
++{
++ unsigned int status = serial_in(up, UART_MSR);
++
++ status |= up->msr_saved_flags;
++ up->msr_saved_flags = 0;
++ if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
++ up->port.state != NULL) {
++ if (status & UART_MSR_TERI)
++ up->port.icount.rng++;
++ if (status & UART_MSR_DDSR)
++ up->port.icount.dsr++;
++ if (status & UART_MSR_DDCD)
++ uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
++ if (status & UART_MSR_DCTS)
++ uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
++
++ wake_up_interruptible(&up->port.state->port.delta_msr_wait);
++ }
++
++ return status;
++}
++
++/*
++ * This handles the interrupt from one port.
++ */
++static void serial8250_handle_port(struct uart_8250_port *up)
++{
++ unsigned int status;
++ unsigned long flags;
++
++ spin_lock_irqsave(&up->port.lock, flags);
++
++ status = serial_inp(up, UART_LSR);
++
++ DEBUG_INTR("status = %x...", status);
++
++ if (status & (UART_LSR_DR | UART_LSR_BI))
++ receive_chars(up, &status);
++ check_modem_status(up);
++ if (status & UART_LSR_THRE)
++ transmit_chars(up);
++
++ spin_unlock_irqrestore(&up->port.lock, flags);
++}
++
++/*
++ * This is the serial driver's interrupt routine.
++ *
++ * Arjan thinks the old way was overly complex, so it got simplified.
++ * Alan disagrees, saying that need the complexity to handle the weird
++ * nature of ISA shared interrupts. (This is a special exception.)
++ *
++ * In order to handle ISA shared interrupts properly, we need to check
++ * that all ports have been serviced, and therefore the ISA interrupt
++ * line has been de-asserted.
++ *
++ * This means we need to loop through all ports. checking that they
++ * don't have an interrupt pending.
++ */
++static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
++{
++ struct irq_info *i = dev_id;
++ struct list_head *l, *end = NULL;
++ int pass_counter = 0, handled = 0;
++
++ DEBUG_INTR("serial8250_interrupt(%d)...", irq);
++
++ spin_lock(&i->lock);
++
++ l = i->head;
++ do {
++ struct uart_8250_port *up;
++ unsigned int iir;
++
++ up = list_entry(l, struct uart_8250_port, list);
++
++ iir = serial_in(up, UART_IIR);
++ if (!(iir & UART_IIR_NO_INT)) {
++ serial8250_handle_port(up);
++
++ handled = 1;
++
++ end = NULL;
++ } else if (up->port.iotype == UPIO_DWAPB &&
++ (iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
++ /* The DesignWare APB UART has an Busy Detect (0x07)
++ * interrupt meaning an LCR write attempt occured while the
++ * UART was busy. The interrupt must be cleared by reading
++ * the UART status register (USR) and the LCR re-written. */
++ unsigned int status;
++ status = *(volatile u32 *)up->port.private_data;
++ serial_out(up, UART_LCR, up->lcr);
++
++ handled = 1;
++
++ end = NULL;
++ } else if (end == NULL)
++ end = l;
++
++ l = l->next;
++
++ if (l == i->head && pass_counter++ > PASS_LIMIT) {
++ /* If we hit this, we're dead. */
++ printk(KERN_ERR "serial8250: too much work for "
++ "irq%d\n", irq);
++ break;
++ }
++ } while (l != end);
++
++ spin_unlock(&i->lock);
++
++ DEBUG_INTR("end.\n");
++
++ return IRQ_RETVAL(handled);
++}
++
++/*
++ * To support ISA shared interrupts, we need to have one interrupt
++ * handler that ensures that the IRQ line has been deasserted
++ * before returning. Failing to do this will result in the IRQ
++ * line being stuck active, and, since ISA irqs are edge triggered,
++ * no more IRQs will be seen.
++ */
++static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
++{
++ spin_lock_irq(&i->lock);
++
++ if (!list_empty(i->head)) {
++ if (i->head == &up->list)
++ i->head = i->head->next;
++ list_del(&up->list);
++ } else {
++ BUG_ON(i->head != &up->list);
++ i->head = NULL;
++ }
++ spin_unlock_irq(&i->lock);
++ /* List empty so throw away the hash node */
++ if (i->head == NULL) {
++ hlist_del(&i->node);
++ kfree(i);
++ }
++}
++
++static int serial_link_irq_chain(struct uart_8250_port *up)
++{
++ struct hlist_head *h;
++ struct hlist_node *n;
++ struct irq_info *i;
++ int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
++
++ mutex_lock(&hash_mutex);
++
++ h = &irq_lists[up->port.irq % NR_IRQ_HASH];
++
++ hlist_for_each(n, h) {
++ i = hlist_entry(n, struct irq_info, node);
++ if (i->irq == up->port.irq)
++ break;
++ }
++
++ if (n == NULL) {
++ i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
++ if (i == NULL) {
++ mutex_unlock(&hash_mutex);
++ return -ENOMEM;
++ }
++ spin_lock_init(&i->lock);
++ i->irq = up->port.irq;
++ hlist_add_head(&i->node, h);
++ }
++ mutex_unlock(&hash_mutex);
++
++ spin_lock_irq(&i->lock);
++
++ if (i->head) {
++ list_add(&up->list, i->head);
++ spin_unlock_irq(&i->lock);
++
++ ret = 0;
++ } else {
++ INIT_LIST_HEAD(&up->list);
++ i->head = &up->list;
++ spin_unlock_irq(&i->lock);
++ irq_flags |= up->port.irqflags;
++ ret = request_irq(up->port.irq, serial8250_interrupt,
++ irq_flags, "serial", i);
++ if (ret < 0)
++ serial_do_unlink(i, up);
++ }
++
++ return ret;
++}
++
++static void serial_unlink_irq_chain(struct uart_8250_port *up)
++{
++ struct irq_info *i;
++ struct hlist_node *n;
++ struct hlist_head *h;
++
++ mutex_lock(&hash_mutex);
++
++ h = &irq_lists[up->port.irq % NR_IRQ_HASH];
++
++ hlist_for_each(n, h) {
++ i = hlist_entry(n, struct irq_info, node);
++ if (i->irq == up->port.irq)
++ break;
++ }
++
++ BUG_ON(n == NULL);
++ BUG_ON(i->head == NULL);
++
++ if (list_empty(i->head))
++ free_irq(up->port.irq, i);
++
++ serial_do_unlink(i, up);
++ mutex_unlock(&hash_mutex);
++}
++
++/* Base timer interval for polling */
++static inline int poll_timeout(int timeout)
++{
++ return timeout > 6 ? (timeout / 2 - 2) : 1;
++}
++
++/*
++ * This function is used to handle ports that do not have an
++ * interrupt. This doesn't work very well for 16450's, but gives
++ * barely passable results for a 16550A. (Although at the expense
++ * of much CPU overhead).
++ */
++static void serial8250_timeout(unsigned long data)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)data;
++ unsigned int iir;
++
++ iir = serial_in(up, UART_IIR);
++ if (!(iir & UART_IIR_NO_INT))
++ serial8250_handle_port(up);
++ mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
++}
++
++static void serial8250_backup_timeout(unsigned long data)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)data;
++ unsigned int iir, ier = 0, lsr;
++ unsigned long flags;
++
++ /*
++ * Must disable interrupts or else we risk racing with the interrupt
++ * based handler.
++ */
++ if (is_real_interrupt(up->port.irq)) {
++ ier = serial_in(up, UART_IER);
++ serial_out(up, UART_IER, 0);
++ }
++
++ iir = serial_in(up, UART_IIR);
++
++ /*
++ * This should be a safe test for anyone who doesn't trust the
++ * IIR bits on their UART, but it's specifically designed for
++ * the "Diva" UART used on the management processor on many HP
++ * ia64 and parisc boxes.
++ */
++ spin_lock_irqsave(&up->port.lock, flags);
++ lsr = serial_in(up, UART_LSR);
++ up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
++ spin_unlock_irqrestore(&up->port.lock, flags);
++ if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
++ (!uart_circ_empty(&up->port.state->xmit) || up->port.x_char) &&
++ (lsr & UART_LSR_THRE)) {
++ iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
++ iir |= UART_IIR_THRI;
++ }
++
++ if (!(iir & UART_IIR_NO_INT))
++ serial8250_handle_port(up);
++
++ if (is_real_interrupt(up->port.irq))
++ serial_out(up, UART_IER, ier);
++
++ /* Standard timer interval plus 0.2s to keep the port running */
++ mod_timer(&up->timer,
++ jiffies + poll_timeout(up->port.timeout) + HZ / 5);
++}
++
++static unsigned int serial8250_tx_empty(struct uart_port *port)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++ unsigned long flags;
++ unsigned int lsr;
++
++ spin_lock_irqsave(&up->port.lock, flags);
++ lsr = serial_in(up, UART_LSR);
++ up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
++ spin_unlock_irqrestore(&up->port.lock, flags);
++
++ return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
++}
++
++static unsigned int serial8250_get_mctrl(struct uart_port *port)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++ unsigned int status;
++ unsigned int ret;
++
++ status = check_modem_status(up);
++
++ ret = 0;
++ if (status & UART_MSR_DCD)
++ ret |= TIOCM_CAR;
++ if (status & UART_MSR_RI)
++ ret |= TIOCM_RNG;
++ if (status & UART_MSR_DSR)
++ ret |= TIOCM_DSR;
++ if (status & UART_MSR_CTS)
++ ret |= TIOCM_CTS;
++ return ret;
++}
++
++static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++ unsigned char mcr = 0;
++
++ if (mctrl & TIOCM_RTS)
++ mcr |= UART_MCR_RTS;
++ if (mctrl & TIOCM_DTR)
++ mcr |= UART_MCR_DTR;
++ if (mctrl & TIOCM_OUT1)
++ mcr |= UART_MCR_OUT1;
++ if (mctrl & TIOCM_OUT2)
++ mcr |= UART_MCR_OUT2;
++ if (mctrl & TIOCM_LOOP)
++ mcr |= UART_MCR_LOOP;
++
++ mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
++
++ serial_out(up, UART_MCR, mcr);
++}
++
++static void serial8250_break_ctl(struct uart_port *port, int break_state)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++ unsigned long flags;
++
++ spin_lock_irqsave(&up->port.lock, flags);
++ if (break_state == -1)
++ up->lcr |= UART_LCR_SBC;
++ else
++ up->lcr &= ~UART_LCR_SBC;
++ serial_out(up, UART_LCR, up->lcr);
++ spin_unlock_irqrestore(&up->port.lock, flags);
++}
++
++/*
++ * Wait for transmitter & holding register to empty
++ */
++static void wait_for_xmitr(struct uart_8250_port *up, int bits)
++{
++ unsigned int status, tmout = 10000;
++
++ /* Wait up to 10ms for the character(s) to be sent. */
++ do {
++ status = serial_in(up, UART_LSR);
++
++ up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
++
++ if (--tmout == 0)
++ break;
++ udelay(1);
++ } while ((status & bits) != bits);
++
++ /* Wait up to 1s for flow control if necessary */
++ if (up->port.flags & UPF_CONS_FLOW) {
++ unsigned int tmout;
++ for (tmout = 1000000; tmout; tmout--) {
++ unsigned int msr = serial_in(up, UART_MSR);
++ up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
++ if (msr & UART_MSR_CTS)
++ break;
++ udelay(1);
++ touch_nmi_watchdog();
++ }
++ }
++}
++
++#ifdef CONFIG_CONSOLE_POLL
++/*
++ * Console polling routines for writing and reading from the uart while
++ * in an interrupt or debug context.
++ */
++
++static int serial8250_get_poll_char(struct uart_port *port)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++ unsigned char lsr = serial_inp(up, UART_LSR);
++
++ if (!(lsr & UART_LSR_DR))
++ return NO_POLL_CHAR;
++
++ return serial_inp(up, UART_RX);
++}
++
++
++static void serial8250_put_poll_char(struct uart_port *port,
++ unsigned char c)
++{
++ unsigned int ier;
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++
++ /*
++ * First save the IER then disable the interrupts
++ */
++ ier = serial_in(up, UART_IER);
++ if (up->capabilities & UART_CAP_UUE)
++ serial_out(up, UART_IER, UART_IER_UUE);
++ else
++ serial_out(up, UART_IER, 0);
++
++ wait_for_xmitr(up, BOTH_EMPTY);
++ /*
++ * Send the character out.
++ * If a LF, also do CR...
++ */
++ serial_out(up, UART_TX, c);
++ if (c == 10) {
++ wait_for_xmitr(up, BOTH_EMPTY);
++ serial_out(up, UART_TX, 13);
++ }
++
++ /*
++ * Finally, wait for transmitter to become empty
++ * and restore the IER
++ */
++ wait_for_xmitr(up, BOTH_EMPTY);
++ serial_out(up, UART_IER, ier);
++}
++
++#endif /* CONFIG_CONSOLE_POLL */
++
++static int serial8250_startup(struct uart_port *port)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++ unsigned long flags;
++ unsigned char lsr, iir;
++ int retval;
++
++ up->capabilities = uart_config[up->port.type].flags;
++ up->mcr = 0;
++
++ if (up->port.iotype != up->cur_iotype)
++ set_io_from_upio(port);
++
++ if (up->port.type == PORT_16C950) {
++ /* Wake up and initialize UART */
++ up->acr = 0;
++ serial_outp(up, UART_LCR, 0xBF);
++ serial_outp(up, UART_EFR, UART_EFR_ECB);
++ serial_outp(up, UART_IER, 0);
++ serial_outp(up, UART_LCR, 0);
++ serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
++ serial_outp(up, UART_LCR, 0xBF);
++ serial_outp(up, UART_EFR, UART_EFR_ECB);
++ serial_outp(up, UART_LCR, 0);
++ }
++
++#ifdef CONFIG_SERIAL_8250_RSA
++ /*
++ * If this is an RSA port, see if we can kick it up to the
++ * higher speed clock.
++ */
++ enable_rsa(up);
++#endif
++
++ /*
++ * Clear the FIFO buffers and disable them.
++ * (they will be reenabled in set_termios())
++ */
++ serial8250_clear_fifos(up);
++
++ /*
++ * Clear the interrupt registers.
++ */
++ (void) serial_inp(up, UART_LSR);
++ (void) serial_inp(up, UART_RX);
++ (void) serial_inp(up, UART_IIR);
++ (void) serial_inp(up, UART_MSR);
++
++ /*
++ * At this point, there's no way the LSR could still be 0xff;
++ * if it is, then bail out, because there's likely no UART
++ * here.
++ */
++ if (!(up->port.flags & UPF_BUGGY_UART) &&
++ (serial_inp(up, UART_LSR) == 0xff)) {
++ printk(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
++ serial_index(&up->port));
++ return -ENODEV;
++ }
++
++ /*
++ * For a XR16C850, we need to set the trigger levels
++ */
++ if (up->port.type == PORT_16850) {
++ unsigned char fctr;
++
++ serial_outp(up, UART_LCR, 0xbf);
++
++ fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
++ serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX);
++ serial_outp(up, UART_TRG, UART_TRG_96);
++ serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX);
++ serial_outp(up, UART_TRG, UART_TRG_96);
++
++ serial_outp(up, UART_LCR, 0);
++ }
++
++ if (is_real_interrupt(up->port.irq)) {
++ unsigned char iir1;
++ /*
++ * Test for UARTs that do not reassert THRE when the
++ * transmitter is idle and the interrupt has already
++ * been cleared. Real 16550s should always reassert
++ * this interrupt whenever the transmitter is idle and
++ * the interrupt is enabled. Delays are necessary to
++ * allow register changes to become visible.
++ */
++ spin_lock_irqsave(&up->port.lock, flags);
++ if (up->port.irqflags & IRQF_SHARED)
++ disable_irq_nosync(up->port.irq);
++
++ wait_for_xmitr(up, UART_LSR_THRE);
++ serial_out_sync(up, UART_IER, UART_IER_THRI);
++ udelay(1); /* allow THRE to set */
++ iir1 = serial_in(up, UART_IIR);
++ serial_out(up, UART_IER, 0);
++ serial_out_sync(up, UART_IER, UART_IER_THRI);
++ udelay(1); /* allow a working UART time to re-assert THRE */
++ iir = serial_in(up, UART_IIR);
++ serial_out(up, UART_IER, 0);
++
++ if (up->port.irqflags & IRQF_SHARED)
++ enable_irq(up->port.irq);
++ spin_unlock_irqrestore(&up->port.lock, flags);
++
++ /*
++ * If the interrupt is not reasserted, setup a timer to
++ * kick the UART on a regular basis.
++ */
++ if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) {
++ up->bugs |= UART_BUG_THRE;
++ pr_debug("ttyS%d - using backup timer\n",
++ serial_index(port));
++ }
++ }
++
++ /*
++ * The above check will only give an accurate result the first time
++ * the port is opened so this value needs to be preserved.
++ */
++ if (up->bugs & UART_BUG_THRE) {
++ up->timer.function = serial8250_backup_timeout;
++ up->timer.data = (unsigned long)up;
++ mod_timer(&up->timer, jiffies +
++ poll_timeout(up->port.timeout) + HZ / 5);
++ }
++
++ /*
++ * If the "interrupt" for this port doesn't correspond with any
++ * hardware interrupt, we use a timer-based system. The original
++ * driver used to do this with IRQ0.
++ */
++ if (!is_real_interrupt(up->port.irq)) {
++ up->timer.data = (unsigned long)up;
++ mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
++ } else {
++ retval = serial_link_irq_chain(up);
++ if (retval)
++ return retval;
++ }
++
++ /*
++ * Now, initialize the UART
++ */
++ serial_outp(up, UART_LCR, UART_LCR_WLEN8);
++
++ spin_lock_irqsave(&up->port.lock, flags);
++ if (up->port.flags & UPF_FOURPORT) {
++ if (!is_real_interrupt(up->port.irq))
++ up->port.mctrl |= TIOCM_OUT1;
++ } else
++ /*
++ * Most PC uarts need OUT2 raised to enable interrupts.
++ */
++ if (is_real_interrupt(up->port.irq))
++ up->port.mctrl |= TIOCM_OUT2;
++
++ serial8250_set_mctrl(&up->port, up->port.mctrl);
++
++ /* Serial over Lan (SoL) hack:
++ Intel 8257x Gigabit ethernet chips have a
++ 16550 emulation, to be used for Serial Over Lan.
++ Those chips take a longer time than a normal
++ serial device to signalize that a transmission
++ data was queued. Due to that, the above test generally
++ fails. One solution would be to delay the reading of
++ iir. However, this is not reliable, since the timeout
++ is variable. So, let's just don't test if we receive
++ TX irq. This way, we'll never enable UART_BUG_TXEN.
++ */
++ if (skip_txen_test || up->port.flags & UPF_NO_TXEN_TEST)
++ goto dont_test_tx_en;
++
++ /*
++ * Do a quick test to see if we receive an
++ * interrupt when we enable the TX irq.
++ */
++ serial_outp(up, UART_IER, UART_IER_THRI);
++ lsr = serial_in(up, UART_LSR);
++ iir = serial_in(up, UART_IIR);
++ serial_outp(up, UART_IER, 0);
++
++ if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
++ if (!(up->bugs & UART_BUG_TXEN)) {
++ up->bugs |= UART_BUG_TXEN;
++ pr_debug("ttyS%d - enabling bad tx status workarounds\n",
++ serial_index(port));
++ }
++ } else {
++ up->bugs &= ~UART_BUG_TXEN;
++ }
++
++dont_test_tx_en:
++ spin_unlock_irqrestore(&up->port.lock, flags);
++
++ /*
++ * Clear the interrupt registers again for luck, and clear the
++ * saved flags to avoid getting false values from polling
++ * routines or the previous session.
++ */
++ serial_inp(up, UART_LSR);
++ serial_inp(up, UART_RX);
++ serial_inp(up, UART_IIR);
++ serial_inp(up, UART_MSR);
++ up->lsr_saved_flags = 0;
++ up->msr_saved_flags = 0;
++
++ /*
++ * Finally, enable interrupts. Note: Modem status interrupts
++ * are set via set_termios(), which will be occurring imminently
++ * anyway, so we don't enable them here.
++ */
++ up->ier = UART_IER_RLSI | UART_IER_RDI;
++ serial_outp(up, UART_IER, up->ier);
++
++ if (up->port.flags & UPF_FOURPORT) {
++ unsigned int icp;
++ /*
++ * Enable interrupts on the AST Fourport board
++ */
++ icp = (up->port.iobase & 0xfe0) | 0x01f;
++ outb_p(0x80, icp);
++ (void) inb_p(icp);
++ }
++
++ return 0;
++}
++
++static void serial8250_shutdown(struct uart_port *port)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++ unsigned long flags;
++
++ /*
++ * Disable interrupts from this port
++ */
++ up->ier = 0;
++ serial_outp(up, UART_IER, 0);
++
++ spin_lock_irqsave(&up->port.lock, flags);
++ if (up->port.flags & UPF_FOURPORT) {
++ /* reset interrupts on the AST Fourport board */
++ inb((up->port.iobase & 0xfe0) | 0x1f);
++ up->port.mctrl |= TIOCM_OUT1;
++ } else
++ up->port.mctrl &= ~TIOCM_OUT2;
++
++ serial8250_set_mctrl(&up->port, up->port.mctrl);
++ spin_unlock_irqrestore(&up->port.lock, flags);
++
++ /*
++ * Disable break condition and FIFOs
++ */
++ serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
++ serial8250_clear_fifos(up);
++
++#ifdef CONFIG_SERIAL_8250_RSA
++ /*
++ * Reset the RSA board back to 115kbps compat mode.
++ */
++ disable_rsa(up);
++#endif
++
++ /*
++ * Read data port to reset things, and then unlink from
++ * the IRQ chain.
++ */
++ (void) serial_in(up, UART_RX);
++
++ del_timer_sync(&up->timer);
++ up->timer.function = serial8250_timeout;
++ if (is_real_interrupt(up->port.irq))
++ serial_unlink_irq_chain(up);
++}
++
++static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
++{
++ unsigned int quot;
++
++ /*
++ * Handle magic divisors for baud rates above baud_base on
++ * SMSC SuperIO chips.
++ */
++ if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
++ baud == (port->uartclk/4))
++ quot = 0x8001;
++ else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
++ baud == (port->uartclk/8))
++ quot = 0x8002;
++ else
++ quot = uart_get_divisor(port, baud);
++
++ return quot;
++}
++
++static void
++serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
++ struct ktermios *old)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++ unsigned char cval, fcr = 0;
++ unsigned long flags;
++ unsigned int baud, quot;
++
++ switch (termios->c_cflag & CSIZE) {
++ case CS5:
++ cval = UART_LCR_WLEN5;
++ break;
++ case CS6:
++ cval = UART_LCR_WLEN6;
++ break;
++ case CS7:
++ cval = UART_LCR_WLEN7;
++ break;
++ default:
++ case CS8:
++ cval = UART_LCR_WLEN8;
++ break;
++ }
++
++ if (termios->c_cflag & CSTOPB)
++ cval |= UART_LCR_STOP;
++ if (termios->c_cflag & PARENB)
++ cval |= UART_LCR_PARITY;
++ if (!(termios->c_cflag & PARODD))
++ cval |= UART_LCR_EPAR;
++#ifdef CMSPAR
++ if (termios->c_cflag & CMSPAR)
++ cval |= UART_LCR_SPAR;
++#endif
++
++ /*
++ * Ask the core to calculate the divisor for us.
++ */
++ baud = uart_get_baud_rate(port, termios, old,
++ port->uartclk / 16 / 0xffff,
++ port->uartclk / 16);
++ quot = serial8250_get_divisor(port, baud);
++
++ /*
++ * Oxford Semi 952 rev B workaround
++ */
++ if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
++ quot++;
++
++ if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
++ if (baud < 2400)
++ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
++ else
++ fcr = uart_config[up->port.type].fcr;
++ }
++
++ /*
++ * MCR-based auto flow control. When AFE is enabled, RTS will be
++ * deasserted when the receive FIFO contains more characters than
++ * the trigger, or the MCR RTS bit is cleared. In the case where
++ * the remote UART is not using CTS auto flow control, we must
++ * have sufficient FIFO entries for the latency of the remote
++ * UART to respond. IOW, at least 32 bytes of FIFO.
++ */
++ if (up->capabilities & UART_CAP_AFE && up->port.fifosize >= 32) {
++ up->mcr &= ~UART_MCR_AFE;
++ if (termios->c_cflag & CRTSCTS)
++ up->mcr |= UART_MCR_AFE;
++ }
++
++ /*
++ * Ok, we're now changing the port state. Do it with
++ * interrupts disabled.
++ */
++ spin_lock_irqsave(&up->port.lock, flags);
++
++ /*
++ * Update the per-port timeout.
++ */
++ uart_update_timeout(port, termios->c_cflag, baud);
++
++ up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
++ if (termios->c_iflag & INPCK)
++ up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
++ if (termios->c_iflag & (BRKINT | PARMRK))
++ up->port.read_status_mask |= UART_LSR_BI;
++
++ /*
++ * Characteres to ignore
++ */
++ up->port.ignore_status_mask = 0;
++ if (termios->c_iflag & IGNPAR)
++ up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
++ if (termios->c_iflag & IGNBRK) {
++ up->port.ignore_status_mask |= UART_LSR_BI;
++ /*
++ * If we're ignoring parity and break indicators,
++ * ignore overruns too (for real raw support).
++ */
++ if (termios->c_iflag & IGNPAR)
++ up->port.ignore_status_mask |= UART_LSR_OE;
++ }
++
++ /*
++ * ignore all characters if CREAD is not set
++ */
++ if ((termios->c_cflag & CREAD) == 0)
++ up->port.ignore_status_mask |= UART_LSR_DR;
++
++ /*
++ * CTS flow control flag and modem status interrupts
++ */
++ up->ier &= ~UART_IER_MSI;
++ if (!(up->bugs & UART_BUG_NOMSR) &&
++ UART_ENABLE_MS(&up->port, termios->c_cflag))
++ up->ier |= UART_IER_MSI;
++ if (up->capabilities & UART_CAP_UUE)
++ up->ier |= UART_IER_UUE | UART_IER_RTOIE;
++
++ serial_out(up, UART_IER, up->ier);
++
++ if (up->capabilities & UART_CAP_EFR) {
++ unsigned char efr = 0;
++ /*
++ * TI16C752/Startech hardware flow control. FIXME:
++ * - TI16C752 requires control thresholds to be set.
++ * - UART_MCR_RTS is ineffective if auto-RTS mode is enabled.
++ */
++ if (termios->c_cflag & CRTSCTS)
++ efr |= UART_EFR_CTS;
++
++ serial_outp(up, UART_LCR, 0xBF);
++ serial_outp(up, UART_EFR, efr);
++ }
++
++#ifdef CONFIG_ARCH_OMAP
++ /* Workaround to enable 115200 baud on OMAP1510 internal ports */
++ if (cpu_is_omap1510() && is_omap_port(up)) {
++ if (baud == 115200) {
++ quot = 1;
++ serial_out(up, UART_OMAP_OSC_12M_SEL, 1);
++ } else
++ serial_out(up, UART_OMAP_OSC_12M_SEL, 0);
++ }
++#endif
++
++ if (up->capabilities & UART_NATSEMI) {
++ /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */
++ serial_outp(up, UART_LCR, 0xe0);
++ } else {
++ serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
++ }
++
++ serial_dl_write(up, quot);
++
++ /*
++ * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
++ * is written without DLAB set, this mode will be disabled.
++ */
++ if (up->port.type == PORT_16750)
++ serial_outp(up, UART_FCR, fcr);
++
++ serial_outp(up, UART_LCR, cval); /* reset DLAB */
++ up->lcr = cval; /* Save LCR */
++ if (up->port.type != PORT_16750) {
++ if (fcr & UART_FCR_ENABLE_FIFO) {
++ /* emulated UARTs (Lucent Venus 167x) need two steps */
++ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
++ }
++ serial_outp(up, UART_FCR, fcr); /* set fcr */
++ }
++ serial8250_set_mctrl(&up->port, up->port.mctrl);
++ spin_unlock_irqrestore(&up->port.lock, flags);
++ /* Don't rewrite B0 */
++ if (tty_termios_baud_rate(termios))
++ tty_termios_encode_baud_rate(termios, baud, baud);
++}
++
++static void
++serial8250_set_ldisc(struct uart_port *port)
++{
++ int line = port->line;
++
++ if (line >= port->state->port.tty->driver->num)
++ return;
++
++ if (port->state->port.tty->ldisc->ops->num == N_PPS) {
++ port->flags |= UPF_HARDPPS_CD;
++ serial8250_enable_ms(port);
++ } else
++ port->flags &= ~UPF_HARDPPS_CD;
++}
++
++static void
++serial8250_pm(struct uart_port *port, unsigned int state,
++ unsigned int oldstate)
++{
++ struct uart_8250_port *p = (struct uart_8250_port *)port;
++
++ serial8250_set_sleep(p, state != 0);
++
++ if (p->pm)
++ p->pm(port, state, oldstate);
++}
++
++static unsigned int serial8250_port_size(struct uart_8250_port *pt)
++{
++ if (pt->port.iotype == UPIO_AU)
++ return 0x1000;
++#ifdef CONFIG_ARCH_OMAP
++ if (is_omap_port(pt))
++ return 0x16 << pt->port.regshift;
++#endif
++ return 8 << pt->port.regshift;
++}
++
++/*
++ * Resource handling.
++ */
++static int serial8250_request_std_resource(struct uart_8250_port *up)
++{
++ unsigned int size = serial8250_port_size(up);
++ int ret = 0;
++
++ switch (up->port.iotype) {
++ case UPIO_AU:
++ case UPIO_TSI:
++ case UPIO_MEM32:
++ case UPIO_MEM:
++ case UPIO_DWAPB:
++ if (!up->port.mapbase)
++ break;
++
++ if (!request_mem_region(up->port.mapbase, size, "serial")) {
++ ret = -EBUSY;
++ break;
++ }
++
++ if (up->port.flags & UPF_IOREMAP) {
++ up->port.membase = ioremap_nocache(up->port.mapbase,
++ size);
++ if (!up->port.membase) {
++ release_mem_region(up->port.mapbase, size);
++ ret = -ENOMEM;
++ }
++ }
++ break;
++
++ case UPIO_HUB6:
++ case UPIO_PORT:
++ if (!request_region(up->port.iobase, size, "serial"))
++ ret = -EBUSY;
++ break;
++ }
++ return ret;
++}
++
++static void serial8250_release_std_resource(struct uart_8250_port *up)
++{
++ unsigned int size = serial8250_port_size(up);
++
++ switch (up->port.iotype) {
++ case UPIO_AU:
++ case UPIO_TSI:
++ case UPIO_MEM32:
++ case UPIO_MEM:
++ case UPIO_DWAPB:
++ if (!up->port.mapbase)
++ break;
++
++ if (up->port.flags & UPF_IOREMAP) {
++ iounmap(up->port.membase);
++ up->port.membase = NULL;
++ }
++
++ release_mem_region(up->port.mapbase, size);
++ break;
++
++ case UPIO_HUB6:
++ case UPIO_PORT:
++ release_region(up->port.iobase, size);
++ break;
++ }
++}
++
++static int serial8250_request_rsa_resource(struct uart_8250_port *up)
++{
++ unsigned long start = UART_RSA_BASE << up->port.regshift;
++ unsigned int size = 8 << up->port.regshift;
++ int ret = -EINVAL;
++
++ switch (up->port.iotype) {
++ case UPIO_HUB6:
++ case UPIO_PORT:
++ start += up->port.iobase;
++ if (request_region(start, size, "serial-rsa"))
++ ret = 0;
++ else
++ ret = -EBUSY;
++ break;
++ }
++
++ return ret;
++}
++
++static void serial8250_release_rsa_resource(struct uart_8250_port *up)
++{
++ unsigned long offset = UART_RSA_BASE << up->port.regshift;
++ unsigned int size = 8 << up->port.regshift;
++
++ switch (up->port.iotype) {
++ case UPIO_HUB6:
++ case UPIO_PORT:
++ release_region(up->port.iobase + offset, size);
++ break;
++ }
++}
++
++static void serial8250_release_port(struct uart_port *port)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++
++ serial8250_release_std_resource(up);
++ if (up->port.type == PORT_RSA)
++ serial8250_release_rsa_resource(up);
++}
++
++static int serial8250_request_port(struct uart_port *port)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++ int ret = 0;
++
++ ret = serial8250_request_std_resource(up);
++ if (ret == 0 && up->port.type == PORT_RSA) {
++ ret = serial8250_request_rsa_resource(up);
++ if (ret < 0)
++ serial8250_release_std_resource(up);
++ }
++
++ return ret;
++}
++
++static void serial8250_config_port(struct uart_port *port, int flags)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++ int probeflags = PROBE_ANY;
++ int ret;
++
++ /*
++ * Find the region that we can probe for. This in turn
++ * tells us whether we can probe for the type of port.
++ */
++ ret = serial8250_request_std_resource(up);
++ if (ret < 0)
++ return;
++
++ ret = serial8250_request_rsa_resource(up);
++ if (ret < 0)
++ probeflags &= ~PROBE_RSA;
++
++ if (up->port.iotype != up->cur_iotype)
++ set_io_from_upio(port);
++
++ if (flags & UART_CONFIG_TYPE)
++ autoconfig(up, probeflags);
++
++#ifdef CONFIG_SERIAL_8250_AU1X00
++ /* if access method is AU, it is a 16550 with a quirk */
++ if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU)
++ up->bugs |= UART_BUG_NOMSR;
++#endif
++
++ if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
++ autoconfig_irq(up);
++
++ if (up->port.type != PORT_RSA && probeflags & PROBE_RSA)
++ serial8250_release_rsa_resource(up);
++ if (up->port.type == PORT_UNKNOWN)
++ serial8250_release_std_resource(up);
++}
++
++static int
++serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
++{
++ if (ser->irq >= nr_irqs || ser->irq < 0 ||
++ ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
++ ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
++ ser->type == PORT_STARTECH)
++ return -EINVAL;
++ return 0;
++}
++
++static const char *
++serial8250_type(struct uart_port *port)
++{
++ int type = port->type;
++
++ if (type >= ARRAY_SIZE(uart_config))
++ type = 0;
++ return uart_config[type].name;
++}
++
++static struct uart_ops serial8250_pops = {
++ .tx_empty = serial8250_tx_empty,
++ .set_mctrl = serial8250_set_mctrl,
++ .get_mctrl = serial8250_get_mctrl,
++ .stop_tx = serial8250_stop_tx,
++ .start_tx = serial8250_start_tx,
++ .stop_rx = serial8250_stop_rx,
++ .enable_ms = serial8250_enable_ms,
++ .break_ctl = serial8250_break_ctl,
++ .startup = serial8250_startup,
++ .shutdown = serial8250_shutdown,
++ .set_termios = serial8250_set_termios,
++ .set_ldisc = serial8250_set_ldisc,
++ .pm = serial8250_pm,
++ .type = serial8250_type,
++ .release_port = serial8250_release_port,
++ .request_port = serial8250_request_port,
++ .config_port = serial8250_config_port,
++ .verify_port = serial8250_verify_port,
++#ifdef CONFIG_CONSOLE_POLL
++ .poll_get_char = serial8250_get_poll_char,
++ .poll_put_char = serial8250_put_poll_char,
++#endif
++};
++
++static struct uart_8250_port serial8250_ports[UART_NR];
++
++static void __init serial8250_isa_init_ports(void)
++{
++ struct uart_8250_port *up;
++ static int first = 1;
++ int i, irqflag = 0;
++
++ if (!first)
++ return;
++ first = 0;
++
++ for (i = 0; i < nr_uarts; i++) {
++ struct uart_8250_port *up = &serial8250_ports[i];
++
++ up->port.line = i;
++ spin_lock_init(&up->port.lock);
++
++ init_timer(&up->timer);
++ up->timer.function = serial8250_timeout;
++
++ /*
++ * ALPHA_KLUDGE_MCR needs to be killed.
++ */
++ up->mcr_mask = ~ALPHA_KLUDGE_MCR;
++ up->mcr_force = ALPHA_KLUDGE_MCR;
++
++ up->port.ops = &serial8250_pops;
++ }
++
++ if (share_irqs)
++ irqflag = IRQF_SHARED;
++
++ for (i = 0, up = serial8250_ports;
++ i < ARRAY_SIZE(old_serial_port) && i < nr_uarts;
++ i++, up++) {
++ up->port.iobase = old_serial_port[i].port;
++ up->port.irq = irq_canonicalize(old_serial_port[i].irq);
++ up->port.irqflags = old_serial_port[i].irqflags;
++ up->port.uartclk = old_serial_port[i].baud_base * 16;
++ up->port.flags = old_serial_port[i].flags;
++ up->port.hub6 = old_serial_port[i].hub6;
++ up->port.membase = old_serial_port[i].iomem_base;
++ up->port.iotype = old_serial_port[i].io_type;
++ up->port.regshift = old_serial_port[i].iomem_reg_shift;
++ set_io_from_upio(&up->port);
++ up->port.irqflags |= irqflag;
++ }
++}
++
++static void
++serial8250_init_fixed_type_port(struct uart_8250_port *up, unsigned int type)
++{
++ up->port.type = type;
++ up->port.fifosize = uart_config[type].fifo_size;
++ up->capabilities = uart_config[type].flags;
++ up->tx_loadsz = uart_config[type].tx_loadsz;
++}
++
++static void __init
++serial8250_register_ports(struct uart_driver *drv, struct device *dev)
++{
++ int i;
++
++ for (i = 0; i < nr_uarts; i++) {
++ struct uart_8250_port *up = &serial8250_ports[i];
++ up->cur_iotype = 0xFF;
++ }
++
++ serial8250_isa_init_ports();
++
++ for (i = 0; i < nr_uarts; i++) {
++ struct uart_8250_port *up = &serial8250_ports[i];
++
++ up->port.dev = dev;
++
++ if (up->port.flags & UPF_FIXED_TYPE)
++ serial8250_init_fixed_type_port(up, up->port.type);
++
++ uart_add_one_port(drv, &up->port);
++ }
++}
++
++#ifdef CONFIG_SERIAL_8250_CONSOLE
++
++static void serial8250_console_putchar(struct uart_port *port, int ch)
++{
++ struct uart_8250_port *up = (struct uart_8250_port *)port;
++
++ wait_for_xmitr(up, UART_LSR_THRE);
++ serial_out(up, UART_TX, ch);
++}
++
++/*
++ * Print a string to the serial port trying not to disturb
++ * any possible real use of the port...
++ *
++ * The console_lock must be held when we get here.
++ */
++static void
++serial8250_console_write(struct console *co, const char *s, unsigned int count)
++{
++ struct uart_8250_port *up = &serial8250_ports[co->index];
++ unsigned long flags;
++ unsigned int ier;
++ int locked = 1;
++
++ touch_nmi_watchdog();
++
++ local_irq_save(flags);
++ if (up->port.sysrq) {
++ /* serial8250_handle_port() already took the lock */
++ locked = 0;
++ } else if (oops_in_progress) {
++ locked = spin_trylock(&up->port.lock);
++ } else
++ spin_lock(&up->port.lock);
++
++ /*
++ * First save the IER then disable the interrupts
++ */
++ ier = serial_in(up, UART_IER);
++
++ if (up->capabilities & UART_CAP_UUE)
++ serial_out(up, UART_IER, UART_IER_UUE);
++ else
++ serial_out(up, UART_IER, 0);
++
++ uart_console_write(&up->port, s, count, serial8250_console_putchar);
++
++ /*
++ * Finally, wait for transmitter to become empty
++ * and restore the IER
++ */
++ wait_for_xmitr(up, BOTH_EMPTY);
++ serial_out(up, UART_IER, ier);
++
++ /*
++ * The receive handling will happen properly because the
++ * receive ready bit will still be set; it is not cleared
++ * on read. However, modem control will not, we must
++ * call it if we have saved something in the saved flags
++ * while processing with interrupts off.
++ */
++ if (up->msr_saved_flags)
++ check_modem_status(up);
++
++ if (locked)
++ spin_unlock(&up->port.lock);
++ local_irq_restore(flags);
++}
++
++static int __init serial8250_console_setup(struct console *co, char *options)
++{
++ struct uart_port *port;
++ int baud = 9600;
++ int bits = 8;
++ int parity = 'n';
++ int flow = 'n';
++
++ /*
++ * Check whether an invalid uart number has been specified, and
++ * if so, search for the first available port that does have
++ * console support.
++ */
++ if (co->index >= nr_uarts)
++ co->index = 0;
++ port = &serial8250_ports[co->index].port;
++ if (!port->iobase && !port->membase)
++ return -ENODEV;
++
++ if (options)
++ uart_parse_options(options, &baud, &parity, &bits, &flow);
++
++ return uart_set_options(port, co, baud, parity, bits, flow);
++}
++
++static int serial8250_console_early_setup(void)
++{
++ return serial8250_find_port_for_earlycon();
++}
++
++static struct console serial8250_console = {
++ .name = "ttyS",
++ .write = serial8250_console_write,
++ .device = uart_console_device,
++ .setup = serial8250_console_setup,
++ .early_setup = serial8250_console_early_setup,
++ .flags = CON_PRINTBUFFER,
++ .index = -1,
++ .data = &serial8250_reg,
++};
++
++static int __init serial8250_console_init(void)
++{
++ if (nr_uarts > UART_NR)
++ nr_uarts = UART_NR;
++
++ serial8250_isa_init_ports();
++ register_console(&serial8250_console);
++ return 0;
++}
++console_initcall(serial8250_console_init);
++
++int serial8250_find_port(struct uart_port *p)
++{
++ int line;
++ struct uart_port *port;
++
++ for (line = 0; line < nr_uarts; line++) {
++ port = &serial8250_ports[line].port;
++ if (uart_match_port(p, port))
++ return line;
++ }
++ return -ENODEV;
++}
++
++#define SERIAL8250_CONSOLE &serial8250_console
++#else
++#define SERIAL8250_CONSOLE NULL
++#endif
++
++static struct uart_driver serial8250_reg = {
++ .owner = THIS_MODULE,
++ .driver_name = "serial",
++ .dev_name = "ttyS",
++ .major = TTY_MAJOR,
++ .minor = 64,
++ .cons = SERIAL8250_CONSOLE,
++};
++
++/*
++ * early_serial_setup - early registration for 8250 ports
++ *
++ * Setup an 8250 port structure prior to console initialisation. Use
++ * after console initialisation will cause undefined behaviour.
++ */
++int __init early_serial_setup(struct uart_port *port)
++{
++ struct uart_port *p;
++
++ if (port->line >= ARRAY_SIZE(serial8250_ports))
++ return -ENODEV;
++
++ serial8250_isa_init_ports();
++ p = &serial8250_ports[port->line].port;
++ p->iobase = port->iobase;
++ p->membase = port->membase;
++ p->irq = port->irq;
++ p->irqflags = port->irqflags;
++ p->uartclk = port->uartclk;
++ p->fifosize = port->fifosize;
++ p->regshift = port->regshift;
++ p->iotype = port->iotype;
++ p->flags = port->flags;
++ p->mapbase = port->mapbase;
++ p->private_data = port->private_data;
++ p->type = port->type;
++ p->line = port->line;
++
++ set_io_from_upio(p);
++ if (port->serial_in)
++ p->serial_in = port->serial_in;
++ if (port->serial_out)
++ p->serial_out = port->serial_out;
++
++ return 0;
++}
++
++/**
++ * serial8250_suspend_port - suspend one serial port
++ * @line: serial line number
++ *
++ * Suspend one serial port.
++ */
++void serial8250_suspend_port(int line)
++{
++ uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port);
++}
++
++/**
++ * serial8250_resume_port - resume one serial port
++ * @line: serial line number
++ *
++ * Resume one serial port.
++ */
++void serial8250_resume_port(int line)
++{
++ struct uart_8250_port *up = &serial8250_ports[line];
++
++ if (up->capabilities & UART_NATSEMI) {
++ unsigned char tmp;
++
++ /* Ensure it's still in high speed mode */
++ serial_outp(up, UART_LCR, 0xE0);
++
++ tmp = serial_in(up, 0x04); /* EXCR2 */
++ tmp &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
++ tmp |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
++ serial_outp(up, 0x04, tmp);
++
++ serial_outp(up, UART_LCR, 0);
++ }
++ uart_resume_port(&serial8250_reg, &up->port);
++}
++
++/*
++ * Register a set of serial devices attached to a platform device. The
++ * list is terminated with a zero flags entry, which means we expect
++ * all entries to have at least UPF_BOOT_AUTOCONF set.
++ */
++static int __devinit serial8250_probe(struct platform_device *dev)
++{
++ struct plat_serial8250_port *p = dev->dev.platform_data;
++ struct uart_port port;
++ int ret, i, irqflag = 0;
++
++ memset(&port, 0, sizeof(struct uart_port));
++
++ if (share_irqs)
++ irqflag = IRQF_SHARED;
++
++ for (i = 0; p && p->flags != 0; p++, i++) {
++ port.iobase = p->iobase;
++ port.membase = p->membase;
++ port.irq = p->irq;
++ port.irqflags = p->irqflags;
++ port.uartclk = p->uartclk;
++ port.regshift = p->regshift;
++ port.iotype = p->iotype;
++ port.flags = p->flags;
++ port.mapbase = p->mapbase;
++ port.hub6 = p->hub6;
++ port.private_data = p->private_data;
++ port.type = p->type;
++ port.serial_in = p->serial_in;
++ port.serial_out = p->serial_out;
++ port.dev = &dev->dev;
++ port.irqflags |= irqflag;
++ ret = serial8250_register_port(&port);
++ if (ret < 0) {
++ dev_err(&dev->dev, "unable to register port at index %d "
++ "(IO%lx MEM%llx IRQ%d): %d\n", i,
++ p->iobase, (unsigned long long)p->mapbase,
++ p->irq, ret);
++ }
++ }
++ return 0;
++}
++
++/*
++ * Remove serial ports registered against a platform device.
++ */
++static int __devexit serial8250_remove(struct platform_device *dev)
++{
++ int i;
++
++ for (i = 0; i < nr_uarts; i++) {
++ struct uart_8250_port *up = &serial8250_ports[i];
++
++ if (up->port.dev == &dev->dev)
++ serial8250_unregister_port(i);
++ }
++ return 0;
++}
++
++static int serial8250_suspend(struct platform_device *dev, pm_message_t state)
++{
++ int i;
++
++ for (i = 0; i < UART_NR; i++) {
++ struct uart_8250_port *up = &serial8250_ports[i];
++
++ if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
++ uart_suspend_port(&serial8250_reg, &up->port);
++ }
++
++ return 0;
++}
++
++static int serial8250_resume(struct platform_device *dev)
++{
++ int i;
++
++ for (i = 0; i < UART_NR; i++) {
++ struct uart_8250_port *up = &serial8250_ports[i];
++
++ if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
++ serial8250_resume_port(i);
++ }
++
++ return 0;
++}
++
++static struct platform_driver serial8250_isa_driver = {
++ .probe = serial8250_probe,
++ .remove = __devexit_p(serial8250_remove),
++ .suspend = serial8250_suspend,
++ .resume = serial8250_resume,
++ .driver = {
++ .name = "serial8250",
++ .owner = THIS_MODULE,
++ },
++};
++
++/*
++ * This "device" covers _all_ ISA 8250-compatible serial devices listed
++ * in the table in include/asm/serial.h
++ */
++static struct platform_device *serial8250_isa_devs;
++
++/*
++ * serial8250_register_port and serial8250_unregister_port allows for
++ * 16x50 serial ports to be configured at run-time, to support PCMCIA
++ * modems and PCI multiport cards.
++ */
++static DEFINE_MUTEX(serial_mutex);
++
++static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port)
++{
++ int i;
++
++ /*
++ * First, find a port entry which matches.
++ */
++ for (i = 0; i < nr_uarts; i++)
++ if (uart_match_port(&serial8250_ports[i].port, port))
++ return &serial8250_ports[i];
++
++ /*
++ * We didn't find a matching entry, so look for the first
++ * free entry. We look for one which hasn't been previously
++ * used (indicated by zero iobase).
++ */
++ for (i = 0; i < nr_uarts; i++)
++ if (serial8250_ports[i].port.type == PORT_UNKNOWN &&
++ serial8250_ports[i].port.iobase == 0)
++ return &serial8250_ports[i];
++
++ /*
++ * That also failed. Last resort is to find any entry which
++ * doesn't have a real port associated with it.
++ */
++ for (i = 0; i < nr_uarts; i++)
++ if (serial8250_ports[i].port.type == PORT_UNKNOWN)
++ return &serial8250_ports[i];
++
++ return NULL;
++}
++
++/**
++ * serial8250_register_port - register a serial port
++ * @port: serial port template
++ *
++ * Configure the serial port specified by the request. If the
++ * port exists and is in use, it is hung up and unregistered
++ * first.
++ *
++ * The port is then probed and if necessary the IRQ is autodetected
++ * If this fails an error is returned.
++ *
++ * On success the port is ready to use and the line number is returned.
++ */
++int serial8250_register_port(struct uart_port *port)
++{
++ struct uart_8250_port *uart;
++ int ret = -ENOSPC;
++
++ if (port->uartclk == 0)
++ return -EINVAL;
++
++ mutex_lock(&serial_mutex);
++
++ uart = serial8250_find_match_or_unused(port);
++ if (uart) {
++ uart_remove_one_port(&serial8250_reg, &uart->port);
++
++ uart->port.iobase = port->iobase;
++ uart->port.membase = port->membase;
++ uart->port.irq = port->irq;
++ uart->port.irqflags = port->irqflags;
++ uart->port.uartclk = port->uartclk;
++ uart->port.fifosize = port->fifosize;
++ uart->port.regshift = port->regshift;
++ uart->port.iotype = port->iotype;
++ uart->port.flags = port->flags | UPF_BOOT_AUTOCONF;
++ uart->port.mapbase = port->mapbase;
++ uart->port.private_data = port->private_data;
++ if (port->dev)
++ uart->port.dev = port->dev;
++
++ if (port->flags & UPF_FIXED_TYPE)
++ serial8250_init_fixed_type_port(uart, port->type);
++
++ set_io_from_upio(&uart->port);
++ /* Possibly override default I/O functions. */
++ if (port->serial_in)
++ uart->port.serial_in = port->serial_in;
++ if (port->serial_out)
++ uart->port.serial_out = port->serial_out;
++
++ ret = uart_add_one_port(&serial8250_reg, &uart->port);
++ if (ret == 0)
++ ret = uart->port.line;
++ }
++ mutex_unlock(&serial_mutex);
++
++ return ret;
++}
++EXPORT_SYMBOL(serial8250_register_port);
++
++/**
++ * serial8250_unregister_port - remove a 16x50 serial port at runtime
++ * @line: serial line number
++ *
++ * Remove one serial port. This may not be called from interrupt
++ * context. We hand the port back to the our control.
++ */
++void serial8250_unregister_port(int line)
++{
++ struct uart_8250_port *uart = &serial8250_ports[line];
++
++ mutex_lock(&serial_mutex);
++ uart_remove_one_port(&serial8250_reg, &uart->port);
++ if (serial8250_isa_devs) {
++ uart->port.flags &= ~UPF_BOOT_AUTOCONF;
++ uart->port.type = PORT_UNKNOWN;
++ uart->port.dev = &serial8250_isa_devs->dev;
++ uart_add_one_port(&serial8250_reg, &uart->port);
++ } else {
++ uart->port.dev = NULL;
++ }
++ mutex_unlock(&serial_mutex);
++}
++EXPORT_SYMBOL(serial8250_unregister_port);
++
++static int __init serial8250_init(void)
++{
++ int ret;
++
++ if (nr_uarts > UART_NR)
++ nr_uarts = UART_NR;
++
++ printk(KERN_INFO "Serial: 8250/16550 driver, "
++ "%d ports, IRQ sharing %sabled\n", nr_uarts,
++ share_irqs ? "en" : "dis");
++
++#ifdef CONFIG_SPARC
++ ret = sunserial_register_minors(&serial8250_reg, UART_NR);
++#else
++ serial8250_reg.nr = UART_NR;
++ ret = uart_register_driver(&serial8250_reg);
++#endif
++ if (ret)
++ goto out;
++
++ serial8250_isa_devs = platform_device_alloc("serial8250",
++ PLAT8250_DEV_LEGACY);
++ if (!serial8250_isa_devs) {
++ ret = -ENOMEM;
++ goto unreg_uart_drv;
++ }
++
++ ret = platform_device_add(serial8250_isa_devs);
++ if (ret)
++ goto put_dev;
++
++ serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev);
++
++ ret = platform_driver_register(&serial8250_isa_driver);
++ if (ret == 0)
++ goto out;
++
++ platform_device_del(serial8250_isa_devs);
++put_dev:
++ platform_device_put(serial8250_isa_devs);
++unreg_uart_drv:
++#ifdef CONFIG_SPARC
++ sunserial_unregister_minors(&serial8250_reg, UART_NR);
++#else
++ uart_unregister_driver(&serial8250_reg);
++#endif
++out:
++ return ret;
++}
++
++static void __exit serial8250_exit(void)
++{
++ struct platform_device *isa_dev = serial8250_isa_devs;
++
++ /*
++ * This tells serial8250_unregister_port() not to re-register
++ * the ports (thereby making serial8250_isa_driver permanently
++ * in use.)
++ */
++ serial8250_isa_devs = NULL;
++
++ platform_driver_unregister(&serial8250_isa_driver);
++ platform_device_unregister(isa_dev);
++
++#ifdef CONFIG_SPARC
++ sunserial_unregister_minors(&serial8250_reg, UART_NR);
++#else
++ uart_unregister_driver(&serial8250_reg);
++#endif
++}
++
++module_init(serial8250_init);
++module_exit(serial8250_exit);
++
++EXPORT_SYMBOL(serial8250_suspend_port);
++EXPORT_SYMBOL(serial8250_resume_port);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Generic 8250/16x50 serial driver");
++
++module_param(share_irqs, uint, 0644);
++MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
++ " (unsafe)");
++
++module_param(nr_uarts, uint, 0644);
++MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")");
++
++module_param(skip_txen_test, uint, 0644);
++MODULE_PARM_DESC(skip_txen_test, "Skip checking for the TXEN bug at init time");
++
++#ifdef CONFIG_SERIAL_8250_RSA
++module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
++MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
++#endif
++MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
+diff -rupN linux-2.6.35.11/drivers/serial/8250_early.c linux-2.6.35.11-ts7500/drivers/serial/8250_early.c
+--- linux-2.6.35.11/drivers/serial/8250_early.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/serial/8250_early.c 2011-03-14 11:18:24.000000000 -0400
+@@ -46,6 +46,24 @@ struct early_serial8250_device {
+
+ static struct early_serial8250_device early_device;
+
++
++#if defined(CONFIG_ARCH_STR9100) || defined(CONFIG_ARCH_STR8100)
++static unsigned int __init serial_in(struct uart_port *port, int offset)
++{
++ if (port->iotype == UPIO_MEM)
++ return readb(port->membase + (offset << 2));
++ else
++ return inb(port->iobase + (offset << 2));
++}
++
++static void __init serial_out(struct uart_port *port, int offset, int value)
++{
++ if (port->iotype == UPIO_MEM)
++ writeb(value, port->membase + (offset << 2));
++ else
++ outb(value, port->iobase + (offset << 2));
++}
++#else
+ static unsigned int __init serial_in(struct uart_port *port, int offset)
+ {
+ if (port->iotype == UPIO_MEM)
+@@ -62,6 +80,9 @@ static void __init serial_out(struct uar
+ outb(value, port->iobase + offset);
+ }
+
++
++#endif
++
+ #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+ static void __init wait_for_xmitr(struct uart_port *port)
+diff -rupN linux-2.6.35.11/drivers/serial/8250_early.c.orig linux-2.6.35.11-ts7500/drivers/serial/8250_early.c.orig
+--- linux-2.6.35.11/drivers/serial/8250_early.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/serial/8250_early.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,260 @@
++/*
++ * Early serial console for 8250/16550 devices
++ *
++ * (c) Copyright 2004 Hewlett-Packard Development Company, L.P.
++ * Bjorn Helgaas <bjorn.helgaas at hp.com>
++ *
++ * 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.
++ *
++ * Based on the 8250.c serial driver, Copyright (C) 2001 Russell King,
++ * and on early_printk.c by Andi Kleen.
++ *
++ * This is for use before the serial driver has initialized, in
++ * particular, before the UARTs have been discovered and named.
++ * Instead of specifying the console device as, e.g., "ttyS0",
++ * we locate the device directly by its MMIO or I/O port address.
++ *
++ * The user can specify the device directly, e.g.,
++ * earlycon=uart8250,io,0x3f8,9600n8
++ * earlycon=uart8250,mmio,0xff5e0000,115200n8
++ * or
++ * console=uart8250,io,0x3f8,9600n8
++ * console=uart8250,mmio,0xff5e0000,115200n8
++ */
++
++#include <linux/tty.h>
++#include <linux/init.h>
++#include <linux/console.h>
++#include <linux/serial_core.h>
++#include <linux/serial_reg.h>
++#include <linux/serial.h>
++#include <linux/serial_8250.h>
++#include <asm/io.h>
++#include <asm/serial.h>
++#ifdef CONFIG_FIX_EARLYCON_MEM
++#include <asm/pgtable.h>
++#include <asm/fixmap.h>
++#endif
++
++struct early_serial8250_device {
++ struct uart_port port;
++ char options[16]; /* e.g., 115200n8 */
++ unsigned int baud;
++};
++
++static struct early_serial8250_device early_device;
++
++static unsigned int __init serial_in(struct uart_port *port, int offset)
++{
++ if (port->iotype == UPIO_MEM)
++ return readb(port->membase + offset);
++ else
++ return inb(port->iobase + offset);
++}
++
++static void __init serial_out(struct uart_port *port, int offset, int value)
++{
++ if (port->iotype == UPIO_MEM)
++ writeb(value, port->membase + offset);
++ else
++ outb(value, port->iobase + offset);
++}
++
++#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
++
++static void __init wait_for_xmitr(struct uart_port *port)
++{
++ unsigned int status;
++
++ for (;;) {
++ status = serial_in(port, UART_LSR);
++ if ((status & BOTH_EMPTY) == BOTH_EMPTY)
++ return;
++ cpu_relax();
++ }
++}
++
++static void __init serial_putc(struct uart_port *port, int c)
++{
++ wait_for_xmitr(port);
++ serial_out(port, UART_TX, c);
++}
++
++static void __init early_serial8250_write(struct console *console,
++ const char *s, unsigned int count)
++{
++ struct uart_port *port = &early_device.port;
++ unsigned int ier;
++
++ /* Save the IER and disable interrupts */
++ ier = serial_in(port, UART_IER);
++ serial_out(port, UART_IER, 0);
++
++ uart_console_write(port, s, count, serial_putc);
++
++ /* Wait for transmitter to become empty and restore the IER */
++ wait_for_xmitr(port);
++ serial_out(port, UART_IER, ier);
++}
++
++static unsigned int __init probe_baud(struct uart_port *port)
++{
++ unsigned char lcr, dll, dlm;
++ unsigned int quot;
++
++ lcr = serial_in(port, UART_LCR);
++ serial_out(port, UART_LCR, lcr | UART_LCR_DLAB);
++ dll = serial_in(port, UART_DLL);
++ dlm = serial_in(port, UART_DLM);
++ serial_out(port, UART_LCR, lcr);
++
++ quot = (dlm << 8) | dll;
++ return (port->uartclk / 16) / quot;
++}
++
++static void __init init_port(struct early_serial8250_device *device)
++{
++ struct uart_port *port = &device->port;
++ unsigned int divisor;
++ unsigned char c;
++
++ serial_out(port, UART_LCR, 0x3); /* 8n1 */
++ serial_out(port, UART_IER, 0); /* no interrupt */
++ serial_out(port, UART_FCR, 0); /* no fifo */
++ serial_out(port, UART_MCR, 0x3); /* DTR + RTS */
++
++ divisor = port->uartclk / (16 * device->baud);
++ c = serial_in(port, UART_LCR);
++ serial_out(port, UART_LCR, c | UART_LCR_DLAB);
++ serial_out(port, UART_DLL, divisor & 0xff);
++ serial_out(port, UART_DLM, (divisor >> 8) & 0xff);
++ serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
++}
++
++static int __init parse_options(struct early_serial8250_device *device,
++ char *options)
++{
++ struct uart_port *port = &device->port;
++ int mmio, length;
++
++ if (!options)
++ return -ENODEV;
++
++ port->uartclk = BASE_BAUD * 16;
++ if (!strncmp(options, "mmio,", 5)) {
++ port->iotype = UPIO_MEM;
++ port->mapbase = simple_strtoul(options + 5, &options, 0);
++#ifdef CONFIG_FIX_EARLYCON_MEM
++ set_fixmap_nocache(FIX_EARLYCON_MEM_BASE,
++ port->mapbase & PAGE_MASK);
++ port->membase =
++ (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
++ port->membase += port->mapbase & ~PAGE_MASK;
++#else
++ port->membase = ioremap_nocache(port->mapbase, 64);
++ if (!port->membase) {
++ printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n",
++ __func__,
++ (unsigned long long)port->mapbase);
++ return -ENOMEM;
++ }
++#endif
++ mmio = 1;
++ } else if (!strncmp(options, "io,", 3)) {
++ port->iotype = UPIO_PORT;
++ port->iobase = simple_strtoul(options + 3, &options, 0);
++ mmio = 0;
++ } else
++ return -EINVAL;
++
++ options = strchr(options, ',');
++ if (options) {
++ options++;
++ device->baud = simple_strtoul(options, NULL, 0);
++ length = min(strcspn(options, " "), sizeof(device->options));
++ strncpy(device->options, options, length);
++ } else {
++ device->baud = probe_baud(port);
++ snprintf(device->options, sizeof(device->options), "%u",
++ device->baud);
++ }
++
++ printk(KERN_INFO "Early serial console at %s 0x%llx (options '%s')\n",
++ mmio ? "MMIO" : "I/O port",
++ mmio ? (unsigned long long) port->mapbase
++ : (unsigned long long) port->iobase,
++ device->options);
++ return 0;
++}
++
++static struct console early_serial8250_console __initdata = {
++ .name = "uart",
++ .write = early_serial8250_write,
++ .flags = CON_PRINTBUFFER | CON_BOOT,
++ .index = -1,
++};
++
++static int __init early_serial8250_setup(char *options)
++{
++ struct early_serial8250_device *device = &early_device;
++ int err;
++
++ if (device->port.membase || device->port.iobase)
++ return 0;
++
++ err = parse_options(device, options);
++ if (err < 0)
++ return err;
++
++ init_port(device);
++ return 0;
++}
++
++int __init setup_early_serial8250_console(char *cmdline)
++{
++ char *options;
++ int err;
++
++ options = strstr(cmdline, "uart8250,");
++ if (!options) {
++ options = strstr(cmdline, "uart,");
++ if (!options)
++ return 0;
++ }
++
++ options = strchr(cmdline, ',') + 1;
++ err = early_serial8250_setup(options);
++ if (err < 0)
++ return err;
++
++ register_console(&early_serial8250_console);
++
++ return 0;
++}
++
++int serial8250_find_port_for_earlycon(void)
++{
++ struct early_serial8250_device *device = &early_device;
++ struct uart_port *port = &device->port;
++ int line;
++ int ret;
++
++ if (!device->port.membase && !device->port.iobase)
++ return -ENODEV;
++
++ line = serial8250_find_port(port);
++ if (line < 0)
++ return -ENODEV;
++
++ ret = update_console_cmdline("uart", 8250,
++ "ttyS", line, device->options);
++ if (ret < 0)
++ ret = update_console_cmdline("uart", 0,
++ "ttyS", line, device->options);
++
++ return ret;
++}
++
++early_param("earlycon", setup_early_serial8250_console);
+diff -rupN linux-2.6.35.11/drivers/serial/Kconfig linux-2.6.35.11-ts7500/drivers/serial/Kconfig
+--- linux-2.6.35.11/drivers/serial/Kconfig 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/serial/Kconfig 2011-03-14 11:18:24.000000000 -0400
+@@ -163,6 +163,62 @@ config SERIAL_8250_MANY_PORTS
+ say N here to save some memory. You can also say Y if you have an
+ "intelligent" multiport card such as Cyclades, Digiboards, etc.
+
++config SERIAL_8250_CTSRTS
++ bool "Support hardware flow-control"
++ depends on SERIAL_8250 && ARCH_STR8100
++ default N
++ help
++ say Y here if you want Hardware Flow Control supoort.
++ GPIOs are used to implement CTS and RTS function.
++
++config GPIO_CTS
++ int "GPIO pin number of CTS"
++ depends on SERIAL_8250_CTSRTS
++ default 0
++ help
++ GPIOA[0:31] 0~31
++ GPIOB[0:31] 32~63
++
++config GPIO_RTS
++ int "GPIO pin number of RTS"
++ depends on SERIAL_8250_CTSRTS
++ default 1
++ help
++ GPIOA[0:31] 0~31
++ GPIOB[0:31] 32~63
++
++config GPIO_DCD
++ int "GPIO pin number of DCD"
++ depends on SERIAL_8250_CTSRTS
++ default 2
++ help
++ GPIOA[0:31] 0~31
++ GPIOB[0:31] 32~63
++
++config GPIO_DTR
++ int "GPIO pin number of DTR"
++ depends on SERIAL_8250_CTSRTS
++ default 3
++ help
++ GPIOA[0:31] 0~31
++ GPIOB[0:31] 32~63
++
++config GPIO_DSR
++ int "GPIO pin number of DSR"
++ depends on SERIAL_8250_CTSRTS
++ default 4
++ help
++ GPIOA[0:31] 0~31
++ GPIOB[0:31] 32~63
++
++config GPIO_RI
++ int "GPIO pin number of RI"
++ depends on SERIAL_8250_CTSRTS
++ default 5
++ help
++ GPIOA[0:31] 0~31
++ GPIOB[0:31] 32~63
++
+ #
+ # Multi-port serial cards
+ #
+diff -rupN linux-2.6.35.11/drivers/spi/Kconfig linux-2.6.35.11-ts7500/drivers/spi/Kconfig
+--- linux-2.6.35.11/drivers/spi/Kconfig 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/spi/Kconfig 2011-03-14 11:18:24.000000000 -0400
+@@ -100,6 +100,15 @@ config SPI_BUTTERFLY
+ inexpensive battery powered microcontroller evaluation board.
+ This same cable can be used to flash new firmware.
+
++# Eileen , for linux kernel 2.6.24 , 20080413
++config SPI_STR8100
++ tristate "STR8100 SPI master"
++ depends on SPI_MASTER && EXPERIMENTAL
++ select SPI_BITBANG
++ help
++ STR8100 SPI master support
++
++
+ config SPI_COLDFIRE_QSPI
+ tristate "Freescale Coldfire QSPI controller"
+ depends on (M520x || M523x || M5249 || M527x || M528x || M532x)
+diff -rupN linux-2.6.35.11/drivers/spi/Makefile linux-2.6.35.11-ts7500/drivers/spi/Makefile
+--- linux-2.6.35.11/drivers/spi/Makefile 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/spi/Makefile 2011-03-14 11:18:24.000000000 -0400
+@@ -47,6 +47,7 @@ obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.
+ obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o
+ obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o
+ obj-$(CONFIG_SPI_NUC900) += spi_nuc900.o
++obj-$(CONFIG_SPI_STR8100) += spi_str8100.o
+
+ # special build for s3c24xx spi driver with fiq support
+ spi_s3c24xx_hw-y := spi_s3c24xx.o
+diff -rupN linux-2.6.35.11/drivers/spi/spi_bitbang.c linux-2.6.35.11-ts7500/drivers/spi/spi_bitbang.c
+--- linux-2.6.35.11/drivers/spi/spi_bitbang.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/spi/spi_bitbang.c 2011-03-14 11:18:24.000000000 -0400
+@@ -335,6 +335,16 @@ static void bitbang_work(struct work_str
+ */
+ if (!m->is_dma_mapped)
+ t->rx_dma = t->tx_dma = 0;
++/* Eileen , for linux kernel 2.6.24 , 20080413 */
++#ifdef CONFIG_ARCH_STR8100
++
++ if (t->transfer_list.next == &m->transfers) {
++ t->last_in_message_list = 1;
++ } else {
++ t->last_in_message_list = 0;
++ }
++
++#endif
+ status = bitbang->txrx_bufs(spi, t);
+ }
+ if (status > 0)
+diff -rupN linux-2.6.35.11/drivers/spi/spi_bitbang.c.orig linux-2.6.35.11-ts7500/drivers/spi/spi_bitbang.c.orig
+--- linux-2.6.35.11/drivers/spi/spi_bitbang.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/spi/spi_bitbang.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,513 @@
++/*
++ * spi_bitbang.c - polling/bitbanging SPI master controller driver utilities
++ *
++ * 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/spinlock.h>
++#include <linux/workqueue.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/errno.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++#include <linux/spi/spi.h>
++#include <linux/spi/spi_bitbang.h>
++
++
++/*----------------------------------------------------------------------*/
++
++/*
++ * FIRST PART (OPTIONAL): word-at-a-time spi_transfer support.
++ * Use this for GPIO or shift-register level hardware APIs.
++ *
++ * spi_bitbang_cs is in spi_device->controller_state, which is unavailable
++ * to glue code. These bitbang setup() and cleanup() routines are always
++ * used, though maybe they're called from controller-aware code.
++ *
++ * chipselect() and friends may use use spi_device->controller_data and
++ * controller registers as appropriate.
++ *
++ *
++ * NOTE: SPI controller pins can often be used as GPIO pins instead,
++ * which means you could use a bitbang driver either to get hardware
++ * working quickly, or testing for differences that aren't speed related.
++ */
++
++struct spi_bitbang_cs {
++ unsigned nsecs; /* (clock cycle time)/2 */
++ u32 (*txrx_word)(struct spi_device *spi, unsigned nsecs,
++ u32 word, u8 bits);
++ unsigned (*txrx_bufs)(struct spi_device *,
++ u32 (*txrx_word)(
++ struct spi_device *spi,
++ unsigned nsecs,
++ u32 word, u8 bits),
++ unsigned, struct spi_transfer *);
++};
++
++static unsigned bitbang_txrx_8(
++ struct spi_device *spi,
++ u32 (*txrx_word)(struct spi_device *spi,
++ unsigned nsecs,
++ u32 word, u8 bits),
++ unsigned ns,
++ struct spi_transfer *t
++) {
++ unsigned bits = spi->bits_per_word;
++ unsigned count = t->len;
++ const u8 *tx = t->tx_buf;
++ u8 *rx = t->rx_buf;
++
++ while (likely(count > 0)) {
++ u8 word = 0;
++
++ if (tx)
++ word = *tx++;
++ word = txrx_word(spi, ns, word, bits);
++ if (rx)
++ *rx++ = word;
++ count -= 1;
++ }
++ return t->len - count;
++}
++
++static unsigned bitbang_txrx_16(
++ struct spi_device *spi,
++ u32 (*txrx_word)(struct spi_device *spi,
++ unsigned nsecs,
++ u32 word, u8 bits),
++ unsigned ns,
++ struct spi_transfer *t
++) {
++ unsigned bits = spi->bits_per_word;
++ unsigned count = t->len;
++ const u16 *tx = t->tx_buf;
++ u16 *rx = t->rx_buf;
++
++ while (likely(count > 1)) {
++ u16 word = 0;
++
++ if (tx)
++ word = *tx++;
++ word = txrx_word(spi, ns, word, bits);
++ if (rx)
++ *rx++ = word;
++ count -= 2;
++ }
++ return t->len - count;
++}
++
++static unsigned bitbang_txrx_32(
++ struct spi_device *spi,
++ u32 (*txrx_word)(struct spi_device *spi,
++ unsigned nsecs,
++ u32 word, u8 bits),
++ unsigned ns,
++ struct spi_transfer *t
++) {
++ unsigned bits = spi->bits_per_word;
++ unsigned count = t->len;
++ const u32 *tx = t->tx_buf;
++ u32 *rx = t->rx_buf;
++
++ while (likely(count > 3)) {
++ u32 word = 0;
++
++ if (tx)
++ word = *tx++;
++ word = txrx_word(spi, ns, word, bits);
++ if (rx)
++ *rx++ = word;
++ count -= 4;
++ }
++ return t->len - count;
++}
++
++int spi_bitbang_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
++{
++ struct spi_bitbang_cs *cs = spi->controller_state;
++ u8 bits_per_word;
++ u32 hz;
++
++ if (t) {
++ bits_per_word = t->bits_per_word;
++ hz = t->speed_hz;
++ } else {
++ bits_per_word = 0;
++ hz = 0;
++ }
++
++ /* spi_transfer level calls that work per-word */
++ if (!bits_per_word)
++ bits_per_word = spi->bits_per_word;
++ if (bits_per_word <= 8)
++ cs->txrx_bufs = bitbang_txrx_8;
++ else if (bits_per_word <= 16)
++ cs->txrx_bufs = bitbang_txrx_16;
++ else if (bits_per_word <= 32)
++ cs->txrx_bufs = bitbang_txrx_32;
++ else
++ return -EINVAL;
++
++ /* nsecs = (clock period)/2 */
++ if (!hz)
++ hz = spi->max_speed_hz;
++ if (hz) {
++ cs->nsecs = (1000000000/2) / hz;
++ if (cs->nsecs > (MAX_UDELAY_MS * 1000 * 1000))
++ return -EINVAL;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(spi_bitbang_setup_transfer);
++
++/**
++ * spi_bitbang_setup - default setup for per-word I/O loops
++ */
++int spi_bitbang_setup(struct spi_device *spi)
++{
++ struct spi_bitbang_cs *cs = spi->controller_state;
++ struct spi_bitbang *bitbang;
++ int retval;
++ unsigned long flags;
++
++ bitbang = spi_master_get_devdata(spi->master);
++
++ if (!cs) {
++ cs = kzalloc(sizeof *cs, GFP_KERNEL);
++ if (!cs)
++ return -ENOMEM;
++ spi->controller_state = cs;
++ }
++
++ /* per-word shift register access, in hardware or bitbanging */
++ cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)];
++ if (!cs->txrx_word)
++ return -EINVAL;
++
++ retval = bitbang->setup_transfer(spi, NULL);
++ if (retval < 0)
++ return retval;
++
++ dev_dbg(&spi->dev, "%s, %u nsec/bit\n", __func__, 2 * cs->nsecs);
++
++ /* NOTE we _need_ to call chipselect() early, ideally with adapter
++ * setup, unless the hardware defaults cooperate to avoid confusion
++ * between normal (active low) and inverted chipselects.
++ */
++
++ /* deselect chip (low or high) */
++ spin_lock_irqsave(&bitbang->lock, flags);
++ if (!bitbang->busy) {
++ bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
++ ndelay(cs->nsecs);
++ }
++ spin_unlock_irqrestore(&bitbang->lock, flags);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(spi_bitbang_setup);
++
++/**
++ * spi_bitbang_cleanup - default cleanup for per-word I/O loops
++ */
++void spi_bitbang_cleanup(struct spi_device *spi)
++{
++ kfree(spi->controller_state);
++}
++EXPORT_SYMBOL_GPL(spi_bitbang_cleanup);
++
++static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
++{
++ struct spi_bitbang_cs *cs = spi->controller_state;
++ unsigned nsecs = cs->nsecs;
++
++ return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t);
++}
++
++/*----------------------------------------------------------------------*/
++
++/*
++ * SECOND PART ... simple transfer queue runner.
++ *
++ * This costs a task context per controller, running the queue by
++ * performing each transfer in sequence. Smarter hardware can queue
++ * several DMA transfers at once, and process several controller queues
++ * in parallel; this driver doesn't match such hardware very well.
++ *
++ * Drivers can provide word-at-a-time i/o primitives, or provide
++ * transfer-at-a-time ones to leverage dma or fifo hardware.
++ */
++static void bitbang_work(struct work_struct *work)
++{
++ struct spi_bitbang *bitbang =
++ container_of(work, struct spi_bitbang, work);
++ unsigned long flags;
++ int do_setup = -1;
++ int (*setup_transfer)(struct spi_device *,
++ struct spi_transfer *);
++
++ setup_transfer = bitbang->setup_transfer;
++
++ spin_lock_irqsave(&bitbang->lock, flags);
++ bitbang->busy = 1;
++ while (!list_empty(&bitbang->queue)) {
++ struct spi_message *m;
++ struct spi_device *spi;
++ unsigned nsecs;
++ struct spi_transfer *t = NULL;
++ unsigned tmp;
++ unsigned cs_change;
++ int status;
++
++ m = container_of(bitbang->queue.next, struct spi_message,
++ queue);
++ list_del_init(&m->queue);
++ spin_unlock_irqrestore(&bitbang->lock, flags);
++
++ /* FIXME this is made-up ... the correct value is known to
++ * word-at-a-time bitbang code, and presumably chipselect()
++ * should enforce these requirements too?
++ */
++ nsecs = 100;
++
++ spi = m->spi;
++ tmp = 0;
++ cs_change = 1;
++ status = 0;
++
++ list_for_each_entry (t, &m->transfers, transfer_list) {
++
++ /* override speed or wordsize? */
++ if (t->speed_hz || t->bits_per_word)
++ do_setup = 1;
++
++ /* init (-1) or override (1) transfer params */
++ if (do_setup != 0) {
++ if (!setup_transfer) {
++ status = -ENOPROTOOPT;
++ break;
++ }
++ status = setup_transfer(spi, t);
++ if (status < 0)
++ break;
++ }
++
++ /* set up default clock polarity, and activate chip;
++ * this implicitly updates clock and spi modes as
++ * previously recorded for this device via setup().
++ * (and also deselects any other chip that might be
++ * selected ...)
++ */
++ if (cs_change) {
++ bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
++ ndelay(nsecs);
++ }
++ cs_change = t->cs_change;
++ if (!t->tx_buf && !t->rx_buf && t->len) {
++ status = -EINVAL;
++ break;
++ }
++
++ /* transfer data. the lower level code handles any
++ * new dma mappings it needs. our caller always gave
++ * us dma-safe buffers.
++ */
++ if (t->len) {
++ /* REVISIT dma API still needs a designated
++ * DMA_ADDR_INVALID; ~0 might be better.
++ */
++ if (!m->is_dma_mapped)
++ t->rx_dma = t->tx_dma = 0;
++ status = bitbang->txrx_bufs(spi, t);
++ }
++ if (status > 0)
++ m->actual_length += status;
++ if (status != t->len) {
++ /* always report some kind of error */
++ if (status >= 0)
++ status = -EREMOTEIO;
++ break;
++ }
++ status = 0;
++
++ /* protocol tweaks before next transfer */
++ if (t->delay_usecs)
++ udelay(t->delay_usecs);
++
++ if (!cs_change)
++ continue;
++ if (t->transfer_list.next == &m->transfers)
++ break;
++
++ /* sometimes a short mid-message deselect of the chip
++ * may be needed to terminate a mode or command
++ */
++ ndelay(nsecs);
++ bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
++ ndelay(nsecs);
++ }
++
++ m->status = status;
++ m->complete(m->context);
++
++ /* restore speed and wordsize if it was overridden */
++ if (do_setup == 1)
++ setup_transfer(spi, NULL);
++ do_setup = 0;
++
++ /* normally deactivate chipselect ... unless no error and
++ * cs_change has hinted that the next message will probably
++ * be for this chip too.
++ */
++ if (!(status == 0 && cs_change)) {
++ ndelay(nsecs);
++ bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
++ ndelay(nsecs);
++ }
++
++ spin_lock_irqsave(&bitbang->lock, flags);
++ }
++ bitbang->busy = 0;
++ spin_unlock_irqrestore(&bitbang->lock, flags);
++}
++
++/**
++ * spi_bitbang_transfer - default submit to transfer queue
++ */
++int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
++{
++ struct spi_bitbang *bitbang;
++ unsigned long flags;
++ int status = 0;
++
++ m->actual_length = 0;
++ m->status = -EINPROGRESS;
++
++ bitbang = spi_master_get_devdata(spi->master);
++
++ spin_lock_irqsave(&bitbang->lock, flags);
++ if (!spi->max_speed_hz)
++ status = -ENETDOWN;
++ else {
++ list_add_tail(&m->queue, &bitbang->queue);
++ queue_work(bitbang->workqueue, &bitbang->work);
++ }
++ spin_unlock_irqrestore(&bitbang->lock, flags);
++
++ return status;
++}
++EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
++
++/*----------------------------------------------------------------------*/
++
++/**
++ * spi_bitbang_start - start up a polled/bitbanging SPI master driver
++ * @bitbang: driver handle
++ *
++ * Caller should have zero-initialized all parts of the structure, and then
++ * provided callbacks for chip selection and I/O loops. If the master has
++ * a transfer method, its final step should call spi_bitbang_transfer; or,
++ * that's the default if the transfer routine is not initialized. It should
++ * also set up the bus number and number of chipselects.
++ *
++ * For i/o loops, provide callbacks either per-word (for bitbanging, or for
++ * hardware that basically exposes a shift register) or per-spi_transfer
++ * (which takes better advantage of hardware like fifos or DMA engines).
++ *
++ * Drivers using per-word I/O loops should use (or call) spi_bitbang_setup,
++ * spi_bitbang_cleanup and spi_bitbang_setup_transfer to handle those spi
++ * master methods. Those methods are the defaults if the bitbang->txrx_bufs
++ * routine isn't initialized.
++ *
++ * This routine registers the spi_master, which will process requests in a
++ * dedicated task, keeping IRQs unblocked most of the time. To stop
++ * processing those requests, call spi_bitbang_stop().
++ */
++int spi_bitbang_start(struct spi_bitbang *bitbang)
++{
++ int status;
++
++ if (!bitbang->master || !bitbang->chipselect)
++ return -EINVAL;
++
++ INIT_WORK(&bitbang->work, bitbang_work);
++ spin_lock_init(&bitbang->lock);
++ INIT_LIST_HEAD(&bitbang->queue);
++
++ if (!bitbang->master->mode_bits)
++ bitbang->master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
++
++ if (!bitbang->master->transfer)
++ bitbang->master->transfer = spi_bitbang_transfer;
++ if (!bitbang->txrx_bufs) {
++ bitbang->use_dma = 0;
++ bitbang->txrx_bufs = spi_bitbang_bufs;
++ if (!bitbang->master->setup) {
++ if (!bitbang->setup_transfer)
++ bitbang->setup_transfer =
++ spi_bitbang_setup_transfer;
++ bitbang->master->setup = spi_bitbang_setup;
++ bitbang->master->cleanup = spi_bitbang_cleanup;
++ }
++ } else if (!bitbang->master->setup)
++ return -EINVAL;
++
++ /* this task is the only thing to touch the SPI bits */
++ bitbang->busy = 0;
++ bitbang->workqueue = create_singlethread_workqueue(
++ dev_name(bitbang->master->dev.parent));
++ if (bitbang->workqueue == NULL) {
++ status = -EBUSY;
++ goto err1;
++ }
++
++ /* driver may get busy before register() returns, especially
++ * if someone registered boardinfo for devices
++ */
++ status = spi_register_master(bitbang->master);
++ if (status < 0)
++ goto err2;
++
++ return status;
++
++err2:
++ destroy_workqueue(bitbang->workqueue);
++err1:
++ return status;
++}
++EXPORT_SYMBOL_GPL(spi_bitbang_start);
++
++/**
++ * spi_bitbang_stop - stops the task providing spi communication
++ */
++int spi_bitbang_stop(struct spi_bitbang *bitbang)
++{
++ spi_unregister_master(bitbang->master);
++
++ WARN_ON(!list_empty(&bitbang->queue));
++
++ destroy_workqueue(bitbang->workqueue);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(spi_bitbang_stop);
++
++MODULE_LICENSE("GPL");
++
+diff -rupN linux-2.6.35.11/drivers/spi/spi.c linux-2.6.35.11-ts7500/drivers/spi/spi.c
+--- linux-2.6.35.11/drivers/spi/spi.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/spi/spi.c 2011-03-14 11:35:13.000000000 -0400
+@@ -22,12 +22,29 @@
+ #include <linux/device.h>
+ #include <linux/init.h>
+ #include <linux/cache.h>
+-#include <linux/mutex.h>
++// #include <linux/mutex.h>
++#include <linux/semaphore.h>
+ #include <linux/slab.h>
+ #include <linux/mod_devicetable.h>
+ #include <linux/spi/spi.h>
+
++#include <mach/star_spi.h>
+
++static inline u8 str8131_spi_bus_idle(void)
++{
++ return ((SPI_SERVICE_STATUS_REG & 0x1) ? 0 : 1);
++}
++
++static inline u8 str8131_spi_tx_buffer_empty(void)
++{
++ return ((SPI_INTERRUPT_STATUS_REG & (0x1 << 3)) ? 1 : 0);
++}
++
++static inline u8 str8131_spi_rx_buffer_full(void)
++{
++ return ((SPI_INTERRUPT_STATUS_REG & (0x1 << 2)) ? 1 : 0);
++}
++
+ /* SPI bustype and spi_master class are registered after board init code
+ * provides the SPI device tables, ensuring that both are present by the
+ * time controller driver registration causes spi_devices to "enumerate".
+@@ -855,6 +872,82 @@ int spi_write_then_read(struct spi_devic
+ }
+ EXPORT_SYMBOL_GPL(spi_write_then_read);
+
++
++#ifdef CONFIG_ARCH_STR8100
++/**
++ * spi_write_read_sync - SPI synchronous write & read
++ * @spi: device with which data will be exchanged
++ * @txbuf: data to be written (need not be dma-safe)
++ * @n_tx: size of txbuf, in bytes
++ * @rxbuf: buffer into which data will be read
++ * @n_rx: size of rxbuf, in bytes (need not be dma-safe)
++ *
++ * This performs a half duplex MicroWire style transaction with the
++ * device, sending txbuf and then reading rxbuf. The return value
++ * is zero for success, else a negative errno status code.
++ * This call may only be used from a context that may sleep.
++ *
++ * Parameters to this routine are always copied using a small buffer;
++ * performance-sensitive or bulk transfer code should instead use
++ * spi_{async,sync}() calls with dma-safe buffers.
++ */
++int spi_write_read_sync(struct spi_device *spi,
++ const u8 *txbuf, unsigned n_tx,
++ u8 *rxbuf, unsigned n_rx)
++{
++ static DECLARE_MUTEX(lock);
++
++ int status;
++ struct spi_message message;
++ struct spi_transfer x;
++ u8 *local_buf;
++
++ /* Use preallocated DMA-safe buffer. We can't avoid copying here,
++ * (as a pure convenience thing), but we can keep heap costs
++ * out of the hot path ...
++ */
++ while (!str8131_spi_bus_idle()){
++ printk("spi bus is not idle \n"); // do nothing
++ }
++ while (!str8131_spi_tx_buffer_empty()){
++ printk("spi tx buffer is not empty \n"); // do nothing
++ }
++ if ((n_tx + n_rx) > SPI_BUFSIZ)
++ return -EINVAL;
++ spi_message_init(&message);
++ memset(&x, 0, sizeof x);
++ x.len = n_tx;
++ spi_message_add_tail(&x, &message);
++
++ /* ... unless someone else is using the pre-allocated buffer */
++ if (down_trylock(&lock)) {
++ local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
++ if (!local_buf)
++ return -ENOMEM;
++ } else
++ local_buf = buf;
++
++ memcpy(local_buf, txbuf, n_tx);
++ x.tx_buf = local_buf;
++ x.rx_buf = local_buf + n_tx;
++
++ /* do the i/o */
++ status = spi_sync(spi, &message);
++ if (status == 0) {
++ memcpy(rxbuf, x.rx_buf, n_rx);
++ status = message.status;
++ }
++
++ if (x.tx_buf == buf)
++ up(&lock);
++ else
++ kfree(local_buf);
++
++ return status;
++}
++EXPORT_SYMBOL_GPL(spi_write_read_sync);
++#endif
++
+ /*-------------------------------------------------------------------------*/
+
+ static int __init spi_init(void)
+diff -rupN linux-2.6.35.11/drivers/spi/spi.c.orig linux-2.6.35.11-ts7500/drivers/spi/spi.c.orig
+--- linux-2.6.35.11/drivers/spi/spi.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/spi/spi.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,896 @@
++/*
++ * spi.c - SPI init/core code
++ *
++ * Copyright (C) 2005 David Brownell
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/kernel.h>
++#include <linux/device.h>
++#include <linux/init.h>
++#include <linux/cache.h>
++#include <linux/mutex.h>
++#include <linux/slab.h>
++#include <linux/mod_devicetable.h>
++#include <linux/spi/spi.h>
++
++
++/* SPI bustype and spi_master class are registered after board init code
++ * provides the SPI device tables, ensuring that both are present by the
++ * time controller driver registration causes spi_devices to "enumerate".
++ */
++static void spidev_release(struct device *dev)
++{
++ struct spi_device *spi = to_spi_device(dev);
++
++ /* spi masters may cleanup for released devices */
++ if (spi->master->cleanup)
++ spi->master->cleanup(spi);
++
++ spi_master_put(spi->master);
++ kfree(spi);
++}
++
++static ssize_t
++modalias_show(struct device *dev, struct device_attribute *a, char *buf)
++{
++ const struct spi_device *spi = to_spi_device(dev);
++
++ return sprintf(buf, "%s\n", spi->modalias);
++}
++
++static struct device_attribute spi_dev_attrs[] = {
++ __ATTR_RO(modalias),
++ __ATTR_NULL,
++};
++
++/* modalias support makes "modprobe $MODALIAS" new-style hotplug work,
++ * and the sysfs version makes coldplug work too.
++ */
++
++static const struct spi_device_id *spi_match_id(const struct spi_device_id *id,
++ const struct spi_device *sdev)
++{
++ while (id->name[0]) {
++ if (!strcmp(sdev->modalias, id->name))
++ return id;
++ id++;
++ }
++ return NULL;
++}
++
++const struct spi_device_id *spi_get_device_id(const struct spi_device *sdev)
++{
++ const struct spi_driver *sdrv = to_spi_driver(sdev->dev.driver);
++
++ return spi_match_id(sdrv->id_table, sdev);
++}
++EXPORT_SYMBOL_GPL(spi_get_device_id);
++
++static int spi_match_device(struct device *dev, struct device_driver *drv)
++{
++ const struct spi_device *spi = to_spi_device(dev);
++ const struct spi_driver *sdrv = to_spi_driver(drv);
++
++ if (sdrv->id_table)
++ return !!spi_match_id(sdrv->id_table, spi);
++
++ return strcmp(spi->modalias, drv->name) == 0;
++}
++
++static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
++{
++ const struct spi_device *spi = to_spi_device(dev);
++
++ add_uevent_var(env, "MODALIAS=%s%s", SPI_MODULE_PREFIX, spi->modalias);
++ return 0;
++}
++
++#ifdef CONFIG_PM
++
++static int spi_suspend(struct device *dev, pm_message_t message)
++{
++ int value = 0;
++ struct spi_driver *drv = to_spi_driver(dev->driver);
++
++ /* suspend will stop irqs and dma; no more i/o */
++ if (drv) {
++ if (drv->suspend)
++ value = drv->suspend(to_spi_device(dev), message);
++ else
++ dev_dbg(dev, "... can't suspend\n");
++ }
++ return value;
++}
++
++static int spi_resume(struct device *dev)
++{
++ int value = 0;
++ struct spi_driver *drv = to_spi_driver(dev->driver);
++
++ /* resume may restart the i/o queue */
++ if (drv) {
++ if (drv->resume)
++ value = drv->resume(to_spi_device(dev));
++ else
++ dev_dbg(dev, "... can't resume\n");
++ }
++ return value;
++}
++
++#else
++#define spi_suspend NULL
++#define spi_resume NULL
++#endif
++
++struct bus_type spi_bus_type = {
++ .name = "spi",
++ .dev_attrs = spi_dev_attrs,
++ .match = spi_match_device,
++ .uevent = spi_uevent,
++ .suspend = spi_suspend,
++ .resume = spi_resume,
++};
++EXPORT_SYMBOL_GPL(spi_bus_type);
++
++
++static int spi_drv_probe(struct device *dev)
++{
++ const struct spi_driver *sdrv = to_spi_driver(dev->driver);
++
++ return sdrv->probe(to_spi_device(dev));
++}
++
++static int spi_drv_remove(struct device *dev)
++{
++ const struct spi_driver *sdrv = to_spi_driver(dev->driver);
++
++ return sdrv->remove(to_spi_device(dev));
++}
++
++static void spi_drv_shutdown(struct device *dev)
++{
++ const struct spi_driver *sdrv = to_spi_driver(dev->driver);
++
++ sdrv->shutdown(to_spi_device(dev));
++}
++
++/**
++ * spi_register_driver - register a SPI driver
++ * @sdrv: the driver to register
++ * Context: can sleep
++ */
++int spi_register_driver(struct spi_driver *sdrv)
++{
++ sdrv->driver.bus = &spi_bus_type;
++ if (sdrv->probe)
++ sdrv->driver.probe = spi_drv_probe;
++ if (sdrv->remove)
++ sdrv->driver.remove = spi_drv_remove;
++ if (sdrv->shutdown)
++ sdrv->driver.shutdown = spi_drv_shutdown;
++ return driver_register(&sdrv->driver);
++}
++EXPORT_SYMBOL_GPL(spi_register_driver);
++
++/*-------------------------------------------------------------------------*/
++
++/* SPI devices should normally not be created by SPI device drivers; that
++ * would make them board-specific. Similarly with SPI master drivers.
++ * Device registration normally goes into like arch/.../mach.../board-YYY.c
++ * with other readonly (flashable) information about mainboard devices.
++ */
++
++struct boardinfo {
++ struct list_head list;
++ unsigned n_board_info;
++ struct spi_board_info board_info[0];
++};
++
++static LIST_HEAD(board_list);
++static DEFINE_MUTEX(board_lock);
++
++/**
++ * spi_alloc_device - Allocate a new SPI device
++ * @master: Controller to which device is connected
++ * Context: can sleep
++ *
++ * Allows a driver to allocate and initialize a spi_device without
++ * registering it immediately. This allows a driver to directly
++ * fill the spi_device with device parameters before calling
++ * spi_add_device() on it.
++ *
++ * Caller is responsible to call spi_add_device() on the returned
++ * spi_device structure to add it to the SPI master. If the caller
++ * needs to discard the spi_device without adding it, then it should
++ * call spi_dev_put() on it.
++ *
++ * Returns a pointer to the new device, or NULL.
++ */
++struct spi_device *spi_alloc_device(struct spi_master *master)
++{
++ struct spi_device *spi;
++ struct device *dev = master->dev.parent;
++
++ if (!spi_master_get(master))
++ return NULL;
++
++ spi = kzalloc(sizeof *spi, GFP_KERNEL);
++ if (!spi) {
++ dev_err(dev, "cannot alloc spi_device\n");
++ spi_master_put(master);
++ return NULL;
++ }
++
++ spi->master = master;
++ spi->dev.parent = dev;
++ spi->dev.bus = &spi_bus_type;
++ spi->dev.release = spidev_release;
++ device_initialize(&spi->dev);
++ return spi;
++}
++EXPORT_SYMBOL_GPL(spi_alloc_device);
++
++/**
++ * spi_add_device - Add spi_device allocated with spi_alloc_device
++ * @spi: spi_device to register
++ *
++ * Companion function to spi_alloc_device. Devices allocated with
++ * spi_alloc_device can be added onto the spi bus with this function.
++ *
++ * Returns 0 on success; negative errno on failure
++ */
++int spi_add_device(struct spi_device *spi)
++{
++ static DEFINE_MUTEX(spi_add_lock);
++ struct device *dev = spi->master->dev.parent;
++ struct device *d;
++ int status;
++
++ /* Chipselects are numbered 0..max; validate. */
++ if (spi->chip_select >= spi->master->num_chipselect) {
++ dev_err(dev, "cs%d >= max %d\n",
++ spi->chip_select,
++ spi->master->num_chipselect);
++ return -EINVAL;
++ }
++
++ /* Set the bus ID string */
++ dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev),
++ spi->chip_select);
++
++
++ /* We need to make sure there's no other device with this
++ * chipselect **BEFORE** we call setup(), else we'll trash
++ * its configuration. Lock against concurrent add() calls.
++ */
++ mutex_lock(&spi_add_lock);
++
++ d = bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev));
++ if (d != NULL) {
++ dev_err(dev, "chipselect %d already in use\n",
++ spi->chip_select);
++ put_device(d);
++ status = -EBUSY;
++ goto done;
++ }
++
++ /* Drivers may modify this initial i/o setup, but will
++ * normally rely on the device being setup. Devices
++ * using SPI_CS_HIGH can't coexist well otherwise...
++ */
++ status = spi_setup(spi);
++ if (status < 0) {
++ dev_err(dev, "can't %s %s, status %d\n",
++ "setup", dev_name(&spi->dev), status);
++ goto done;
++ }
++
++ /* Device may be bound to an active driver when this returns */
++ status = device_add(&spi->dev);
++ if (status < 0)
++ dev_err(dev, "can't %s %s, status %d\n",
++ "add", dev_name(&spi->dev), status);
++ else
++ dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev));
++
++done:
++ mutex_unlock(&spi_add_lock);
++ return status;
++}
++EXPORT_SYMBOL_GPL(spi_add_device);
++
++/**
++ * spi_new_device - instantiate one new SPI device
++ * @master: Controller to which device is connected
++ * @chip: Describes the SPI device
++ * Context: can sleep
++ *
++ * On typical mainboards, this is purely internal; and it's not needed
++ * after board init creates the hard-wired devices. Some development
++ * platforms may not be able to use spi_register_board_info though, and
++ * this is exported so that for example a USB or parport based adapter
++ * driver could add devices (which it would learn about out-of-band).
++ *
++ * Returns the new device, or NULL.
++ */
++struct spi_device *spi_new_device(struct spi_master *master,
++ struct spi_board_info *chip)
++{
++ struct spi_device *proxy;
++ int status;
++
++ /* NOTE: caller did any chip->bus_num checks necessary.
++ *
++ * Also, unless we change the return value convention to use
++ * error-or-pointer (not NULL-or-pointer), troubleshootability
++ * suggests syslogged diagnostics are best here (ugh).
++ */
++
++ proxy = spi_alloc_device(master);
++ if (!proxy)
++ return NULL;
++
++ WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));
++
++ proxy->chip_select = chip->chip_select;
++ proxy->max_speed_hz = chip->max_speed_hz;
++ proxy->mode = chip->mode;
++ proxy->irq = chip->irq;
++ strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));
++ proxy->dev.platform_data = (void *) chip->platform_data;
++ proxy->controller_data = chip->controller_data;
++ proxy->controller_state = NULL;
++
++ status = spi_add_device(proxy);
++ if (status < 0) {
++ spi_dev_put(proxy);
++ return NULL;
++ }
++
++ return proxy;
++}
++EXPORT_SYMBOL_GPL(spi_new_device);
++
++/**
++ * spi_register_board_info - register SPI devices for a given board
++ * @info: array of chip descriptors
++ * @n: how many descriptors are provided
++ * Context: can sleep
++ *
++ * Board-specific early init code calls this (probably during arch_initcall)
++ * with segments of the SPI device table. Any device nodes are created later,
++ * after the relevant parent SPI controller (bus_num) is defined. We keep
++ * this table of devices forever, so that reloading a controller driver will
++ * not make Linux forget about these hard-wired devices.
++ *
++ * Other code can also call this, e.g. a particular add-on board might provide
++ * SPI devices through its expansion connector, so code initializing that board
++ * would naturally declare its SPI devices.
++ *
++ * The board info passed can safely be __initdata ... but be careful of
++ * any embedded pointers (platform_data, etc), they're copied as-is.
++ */
++int __init
++spi_register_board_info(struct spi_board_info const *info, unsigned n)
++{
++ struct boardinfo *bi;
++
++ bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);
++ if (!bi)
++ return -ENOMEM;
++ bi->n_board_info = n;
++ memcpy(bi->board_info, info, n * sizeof *info);
++
++ mutex_lock(&board_lock);
++ list_add_tail(&bi->list, &board_list);
++ mutex_unlock(&board_lock);
++ return 0;
++}
++
++/* FIXME someone should add support for a __setup("spi", ...) that
++ * creates board info from kernel command lines
++ */
++
++static void scan_boardinfo(struct spi_master *master)
++{
++ struct boardinfo *bi;
++
++ mutex_lock(&board_lock);
++ list_for_each_entry(bi, &board_list, list) {
++ struct spi_board_info *chip = bi->board_info;
++ unsigned n;
++
++ for (n = bi->n_board_info; n > 0; n--, chip++) {
++ if (chip->bus_num != master->bus_num)
++ continue;
++ /* NOTE: this relies on spi_new_device to
++ * issue diagnostics when given bogus inputs
++ */
++ (void) spi_new_device(master, chip);
++ }
++ }
++ mutex_unlock(&board_lock);
++}
++
++/*-------------------------------------------------------------------------*/
++
++static void spi_master_release(struct device *dev)
++{
++ struct spi_master *master;
++
++ master = container_of(dev, struct spi_master, dev);
++ kfree(master);
++}
++
++static struct class spi_master_class = {
++ .name = "spi_master",
++ .owner = THIS_MODULE,
++ .dev_release = spi_master_release,
++};
++
++
++/**
++ * spi_alloc_master - allocate SPI master controller
++ * @dev: the controller, possibly using the platform_bus
++ * @size: how much zeroed driver-private data to allocate; the pointer to this
++ * memory is in the driver_data field of the returned device,
++ * accessible with spi_master_get_devdata().
++ * Context: can sleep
++ *
++ * This call is used only by SPI master controller drivers, which are the
++ * only ones directly touching chip registers. It's how they allocate
++ * an spi_master structure, prior to calling spi_register_master().
++ *
++ * This must be called from context that can sleep. It returns the SPI
++ * master structure on success, else NULL.
++ *
++ * The caller is responsible for assigning the bus number and initializing
++ * the master's methods before calling spi_register_master(); and (after errors
++ * adding the device) calling spi_master_put() to prevent a memory leak.
++ */
++struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
++{
++ struct spi_master *master;
++
++ if (!dev)
++ return NULL;
++
++ master = kzalloc(size + sizeof *master, GFP_KERNEL);
++ if (!master)
++ return NULL;
++
++ device_initialize(&master->dev);
++ master->dev.class = &spi_master_class;
++ master->dev.parent = get_device(dev);
++ spi_master_set_devdata(master, &master[1]);
++
++ return master;
++}
++EXPORT_SYMBOL_GPL(spi_alloc_master);
++
++/**
++ * spi_register_master - register SPI master controller
++ * @master: initialized master, originally from spi_alloc_master()
++ * Context: can sleep
++ *
++ * SPI master controllers connect to their drivers using some non-SPI bus,
++ * such as the platform bus. The final stage of probe() in that code
++ * includes calling spi_register_master() to hook up to this SPI bus glue.
++ *
++ * SPI controllers use board specific (often SOC specific) bus numbers,
++ * and board-specific addressing for SPI devices combines those numbers
++ * with chip select numbers. Since SPI does not directly support dynamic
++ * device identification, boards need configuration tables telling which
++ * chip is at which address.
++ *
++ * This must be called from context that can sleep. It returns zero on
++ * success, else a negative error code (dropping the master's refcount).
++ * After a successful return, the caller is responsible for calling
++ * spi_unregister_master().
++ */
++int spi_register_master(struct spi_master *master)
++{
++ static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
++ struct device *dev = master->dev.parent;
++ int status = -ENODEV;
++ int dynamic = 0;
++
++ if (!dev)
++ return -ENODEV;
++
++ /* even if it's just one always-selected device, there must
++ * be at least one chipselect
++ */
++ if (master->num_chipselect == 0)
++ return -EINVAL;
++
++ /* convention: dynamically assigned bus IDs count down from the max */
++ if (master->bus_num < 0) {
++ /* FIXME switch to an IDR based scheme, something like
++ * I2C now uses, so we can't run out of "dynamic" IDs
++ */
++ master->bus_num = atomic_dec_return(&dyn_bus_id);
++ dynamic = 1;
++ }
++
++ /* register the device, then userspace will see it.
++ * registration fails if the bus ID is in use.
++ */
++ dev_set_name(&master->dev, "spi%u", master->bus_num);
++ status = device_add(&master->dev);
++ if (status < 0)
++ goto done;
++ dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev),
++ dynamic ? " (dynamic)" : "");
++
++ /* populate children from any spi device tables */
++ scan_boardinfo(master);
++ status = 0;
++done:
++ return status;
++}
++EXPORT_SYMBOL_GPL(spi_register_master);
++
++
++static int __unregister(struct device *dev, void *master_dev)
++{
++ /* note: before about 2.6.14-rc1 this would corrupt memory: */
++ if (dev != master_dev)
++ spi_unregister_device(to_spi_device(dev));
++ return 0;
++}
++
++/**
++ * spi_unregister_master - unregister SPI master controller
++ * @master: the master being unregistered
++ * Context: can sleep
++ *
++ * This call is used only by SPI master controller drivers, which are the
++ * only ones directly touching chip registers.
++ *
++ * This must be called from context that can sleep.
++ */
++void spi_unregister_master(struct spi_master *master)
++{
++ int dummy;
++
++ dummy = device_for_each_child(master->dev.parent, &master->dev,
++ __unregister);
++ device_unregister(&master->dev);
++}
++EXPORT_SYMBOL_GPL(spi_unregister_master);
++
++static int __spi_master_match(struct device *dev, void *data)
++{
++ struct spi_master *m;
++ u16 *bus_num = data;
++
++ m = container_of(dev, struct spi_master, dev);
++ return m->bus_num == *bus_num;
++}
++
++/**
++ * spi_busnum_to_master - look up master associated with bus_num
++ * @bus_num: the master's bus number
++ * Context: can sleep
++ *
++ * This call may be used with devices that are registered after
++ * arch init time. It returns a refcounted pointer to the relevant
++ * spi_master (which the caller must release), or NULL if there is
++ * no such master registered.
++ */
++struct spi_master *spi_busnum_to_master(u16 bus_num)
++{
++ struct device *dev;
++ struct spi_master *master = NULL;
++
++ dev = class_find_device(&spi_master_class, NULL, &bus_num,
++ __spi_master_match);
++ if (dev)
++ master = container_of(dev, struct spi_master, dev);
++ /* reference got in class_find_device */
++ return master;
++}
++EXPORT_SYMBOL_GPL(spi_busnum_to_master);
++
++
++/*-------------------------------------------------------------------------*/
++
++/* Core methods for SPI master protocol drivers. Some of the
++ * other core methods are currently defined as inline functions.
++ */
++
++/**
++ * spi_setup - setup SPI mode and clock rate
++ * @spi: the device whose settings are being modified
++ * Context: can sleep, and no requests are queued to the device
++ *
++ * SPI protocol drivers may need to update the transfer mode if the
++ * device doesn't work with its default. They may likewise need
++ * to update clock rates or word sizes from initial values. This function
++ * changes those settings, and must be called from a context that can sleep.
++ * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
++ * effect the next time the device is selected and data is transferred to
++ * or from it. When this function returns, the spi device is deselected.
++ *
++ * Note that this call will fail if the protocol driver specifies an option
++ * that the underlying controller or its driver does not support. For
++ * example, not all hardware supports wire transfers using nine bit words,
++ * LSB-first wire encoding, or active-high chipselects.
++ */
++int spi_setup(struct spi_device *spi)
++{
++ unsigned bad_bits;
++ int status;
++
++ /* help drivers fail *cleanly* when they need options
++ * that aren't supported with their current master
++ */
++ bad_bits = spi->mode & ~spi->master->mode_bits;
++ if (bad_bits) {
++ dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
++ bad_bits);
++ return -EINVAL;
++ }
++
++ if (!spi->bits_per_word)
++ spi->bits_per_word = 8;
++
++ status = spi->master->setup(spi);
++
++ dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s"
++ "%u bits/w, %u Hz max --> %d\n",
++ (int) (spi->mode & (SPI_CPOL | SPI_CPHA)),
++ (spi->mode & SPI_CS_HIGH) ? "cs_high, " : "",
++ (spi->mode & SPI_LSB_FIRST) ? "lsb, " : "",
++ (spi->mode & SPI_3WIRE) ? "3wire, " : "",
++ (spi->mode & SPI_LOOP) ? "loopback, " : "",
++ spi->bits_per_word, spi->max_speed_hz,
++ status);
++
++ return status;
++}
++EXPORT_SYMBOL_GPL(spi_setup);
++
++/**
++ * spi_async - asynchronous SPI transfer
++ * @spi: device with which data will be exchanged
++ * @message: describes the data transfers, including completion callback
++ * Context: any (irqs may be blocked, etc)
++ *
++ * This call may be used in_irq and other contexts which can't sleep,
++ * as well as from task contexts which can sleep.
++ *
++ * The completion callback is invoked in a context which can't sleep.
++ * Before that invocation, the value of message->status is undefined.
++ * When the callback is issued, message->status holds either zero (to
++ * indicate complete success) or a negative error code. After that
++ * callback returns, the driver which issued the transfer request may
++ * deallocate the associated memory; it's no longer in use by any SPI
++ * core or controller driver code.
++ *
++ * Note that although all messages to a spi_device are handled in
++ * FIFO order, messages may go to different devices in other orders.
++ * Some device might be higher priority, or have various "hard" access
++ * time requirements, for example.
++ *
++ * On detection of any fault during the transfer, processing of
++ * the entire message is aborted, and the device is deselected.
++ * Until returning from the associated message completion callback,
++ * no other spi_message queued to that device will be processed.
++ * (This rule applies equally to all the synchronous transfer calls,
++ * which are wrappers around this core asynchronous primitive.)
++ */
++int spi_async(struct spi_device *spi, struct spi_message *message)
++{
++ struct spi_master *master = spi->master;
++
++ /* Half-duplex links include original MicroWire, and ones with
++ * only one data pin like SPI_3WIRE (switches direction) or where
++ * either MOSI or MISO is missing. They can also be caused by
++ * software limitations.
++ */
++ if ((master->flags & SPI_MASTER_HALF_DUPLEX)
++ || (spi->mode & SPI_3WIRE)) {
++ struct spi_transfer *xfer;
++ unsigned flags = master->flags;
++
++ list_for_each_entry(xfer, &message->transfers, transfer_list) {
++ if (xfer->rx_buf && xfer->tx_buf)
++ return -EINVAL;
++ if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf)
++ return -EINVAL;
++ if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf)
++ return -EINVAL;
++ }
++ }
++
++ message->spi = spi;
++ message->status = -EINPROGRESS;
++ return master->transfer(spi, message);
++}
++EXPORT_SYMBOL_GPL(spi_async);
++
++
++/*-------------------------------------------------------------------------*/
++
++/* Utility methods for SPI master protocol drivers, layered on
++ * top of the core. Some other utility methods are defined as
++ * inline functions.
++ */
++
++static void spi_complete(void *arg)
++{
++ complete(arg);
++}
++
++/**
++ * spi_sync - blocking/synchronous SPI data transfers
++ * @spi: device with which data will be exchanged
++ * @message: describes the data transfers
++ * Context: can sleep
++ *
++ * This call may only be used from a context that may sleep. The sleep
++ * is non-interruptible, and has no timeout. Low-overhead controller
++ * drivers may DMA directly into and out of the message buffers.
++ *
++ * Note that the SPI device's chip select is active during the message,
++ * and then is normally disabled between messages. Drivers for some
++ * frequently-used devices may want to minimize costs of selecting a chip,
++ * by leaving it selected in anticipation that the next message will go
++ * to the same chip. (That may increase power usage.)
++ *
++ * Also, the caller is guaranteeing that the memory associated with the
++ * message will not be freed before this call returns.
++ *
++ * It returns zero on success, else a negative error code.
++ */
++int spi_sync(struct spi_device *spi, struct spi_message *message)
++{
++ DECLARE_COMPLETION_ONSTACK(done);
++ int status;
++
++ message->complete = spi_complete;
++ message->context = &done;
++ status = spi_async(spi, message);
++ if (status == 0) {
++ wait_for_completion(&done);
++ status = message->status;
++ }
++ message->context = NULL;
++ return status;
++}
++EXPORT_SYMBOL_GPL(spi_sync);
++
++/* portable code must never pass more than 32 bytes */
++#define SPI_BUFSIZ max(32,SMP_CACHE_BYTES)
++
++static u8 *buf;
++
++/**
++ * spi_write_then_read - SPI synchronous write followed by read
++ * @spi: device with which data will be exchanged
++ * @txbuf: data to be written (need not be dma-safe)
++ * @n_tx: size of txbuf, in bytes
++ * @rxbuf: buffer into which data will be read (need not be dma-safe)
++ * @n_rx: size of rxbuf, in bytes
++ * Context: can sleep
++ *
++ * This performs a half duplex MicroWire style transaction with the
++ * device, sending txbuf and then reading rxbuf. The return value
++ * is zero for success, else a negative errno status code.
++ * This call may only be used from a context that may sleep.
++ *
++ * Parameters to this routine are always copied using a small buffer;
++ * portable code should never use this for more than 32 bytes.
++ * Performance-sensitive or bulk transfer code should instead use
++ * spi_{async,sync}() calls with dma-safe buffers.
++ */
++int spi_write_then_read(struct spi_device *spi,
++ const u8 *txbuf, unsigned n_tx,
++ u8 *rxbuf, unsigned n_rx)
++{
++ static DEFINE_MUTEX(lock);
++
++ int status;
++ struct spi_message message;
++ struct spi_transfer x[2];
++ u8 *local_buf;
++
++ /* Use preallocated DMA-safe buffer. We can't avoid copying here,
++ * (as a pure convenience thing), but we can keep heap costs
++ * out of the hot path ...
++ */
++ if ((n_tx + n_rx) > SPI_BUFSIZ)
++ return -EINVAL;
++
++ spi_message_init(&message);
++ memset(x, 0, sizeof x);
++ if (n_tx) {
++ x[0].len = n_tx;
++ spi_message_add_tail(&x[0], &message);
++ }
++ if (n_rx) {
++ x[1].len = n_rx;
++ spi_message_add_tail(&x[1], &message);
++ }
++
++ /* ... unless someone else is using the pre-allocated buffer */
++ if (!mutex_trylock(&lock)) {
++ local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
++ if (!local_buf)
++ return -ENOMEM;
++ } else
++ local_buf = buf;
++
++ memcpy(local_buf, txbuf, n_tx);
++ x[0].tx_buf = local_buf;
++ x[1].rx_buf = local_buf + n_tx;
++
++ /* do the i/o */
++ status = spi_sync(spi, &message);
++ if (status == 0)
++ memcpy(rxbuf, x[1].rx_buf, n_rx);
++
++ if (x[0].tx_buf == buf)
++ mutex_unlock(&lock);
++ else
++ kfree(local_buf);
++
++ return status;
++}
++EXPORT_SYMBOL_GPL(spi_write_then_read);
++
++/*-------------------------------------------------------------------------*/
++
++static int __init spi_init(void)
++{
++ int status;
++
++ buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
++ if (!buf) {
++ status = -ENOMEM;
++ goto err0;
++ }
++
++ status = bus_register(&spi_bus_type);
++ if (status < 0)
++ goto err1;
++
++ status = class_register(&spi_master_class);
++ if (status < 0)
++ goto err2;
++ return 0;
++
++err2:
++ bus_unregister(&spi_bus_type);
++err1:
++ kfree(buf);
++ buf = NULL;
++err0:
++ return status;
++}
++
++/* board_info is normally registered in arch_initcall(),
++ * but even essential drivers wait till later
++ *
++ * REVISIT only boardinfo really needs static linking. the rest (device and
++ * driver registration) _could_ be dynamically linked (modular) ... costs
++ * include needing to have boardinfo data structures be much more public.
++ */
++postcore_initcall(spi_init);
++
+diff -rupN linux-2.6.35.11/drivers/spi/spi_str8100.c linux-2.6.35.11-ts7500/drivers/spi/spi_str8100.c
+--- linux-2.6.35.11/drivers/spi/spi_str8100.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/spi/spi_str8100.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,452 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/init.h>
++#include <linux/spinlock.h>
++#include <linux/workqueue.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/errno.h>
++#include <linux/err.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++
++#include <linux/spi/spi.h>
++#include <linux/spi/spi_bitbang.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/io.h>
++#include <asm/dma.h>
++#include <asm/hardware.h>
++#include <asm/arch/star_intc.h>
++#include <asm/arch/star_spi.h>
++#include <asm/arch/star_misc.h>
++#include <asm/arch/star_powermgt.h>
++
++//#define STR8100_SPI_DEBUG
++
++struct str8100_spi {
++ /* bitbang has to be first */
++ struct spi_bitbang bitbang;
++ struct completion done;
++
++ int len;
++ int count;
++
++ /* data buffers */
++ const unsigned char *tx;
++ unsigned char *rx;
++
++ struct spi_master *master;
++ struct device *dev;
++ struct spi_device *spi_dev[4];
++
++ int board_count;
++ struct spi_board_info board_info[4];
++};
++
++extern u32 APB_clock;
++
++static inline u8 str8100_spi_bus_idle(void)
++{
++ return ((SPI_SERVICE_STATUS_REG & 0x1) ? 0 : 1);
++}
++
++static inline u8 str8100_spi_tx_buffer_empty(void)
++{
++ return ((SPI_INTERRUPT_STATUS_REG & (0x1 << 3)) ? 1 : 0);
++}
++
++static inline u8 str8100_spi_rx_buffer_full(void)
++{
++ return ((SPI_INTERRUPT_STATUS_REG & (0x1 << 2)) ? 1 : 0);
++}
++
++static u8 str8100_spi_tx_rx(u8 tx_channel, u8 tx_eof_flag, u32 tx_data, u32 *rx_data)
++{
++ u8 rx_channel;
++ u8 rx_eof_flag;
++
++ while (!str8100_spi_bus_idle())
++ ; // do nothing
++
++ while (!str8100_spi_tx_buffer_empty())
++ ; // do nothing
++
++ SPI_TRANSMIT_CONTROL_REG &= ~(0x7);
++ SPI_TRANSMIT_CONTROL_REG |= (tx_channel & 0x3) | ((tx_eof_flag & 0x1) << 2);
++
++ SPI_TRANSMIT_BUFFER_REG = tx_data;
++
++ while (!str8100_spi_rx_buffer_full())
++ ; // do nothing
++
++ rx_channel = (SPI_RECEIVE_CONTROL_REG & 0x3);
++
++ rx_eof_flag = (SPI_RECEIVE_CONTROL_REG & (0x1 << 2)) ? 1 : 0;
++
++ *rx_data = SPI_RECEIVE_BUFFER_REG;
++
++ if ((tx_channel != rx_channel) || (tx_eof_flag != rx_eof_flag)) {
++ return 0;
++ } else {
++ return 1;
++ }
++}
++
++static inline struct str8100_spi *to_hw(struct spi_device *sdev)
++{
++ return spi_master_get_devdata(sdev->master);
++}
++
++static void str8100_spi_chipselect(struct spi_device *spi, int value)
++{
++ unsigned int spi_config;
++ int i;
++
++ switch (value) {
++ case BITBANG_CS_INACTIVE:
++ break;
++
++ case BITBANG_CS_ACTIVE:
++ spi_config = SPI_CONFIGURATION_REG;
++ if (spi->mode & SPI_CPHA)
++ spi_config |= (0x1 << 13);
++ else
++ spi_config &= ~(0x1 << 13);
++
++ if (spi->mode & SPI_CPOL)
++ spi_config |= (0x1 << 14);
++ else
++ spi_config &= ~(0x1 << 14);
++
++ /* write new configration */
++ SPI_CONFIGURATION_REG = spi_config;
++
++ SPI_TRANSMIT_CONTROL_REG &= ~(0x7);
++ SPI_TRANSMIT_CONTROL_REG |= (spi->chip_select & 0x3);
++
++ for (i = 0; i < 8; i++) {
++ if (spi->max_speed_hz > (APB_clock >> i))
++ break;
++ }
++#ifdef STR8100_SPI_DEBUG
++ printk("[STR8100_SPI_DEBUG] APB_clock:%u\n", APB_clock);
++ printk("[STR8100_SPI_DEBUG] spi->max_speed_hz:%u\n", spi->max_speed_hz);
++ printk("[STR8100_SPI_DEBUG] SPI bit rate control val:%d\n", i);
++#endif
++ SPI_BIT_RATE_CONTROL_REG = i;
++
++ break;
++ }
++}
++
++static int str8100_spi_setup(struct spi_device *spi)
++{
++ if (!spi->bits_per_word)
++ spi->bits_per_word = 8;
++
++ return 0;
++}
++
++static int str8100_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
++{
++ struct str8100_spi *hw = to_hw(spi);
++ int error = 0;
++
++ hw->tx = t->tx_buf;
++ hw->rx = t->rx_buf;
++ hw->len = t->len;
++ hw->count = 0;
++
++#ifdef STR8100_SPI_DEBUG
++ printk("[STR8100_SPI_DEBUG] txrx: tx %p, rx %p, len %d\n", t->tx_buf, t->rx_buf, t->len);
++ if (hw->tx) {
++ int i;
++ for (i = 0; i < t->len; i++) {
++ printk("[STR8100_SPI_DEBUG] t->tx_buf[%02d]: 0x%02x\n", i, hw->tx[i]);
++ }
++ }
++#endif
++ if (hw->tx) {
++ int i;
++ u32 rx_data;
++ for (i = 0; i < (hw->len - 1); i++) {
++ str8100_spi_tx_rx(spi->chip_select, 0, hw->tx[i], &rx_data);
++ if (hw->rx) {
++ hw->rx[i] = rx_data;
++#ifdef STR8100_SPI_DEBUG
++ printk("[STR8100_SPI_DEBUG] hw->rx[%02d]:0x%02x\n", i, hw->rx[i]);
++#endif
++ }
++ }
++ if (t->last_in_message_list) {
++ str8100_spi_tx_rx(spi->chip_select, 1, hw->tx[i], &rx_data);
++ if (hw->rx) {
++ hw->rx[i] = rx_data;
++#ifdef STR8100_SPI_DEBUG
++ printk("[STR8100_SPI_DEBUG] hw->rx[%02d]:0x%02x\n", i, hw->rx[i]);
++#endif
++ }
++ } else {
++ str8100_spi_tx_rx(spi->chip_select, 0, hw->tx[i], &rx_data);
++ }
++ goto done;
++ }
++
++ if (hw->rx) {
++ int i;
++ u32 rx_data;
++ for (i = 0; i < (hw->len - 1); i++) {
++ str8100_spi_tx_rx(spi->chip_select, 0, 0xff, &rx_data);
++ hw->rx[i] = rx_data;
++#ifdef STR8100_SPI_DEBUG
++ printk("[STR8100_SPI_DEBUG] hw->rx[%02d]:0x%02x\n", i, hw->rx[i]);
++#endif
++ }
++ if (t->last_in_message_list) {
++ str8100_spi_tx_rx(spi->chip_select, 1, 0xff, &rx_data);
++ hw->rx[i] = rx_data;
++#ifdef STR8100_SPI_DEBUG
++ printk("[STR8100_SPI_DEBUG] hw->rx[%02d]:0x%02x\n", i, hw->rx[i]);
++#endif
++ } else {
++ str8100_spi_tx_rx(spi->chip_select, 0, 0xff, &rx_data);
++ hw->rx[i] = rx_data;
++#ifdef STR8100_SPI_DEBUG
++ printk("[STR8100_SPI_DEBUG] hw->rx[%02d]:0x%02x\n", i, hw->rx[i]);
++#endif
++ }
++ }
++
++done:
++ return t->len;
++}
++
++static int __init str8100_spi_probe(struct platform_device *pdev)
++{
++ struct str8100_spi *hw;
++ struct spi_master *master;
++ unsigned int receive_data;
++ int err = 0;
++
++ master = spi_alloc_master(&pdev->dev, sizeof(struct str8100_spi));
++ if (master == NULL) {
++ dev_err(&pdev->dev, "No memory for spi_master\n");
++ err = -ENOMEM;
++ goto err_nomem;
++ }
++
++ master->bus_num = 1;
++ master->num_chipselect = 4;
++
++ hw = spi_master_get_devdata(master);
++ memset(hw, 0, sizeof(struct str8100_spi));
++
++ hw->master = spi_master_get(master);
++
++ hw->dev = &pdev->dev;
++
++ platform_set_drvdata(pdev, hw);
++ init_completion(&hw->done);
++
++ /* scott.patch.spi */
++ // Clear spurious interrupt sources
++ SPI_INTERRUPT_STATUS_REG = (0xF << 4);
++
++ // Disable SPI interrupt
++ SPI_INTERRUPT_ENABLE_REG = 0;
++
++ // Enable SPI
++ SPI_CONFIGURATION_REG |= (0x1 << 31);
++
++ /* setup the state for the bitbang driver */
++
++ hw->bitbang.master = hw->master;
++ hw->bitbang.chipselect = str8100_spi_chipselect;
++ hw->bitbang.txrx_bufs = str8100_spi_txrx;
++ hw->bitbang.master->setup = str8100_spi_setup;
++
++ dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
++
++ /* register our spi controller */
++
++ err = spi_bitbang_start(&hw->bitbang);
++ if (err) {
++ dev_err(&pdev->dev, "Failed to register SPI master\n");
++ goto err_register;
++ }
++
++#ifdef STR8100_SPI_DEBUG
++{
++ int i;
++ u32 rx_data1, rx_data2, rx_data3;
++
++ str8100_spi_tx_rx(0, 0, 0x9f, &rx_data1);
++ str8100_spi_tx_rx(0, 0, 0xff, &rx_data1);
++ str8100_spi_tx_rx(0, 0, 0xff, &rx_data2);
++ str8100_spi_tx_rx(0, 1, 0xff, &rx_data3);
++ printk("[STR8100_SPI_DEBUG] manufacturer: %x\n", rx_data1);
++ printk("[STR8100_SPI_DEBUG] device: %x\n", ((rx_data2 & 0xff) << 8) | (u16) (rx_data3 & 0xff));
++
++ str8100_spi_tx_rx(0, 0, 0x03, &rx_data1);
++ str8100_spi_tx_rx(0, 0, 0x00, &rx_data1);
++ str8100_spi_tx_rx(0, 0, 0x00, &rx_data1);
++ str8100_spi_tx_rx(0, 0, 0x00, &rx_data1);
++ for (i = 0; i < 15; i++) {
++ str8100_spi_tx_rx(0, 0, 0xff, &rx_data1);
++ printk("[STR8100_SPI_DEBUG] flash[%02d]:0x%02x\n", i, rx_data1 & 0xff);
++ }
++ str8100_spi_tx_rx(0, 1, 0xff, &rx_data1);
++ printk("[STR8100_SPI_DEBUG] flash[%02d]:0x%02x\n", i, rx_data1 & 0xff);
++}
++#endif
++
++ return 0;
++
++err_register:
++ spi_master_put(hw->master);;
++
++err_nomem:
++ return err;
++}
++
++static int str8100_spi_remove(struct platform_device *dev)
++{
++ struct str8100_spi *hw = platform_get_drvdata(dev);
++
++ platform_set_drvdata(dev, NULL);
++
++ spi_unregister_master(hw->master);
++
++ //str8100_spi_clk_disable();
++
++ spi_master_put(hw->master);
++
++ return 0;
++}
++
++
++#ifdef CONFIG_PM
++
++static int str8100_spi_suspend(struct platform_device *pdev, pm_message_t msg)
++{
++ struct str8100_spi *hw = platform_get_drvdata(pdev);
++
++ //str8100_spi_clk_disable();
++ return 0;
++}
++
++static int str8100_spi_resume(struct platform_device *pdev)
++{
++ struct str8100_spi *hw = platform_get_drvdata(pdev);
++
++ //str8100_spi_clk_enable()
++ return 0;
++}
++
++#else
++#define str8100_spi_suspend NULL
++#define str8100_spi_resume NULL
++#endif
++
++static void __init str8100_spi_hw_init(void)
++{
++ u32 receive_data;
++
++ // Enable SPI pins
++ HAL_MISC_ENABLE_SPI_PINS();
++
++ // Enable SPI clock
++ HAL_PWRMGT_ENABLE_SPI_CLOCK();
++
++ // Disable SPI serial flash access through 0x30000000 region
++ HAL_MISC_DISABLE_SPI_SERIAL_FLASH_BANK_ACCESS();
++
++ /*
++ * Note SPI is NOT enabled after this function is invoked!!
++ */
++ SPI_CONFIGURATION_REG =
++ (((0x0 & 0x3) << 0) | /* 8bits shift length */
++ (0x0 << 9) | /* general SPI mode */
++ (0x0 << 10) | /* disable FIFO */
++ (0x1 << 11) | /* SPI master mode */
++ (0x0 << 12) | /* disable SPI loopback mode */
++ (0x0 << 13) | /* clock phase */
++ (0x0 << 14) | /* clock polarity */
++ (0x0 << 24) | /* disable SPI Data Swap */
++ (0x0 << 30) | /* disable SPI High Speed Read for BootUp */
++ (0x0 << 31)); /* disable SPI */
++
++ SPI_BIT_RATE_CONTROL_REG = 0x1; // PCLK/2
++
++ // Configure SPI's Tx channel
++ SPI_TRANSMIT_CONTROL_REG = 0;
++
++ // Configure Tx FIFO Threshold
++ SPI_FIFO_TRANSMIT_CONFIG_REG &= ~(0x03 << 4);
++ SPI_FIFO_TRANSMIT_CONFIG_REG |= ((0x0 & 0x03) << 4);
++
++ // Configure Rx FIFO Threshold
++ SPI_FIFO_RECEIVE_CONFIG_REG &= ~(0x03 << 4);
++ SPI_FIFO_RECEIVE_CONFIG_REG |= ((0x0 & 0x03) << 4);
++
++ SPI_INTERRUPT_ENABLE_REG = 0;
++
++ // Clear spurious interrupt sources
++ SPI_INTERRUPT_STATUS_REG = (0xF << 4);
++
++ receive_data = SPI_RECEIVE_BUFFER_REG;
++
++ return;
++}
++
++static struct platform_driver str8100_spidrv = {
++ .remove = __devexit_p(str8100_spi_remove),
++ .suspend = str8100_spi_suspend,
++ .resume = str8100_spi_resume,
++ .driver = {
++ .name = "str8100_spi",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init str8100_spi_init(void)
++{
++ printk("STR8100 SPI: init\n");
++ str8100_spi_hw_init();
++
++ return platform_driver_probe(&str8100_spidrv, str8100_spi_probe);
++}
++
++static void __exit str8100_spi_exit(void)
++{
++ platform_driver_unregister(&str8100_spidrv);
++}
++
++module_init(str8100_spi_init);
++module_exit(str8100_spi_exit);
++
++MODULE_DESCRIPTION("STR8100 SPI Driver");
++MODULE_AUTHOR("STAR Semi Corp.");
++MODULE_LICENSE("GPL");
+diff -rupN linux-2.6.35.11/drivers/star/Makefile linux-2.6.35.11-ts7500/drivers/star/Makefile
+--- linux-2.6.35.11/drivers/star/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/star/Makefile 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,30 @@
++################################################################################
++#
++#
++# Copyright(c) 2005 - Star semiconduction. 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 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.
++#
++# The full GNU General Public License is included in this distribution in the
++# file called LICENSE.
++#
++# Contact Information:
++# Star semiconduction Linux Support <support at starsemi.com>
++#
++################################################################################
++
++obj-$(CONFIG_ARCH_STR9100) += str9100/
++obj-$(CONFIG_ARCH_STR8100) += str8100/
++
+diff -rupN linux-2.6.35.11/drivers/star/str8100/crash.c linux-2.6.35.11-ts7500/drivers/star/str8100/crash.c
+--- linux-2.6.35.11/drivers/star/str8100/crash.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/star/str8100/crash.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,85 @@
++/*======================================================================
++
++ Copyright (C) 2006 STAR Semiconductor Limited
++
++ 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/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/interrupt.h>
++#include <linux/smp_lock.h>
++
++#include <asm/arch/star_gpio.h>
++#include <asm/arch/star_intc.h>
++#include <asm/arch/star_misc.h>
++#include <asm/arch/star_powermgt.h>
++
++extern void str8100_set_interrupt_trigger(unsigned int, unsigned int, unsigned int);
++
++static int mode=0;
++module_param(mode, int, 0);
++MODULE_PARM_DESC(mode, "");
++static irqreturn_t str8100_ext_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs)
++{
++ void (*fnptr)(void)=NULL;
++ printk("%s: this_irq=%d\n",__FUNCTION__,this_irq);
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(this_irq);
++
++ if(mode==1) while(1);
++ else fnptr();
++
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq);
++
++ return IRQ_HANDLED;
++}
++
++static int __init str8100_inthandler_init(void)
++{
++ int ret;
++printk("%s: \n",__FUNCTION__);
++ if(mode==0) panic("%s: panic for testing...\n",__FUNCTION__);
++
++#define register_ext_int(_i){\
++ printk("%s: registering int handler for external int%d\n",__FUNCTION__,_i);\
++ HAL_MISC_ENABLE_EXT_INT##_i##_PINS();\
++ str8100_set_interrupt_trigger (INTC_EXT_INT##_i##_BIT_INDEX,INTC_LEVEL_TRIGGER,INTC_ACTIVE_LOW);\
++ if ((ret=request_irq(INTC_EXT_INT##_i##_BIT_INDEX, str8100_ext_irq_handler, 0, "testing", NULL))){\
++ printk("%s: request_irq %d failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,INTC_EXT_INT##_i##_BIT_INDEX,ret,-EBUSY);\
++ return -EBUSY;\
++ }\
++ }
++ register_ext_int(29);
++ register_ext_int(30);
++ return 0;
++}
++
++static void __exit str8100_inthandler_exit(void)
++{
++//#ifdef DEBUG
++ printk("%s: \n",__FUNCTION__);
++//#endif
++ lock_kernel();
++ free_irq(INTC_EXT_INT29_BIT_INDEX, NULL);
++ free_irq(INTC_EXT_INT30_BIT_INDEX, NULL);
++ unlock_kernel();
++}
++
++module_init(str8100_inthandler_init);
++module_exit(str8100_inthandler_exit);
++
+diff -rupN linux-2.6.35.11/drivers/star/str8100/int28handler.c linux-2.6.35.11-ts7500/drivers/star/str8100/int28handler.c
+--- linux-2.6.35.11/drivers/star/str8100/int28handler.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/star/str8100/int28handler.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,80 @@
++/*======================================================================
++
++ Copyright (C) 2006 STAR Semiconductor Limited
++
++ 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/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/interrupt.h>
++
++#include <asm/arch/star_gpio.h>
++#include <asm/arch/star_intc.h>
++#include <asm/arch/star_misc.h>
++#include <asm/arch/star_powermgt.h>
++
++extern void str8100_set_interrupt_trigger(unsigned int, unsigned int, unsigned int);
++static struct work_struct reboot_work;
++void do_reboot(){
++ char* argv[2];
++ char* env[1];
++ argv[0]="/sbin/reboot";
++ argv[1]=NULL;
++ env[0]=NULL;
++ call_usermodehelper(argv[0],argv,env,0);
++
++}
++static irqreturn_t str8100_int28vbus_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs)
++{
++ printk("%s: this_irq=%d\n",__FUNCTION__,this_irq);
++
++printk("%s: registering work\n",__FUNCTION__);
++ INIT_WORK(&reboot_work,do_reboot,NULL);
++ if(PWRMGT_USB_DEVICE_POWERMGT_REG&0x1)
++ schedule_work(&reboot_work);
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq);
++ return IRQ_HANDLED;
++}
++
++static int __init str8100_int28vbus_inthandler_init(void)
++{
++ int ret;
++printk("%s: \n",__FUNCTION__);
++ if(PWRMGT_USB_DEVICE_POWERMGT_REG&0x1)
++ HAL_PWRMGT_GLOBAL_SOFTWARE_RESET();
++ // schedule_work(&reboot_work);
++
++ //str8100_set_interrupt_trigger (INTC_GPIO_EXTERNAL_INT_BIT_INDEX,INTC_LEVEL_TRIGGER,INTC_ACTIVE_HIGH);
++ if ((ret=request_irq(INTC_USB_DEVICE_VBUS_BIT_INDEX, str8100_int28vbus_irq_handler, 0, "vbus", NULL))){
++ printk("%s: request_irq failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,ret,-EBUSY);
++ return -EBUSY;
++ }
++ return 0;
++}
++
++static void __exit str8100_int28vbus_inthandler_exit(void)
++{
++ printk("%s: \n",__FUNCTION__);
++ lock_kernel();
++ free_irq(INTC_USB_DEVICE_VBUS_BIT_INDEX, NULL);
++ unlock_kernel();
++}
++
++module_init(str8100_int28vbus_inthandler_init);
++module_exit(str8100_int28vbus_inthandler_exit);
++
+diff -rupN linux-2.6.35.11/drivers/star/str8100/inthandler.c linux-2.6.35.11-ts7500/drivers/star/str8100/inthandler.c
+--- linux-2.6.35.11/drivers/star/str8100/inthandler.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/star/str8100/inthandler.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,178 @@
++/*======================================================================
++
++ Copyright (C) 2006 STAR Semiconductor Limited
++
++ 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/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/interrupt.h>
++#include <linux/smp_lock.h>
++
++#include <asm/arch/star_gpio.h>
++#include <asm/arch/star_intc.h>
++#include <asm/arch/star_misc.h>
++#include <asm/arch/star_powermgt.h>
++
++static int gpio=0;
++module_param(gpio, int, 0);
++MODULE_PARM_DESC(gpio, "GPIO int switch(0: disable, 1:enable default=0)");
++
++static int ext29=0;
++module_param(ext29, int, 0);
++MODULE_PARM_DESC(ext29, "Ext int 29 switch(0: disable, 1:enable default=0)");
++
++static int ext30=0;
++module_param(ext30, int, 0);
++MODULE_PARM_DESC(ext30, "Ext int 30 switch(0: disable, 1:enable default=0)");
++
++static int debug=1;
++module_param(debug, int, 0);
++MODULE_PARM_DESC(debug, "debug mode (1=on, 0=off, default=1");
++
++static irqreturn_t (*gpioA_irq_handler)(int, void*, struct pt_regs*)=NULL;
++static irqreturn_t (*gpioB_irq_handler)(int, void*, struct pt_regs*)=NULL;
++static irqreturn_t (*ext_irq_handler)(int, void*, struct pt_regs*)=NULL;
++
++extern void str8100_set_interrupt_trigger(unsigned int, unsigned int, unsigned int);
++
++static irqreturn_t str8100_ext_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs)
++{
++ if(debug) printk("%s: this_irq=%d\n",__FUNCTION__,this_irq);
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(this_irq);
++ if(ext_irq_handler){
++ ext_irq_handler(this_irq,dev_id,regs);
++ }
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(this_irq);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(this_irq);
++
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t str8100_gpio_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs)
++{
++ unsigned int volatile statusA,statusB;
++ int i;
++
++ if(debug) printk("%s: this_irq=%d\n",__FUNCTION__,this_irq);
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++
++ HAL_GPIOA_READ_INTERRUPT_MASKED_STATUS(statusA);
++ HAL_GPIOB_READ_INTERRUPT_MASKED_STATUS(statusB);
++//printk("%s: %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x \n",__FUNCTION__,GPIOA_DATA_OUTPUT_REG,GPIOA_DATA_INPUT_REG,GPIOA_DIRECTION_REG,GPIOA_INTERRUPT_ENABLE_REG,GPIOA_INTERRUPT_RAW_STATUS_REG,GPIOA_INTERRUPT_MASKED_STATUS_REG,GPIOA_INTERRUPT_MASKED_STATUS_REG,GPIOA_INTERRUPT_MASK_REG,GPIOA_INTERRUPT_TRIGGER_METHOD_REG,GPIOA_INTERRUPT_TRIGGER_BOTH_EDGES_REG,GPIOA_INTERRUPT_TRIGGER_TYPE_REG,GPIOA_BOUNCE_ENABLE_REG,GPIOA_BOUNCE_CLOCK_PRESCALE_REG);
++ for (i = 0; i < 32; i++)
++ {
++ if (statusA & (1 << i)){
++ if(debug) printk("%s: GPIOA Int %d\n",__FUNCTION__,i);
++ if(gpioA_irq_handler){
++ gpioA_irq_handler(i,dev_id,regs);
++ }
++ }
++ if (statusB & (1 << i)){
++ if(debug) printk("%s: GPIOB Int %d\n",__FUNCTION__,i);
++ if(gpioB_irq_handler){
++ gpioB_irq_handler(i,dev_id,regs);
++ }
++ }
++ }
++ HAL_GPIOA_CLEAR_INTERRUPT(statusA);
++ HAL_GPIOB_CLEAR_INTERRUPT(statusB);
++
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++
++ return IRQ_HANDLED;
++}
++
++static int __init str8100_inthandler_init(void)
++{
++ int ret;
++if(debug) printk("%s: \n",__FUNCTION__);
++
++#if 0
++ /*
++ * Configure system Xtal clock to be output to CLKOUT pin
++ */
++ HAL_PWRMGT_CONFIGURE_CLOCK_OUT_PIN(0, 0);
++#endif
++
++// HAL_MISC_ENABLE_ALL_SHARED_GPIO_PINS();
++ if(gpio){
++ if(debug) printk("%s: registering int handler for gpio int\n",__FUNCTION__);\
++//gpio initialization depend on application
++#if 0
++ HAL_MISC_DISABLE_EXT_INT29_PINS();
++ HAL_MISC_DISABLE_EXT_INT30_PINS();
++
++ HAL_PWRMGT_ENABLE_GPIO_CLOCK();
++
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << PWRMGT_GPIO_SOFTWARE_RESET_BIT_INDEX);
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG &= ~(0x1 << PWRMGT_GPIO_SOFTWARE_RESET_BIT_INDEX);
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << PWRMGT_GPIO_SOFTWARE_RESET_BIT_INDEX);
++
++ HAL_GPIOA_SET_DIRECTION_INPUT(3);
++ HAL_GPIOA_ENABLE_INTERRUPT(3);
++ HAL_GPIOA_DISABLE_INTERRUPT_MASK(3);
++ HAL_GPIOA_SET_INTERRUPT_EDGE_TRIGGER_MODE(3);
++#endif
++
++ str8100_set_interrupt_trigger (INTC_GPIO_EXTERNAL_INT_BIT_INDEX,INTC_LEVEL_TRIGGER,INTC_ACTIVE_HIGH);
++ if ((ret=request_irq(INTC_GPIO_EXTERNAL_INT_BIT_INDEX, str8100_gpio_irq_handler, 0, "testing", NULL))){
++ if(debug) printk("%s: request_irq failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,ret,-EBUSY);
++ return -EBUSY;
++ }
++ }
++#define register_ext_int(_i){\
++ if(debug) printk("%s: registering int handler for external int%d\n",__FUNCTION__,_i);\
++ HAL_MISC_ENABLE_EXT_INT##_i##_PINS();\
++ str8100_set_interrupt_trigger (INTC_EXT_INT##_i##_BIT_INDEX,INTC_LEVEL_TRIGGER,INTC_ACTIVE_LOW);\
++ if ((ret=request_irq(INTC_EXT_INT##_i##_BIT_INDEX, str8100_ext_irq_handler, 0, "testing", NULL))){\
++ if(debug) printk("%s: request_irq %d failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,INTC_EXT_INT##_i##_BIT_INDEX,ret,-EBUSY);\
++ return -EBUSY;\
++ }\
++ }
++ if(ext29) register_ext_int(29);
++ if(ext30) register_ext_int(30);
++
++/* HAL_MISC_ENABLE_EXT_INT30_PINS();
++ str8100_set_interrupt_trigger (INTC_EXT_INT30_BIT_INDEX,INTC_IRQ_INTERRUPT,INTC_LEVEL_TRIGGER,INTC_ACTIVE_LOW);
++ if ((ret=request_irq(INTC_EXT_INT30_BIT_INDEX, str8100_pm_irq_handler, 0, "testing", NULL))){
++ printk("%s: request_irq failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,ret,-EBUSY);
++ return -EBUSY;
++ }
++*/
++ return 0;
++}
++
++static void __exit str8100_inthandler_exit(void)
++{
++//#ifdef DEBUG
++ if(debug) printk("%s: \n",__FUNCTION__);
++//#endif
++ lock_kernel();
++ if(gpio) free_irq(INTC_GPIO_EXTERNAL_INT_BIT_INDEX, NULL);
++ if(ext29) free_irq(INTC_EXT_INT29_BIT_INDEX, NULL);
++ if(ext30) free_irq(INTC_EXT_INT30_BIT_INDEX, NULL);
++ unlock_kernel();
++}
++
++module_init(str8100_inthandler_init);
++module_exit(str8100_inthandler_exit);
++
+diff -rupN linux-2.6.35.11/drivers/star/str8100/Makefile linux-2.6.35.11-ts7500/drivers/star/str8100/Makefile
+--- linux-2.6.35.11/drivers/star/str8100/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/star/str8100/Makefile 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,33 @@
++################################################################################
++#
++#
++# Copyright(c) 2005 - Star semiconduction. 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 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.
++#
++# The full GNU General Public License is included in this distribution in the
++# file called LICENSE.
++#
++# Contact Information:
++# Star semiconduction Linux Support <support at starsemi.com>
++#
++################################################################################
++
++#obj-y += str8100_tool.o
++#obj-$(CONFIG_STR8100_INFO) += str8100_info.o
++
++obj-$(CONFIG_STR8100_USBD_REBOOT_INTHANDLER) += int28handler.o
++obj-m += inthandler.o
++obj-m += crash.o
+diff -rupN linux-2.6.35.11/drivers/star/str8100/str8100_gpio_test.c linux-2.6.35.11-ts7500/drivers/star/str8100/str8100_gpio_test.c
+--- linux-2.6.35.11/drivers/star/str8100/str8100_gpio_test.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/star/str8100/str8100_gpio_test.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,140 @@
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/fs.h>
++#include <linux/mm.h>
++#include <linux/miscdevice.h>
++#include <linux/watchdog.h>
++#include <linux/reboot.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/smp_lock.h>
++#include <linux/delay.h>
++#include <asm/irq.h>
++#include <asm/uaccess.h>
++#include <asm/hardware.h>
++#include <asm/mach-types.h>
++#include <asm/arch/star_powermgt.h>
++#include <asm/arch/star_intc.h>
++#include <asm/arch/star_misc.h>
++#include <asm/arch/star_gpio.h>
++
++MODULE_LICENSE("Dual BSD/GPL");
++
++extern void str8100_led_all_on(void);
++extern void str8100_led_all_off(void);
++extern void str8100_led_on(unsigned int led_index);
++extern void str8100_led_off(unsigned int led_index);
++extern void str8100_led_toggle(unsigned int led_index);
++extern void str8100_led_init(void);
++
++extern void str8100_set_interrupt_trigger(unsigned int, unsigned int, unsigned int, unsigned int);
++
++static irqreturn_t str8100_gpio_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs)
++{
++ unsigned int volatile status;
++ int i;
++
++ printk("%s: \n",__FUNCTION__);
++
++ HAL_INTC_DISABLE_INTERRUPT_SOURCE(INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++ HAL_GPIOA_READ_INTERRUPT_MASKED_STATUS(status);
++
++//printk("%s: %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x \n", \
++// __FUNCTION__, \
++// GPIOA_DATA_OUTPUT_REG, \
++// GPIOA_DATA_INPUT_REG, \
++// GPIOA_DIRECTION_REG, \
++// GPIOA_INTERRUPT_ENABLE_REG, \
++// GPIOA_INTERRUPT_RAW_STATUS_REG, \
++// GPIOA_INTERRUPT_MASKED_STATUS_REG, \
++// GPIOA_INTERRUPT_MASKED_STATUS_REG, \
++// GPIOA_INTERRUPT_MASK_REG, \
++// GPIOA_INTERRUPT_TRIGGER_METHOD_REG, \
++// GPIOA_INTERRUPT_TRIGGER_BOTH_EDGES_REG, \
++// GPIOA_INTERRUPT_TRIGGER_TYPE_REG, \
++// GPIOA_BOUNCE_ENABLE_REG, \
++// GPIOA_BOUNCE_CLOCK_PRESCALE_REG);
++
++ for (i = 0; i < 32; i++) {
++ if (status & (1 << i)) {
++ printk(" str8100 gpio: Interrupt Happen (status: 0x%x, GPIO %.2d)\n",status,i);
++ //GPIOA[0] will toggle GPIOB[2]
++ //GPIOA[1] will toggle GPIOB[3]
++ str8100_led_toggle(1<<(i+2));
++ }
++ }
++
++ HAL_GPIOA_CLEAR_INTERRUPT(status);
++ HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++ HAL_INTC_ENABLE_INTERRUPT_SOURCE(INTC_GPIO_EXTERNAL_INT_BIT_INDEX);
++
++ return IRQ_HANDLED;
++}
++
++static int __init test_init(void){
++ int ret;
++// __u32 data,cnt=0;
++
++ printk("%s: Output led test...\n",__FUNCTION__);
++
++
++ HAL_MISC_ENABLE_ALL_SHARED_GPIO_PINS();
++ HAL_PWRMGT_ENABLE_GPIO_CLOCK();
++
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << PWRMGT_GPIO_SOFTWARE_RESET_BIT_INDEX);
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG &= ~(0x1 << PWRMGT_GPIO_SOFTWARE_RESET_BIT_INDEX);
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << PWRMGT_GPIO_SOFTWARE_RESET_BIT_INDEX);
++
++ str8100_led_init();
++
++/*
++ printk("%s: Input button test...\n",__FUNCTION__);
++ HAL_GPIOA_SET_DIRECTION_INPUT(3);
++ while(cnt<20){
++ HAL_GPIOA_READ_DATA_IN_STATUS(data);
++ printk("%d-%s: read data=0x%x\n",cnt,__FUNCTION__,data);
++ msleep(500);
++ cnt++;
++ }
++*/
++
++ printk("%s: IRQ test...\n",__FUNCTION__);
++ //Configure GPIOA[0:1] as interrupts
++ HAL_GPIOA_SET_DIRECTION_INPUT(3);
++ HAL_GPIOA_ENABLE_INTERRUPT(3);
++ HAL_GPIOA_DISABLE_INTERRUPT_MASK(3);
++
++ //GPIOA[0] will toggle GPIOB[2] (in interrupt handler)
++ //set GPIOA[0] to level trigger
++ //==> GPIOB[2] will keep blinking while button pressed
++ HAL_GPIOA_SET_INTERRUPT_LEVEL_TRIGGER_MODE(1);
++ HAL_GPIOA_SET_INTERRUPT_LOW_LEVEL_TRIGGER_MODE(1);
++// HAL_GPIOA_SET_INTERRUPT_SINGLE_EDGE_TRIGGER_MODE(1);
++// HAL_GPIOA_SET_INTERRUPT_SINGLE_FALLING_EDGE_TRIGGER_MODE(1);
++// HAL_GPIOA_SET_INTERRUPT_SINGLE_RISING_EDGE_TRIGGER_MODE(1);
++
++ //GPIOA[1] will toggle GPIOB[3] (in interrupt handler)
++ //set GPIOA[1] to edge trigger
++ //==> GPIOB[3] will turn on while pressed
++ HAL_GPIOA_SET_INTERRUPT_EDGE_TRIGGER_MODE(2);
++ HAL_GPIOA_SET_INTERRUPT_BOTH_EDGE_TRIGGER_MODE(2);
++
++ str8100_set_interrupt_trigger (INTC_GPIO_EXTERNAL_INT_BIT_INDEX,INTC_IRQ_INTERRUPT,INTC_LEVEL_TRIGGER,INTC_ACTIVE_HIGH);
++ if ((ret=request_irq(INTC_GPIO_EXTERNAL_INT_BIT_INDEX, str8100_gpio_irq_handler, 0, "testing", NULL))){
++ printk("%s: request_irq failed(ret=0x%x)(-EBUSY=0x%x)\n",__FUNCTION__,ret,-EBUSY);
++ return -EBUSY;
++ }
++
++ return 0;
++}
++
++static void __exit test_exit(void){
++ printk("%s: \n",__FUNCTION__);
++ free_irq(INTC_GPIO_EXTERNAL_INT_BIT_INDEX,NULL);
++}
++
++module_init(test_init);
++module_exit(test_exit);
++
+diff -rupN linux-2.6.35.11/drivers/star/str8100/str8100_led.c linux-2.6.35.11-ts7500/drivers/star/str8100/str8100_led.c
+--- linux-2.6.35.11/drivers/star/str8100/str8100_led.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/star/str8100/str8100_led.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,158 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <asm/arch/star_gpio.h>
++
++#define LED_MASK_A 0xfe3fe07f
++#define LED_MASK_B 0xffe0dfff
++
++#if 0
++#define LED_MASK LED_MASK_A
++#define GPIO_DIRECTION_REG GPIOA_DIRECTION_REG
++#define GPIO_DATA_OUTPUT_REG GPIOA_DATA_OUTPUT_REG
++#define GPIO_DATA_BIT_SET_REG GPIOA_DATA_BIT_SET_REG
++#define GPIO_DATA_BIT_CLEAR_REG GPIOA_DATA_BIT_CLEAR_REG
++#else
++#define LED_MASK LED_MASK_B
++#define GPIO_DIRECTION_REG GPIOB_DIRECTION_REG
++#define GPIO_DATA_OUTPUT_REG GPIOB_DATA_OUTPUT_REG
++#define GPIO_DATA_BIT_SET_REG GPIOB_DATA_BIT_SET_REG
++#define GPIO_DATA_BIT_CLEAR_REG GPIOB_DATA_BIT_CLEAR_REG
++#endif
++
++
++#define LED_DELAY_MS 50
++
++/*
++ * Configure all LEDs on
++ */
++void str8100_led_all_on(void)
++{
++ /*
++ * perform Write Low to GPIO Pin
++ */
++ GPIO_DATA_BIT_CLEAR_REG |= LED_MASK;
++}
++
++
++
++/*
++ * Configure all LEDs off
++ */
++void str8100_led_all_off(void)
++{
++ /*
++ * perform Write High to GPIO Pin
++ */
++ GPIO_DATA_BIT_SET_REG |= LED_MASK;
++}
++
++
++/*
++ * Configure one LED on
++ */
++void str8100_led_on(unsigned int led_index)
++{
++ /*
++ * perform Write Low to GPIO Pin
++ */
++ GPIO_DATA_BIT_CLEAR_REG |= (led_index & LED_MASK);
++}
++
++
++/*
++ * Configure one LED off
++ */
++void str8100_led_off(unsigned int led_index)
++{
++ /*
++ * perform Write High to GPIO Pin
++ */
++ GPIO_DATA_BIT_SET_REG |= (led_index & LED_MASK);
++}
++
++
++
++/*
++ * Toggle one LED on/off
++ */
++void str8100_led_toggle(unsigned int led_index)
++{
++ volatile unsigned int data_out_state;
++
++
++ /*
++ * 1. read GPIO Data Out State
++ * 2. if GPIO High, turn LED on, otherwise, turn LED off
++ */
++ data_out_state = GPIO_DATA_OUTPUT_REG;
++
++ if (data_out_state & led_index& LED_MASK)
++ {
++ // GPIO High, i.e., LED is off. Now, turn it on
++ str8100_led_on(led_index & LED_MASK);
++ }
++ else
++ {
++ // GPIO Low, i.e., LED is on. Now turn it off
++ str8100_led_off(led_index & LED_MASK);
++ }
++}
++
++
++/*
++ * Initilaize LED settings
++ */
++void str8100_led_init(void)
++{
++ volatile unsigned int ii;
++
++
++ /*
++ * Configure all GPIO pins as follows:
++ * 1. output pins
++ * 2. turn all leds off
++ * 3. sequentially turn all leds on and all leds off
++ * then, we can set GPIO Low to turn LED On, and GPIO High to turn LED Off
++ */
++ printk("%s: \n",__FUNCTION__);
++
++ GPIO_DIRECTION_REG |= LED_MASK;
++
++ str8100_led_all_off();
++
++ for (ii = 0; ii < 32; ii++)
++ {
++ if(1<<ii&LED_MASK){
++//printk("%s: ii=%d\n",__FUNCTION__,ii);
++ str8100_led_on(1 << ii);
++ msleep(LED_DELAY_MS);
++ str8100_led_off(1 << ii);
++// msleep(LED_DELAY_MS);
++
++ }
++ }
++}
++
+diff -rupN linux-2.6.35.11/drivers/star/str9100/Makefile linux-2.6.35.11-ts7500/drivers/star/str9100/Makefile
+--- linux-2.6.35.11/drivers/star/str9100/Makefile 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/star/str9100/Makefile 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,32 @@
++################################################################################
++#
++#
++# Copyright(c) 2005 - Star semiconduction. 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 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.
++#
++# The full GNU General Public License is included in this distribution in the
++# file called LICENSE.
++#
++# Contact Information:
++# Star semiconduction Linux Support <support at starsemi.com>
++#
++################################################################################
++
++obj-y += str9100_tool.o
++
++obj-$(CONFIG_STR9100_INFO) += str9100_info.o
++obj-$(CONFIG_STR9100_SHNAT) += str9100_shnat_hook.o
++
+diff -rupN linux-2.6.35.11/drivers/star/str9100/str9100_info.c linux-2.6.35.11-ts7500/drivers/star/str9100/str9100_info.c
+--- linux-2.6.35.11/drivers/star/str9100/str9100_info.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/star/str9100/str9100_info.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,755 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/version.h>
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,32)
++#define LINUX24 1
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++#define LINUX26 1
++#endif
++
++#include <linux/stddef.h>
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <asm/byteorder.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/string.h>
++#include <linux/proc_fs.h>
++#include <asm/arch/hardware.h>
++#include <linux/kdev_t.h>
++#include <linux/miscdevice.h>
++#include <asm/uaccess.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/system.h>
++#include "../../net/str9100/star_gsw.h"
++
++#ifdef LINUX24
++#include <asm/arch/str9100_info.h>
++#include <asm/arch/str9100/star_tool.h>
++#include <asm/arch/str9100/star_gsw.h>
++#endif
++
++#ifdef LINUX26
++#include <linux/str9100/str9100_tool.h>
++#include <linux/str9100/str9100_info.h>
++#endif
++
++
++
++
++
++
++
++
++static const char *cpu_str[]={
++"175",
++"200",
++"225",
++"250"};
++
++static const char *v18_str[] = {
++"1.537",
++"1.594",
++"1.655",
++"1.721",
++"1.793",
++"1.871",
++"1.956",
++"2.049"};
++
++static const char *pciclk_str[] = {
++"33",
++"66",
++"-"};
++
++static const char *dram_str[] = {
++"16",
++"32",
++"64",
++"-"};
++
++#ifdef LINUX24
++struct proc_dir_entry *str9100_info_proc;
++#endif
++
++
++typedef struct STR9100_INFO_{
++ u32 cpu;
++ u32 v18regular;
++ u32 pciclk;
++ u32 dram;
++}STR9100_INFO;
++
++static STR9100_INFO str9100_info;
++
++#ifdef LINUX26
++static struct proc_dir_entry *str9100_info_proc_entry;
++#endif
++
++
++#ifdef LINUX24
++int get_system_info(void){
++ u32 volatile temp;
++ temp = (((*(u32 volatile *)(IO_ADDRESS(0x77000014))) >> 6) & 0x3);
++ str9100_info.cpu = temp;
++
++ temp = (*(u32 volatile *)(IO_ADDRESS(0x77000018)));
++ temp = ((temp >> 11)&0x7);
++ str9100_info.v18regular = temp;
++
++#if defined(CONFIG_STAR9100_PCI66M)
++ str9100_info.pciclk = 1;
++#elif defined(CONFIG_STAR9100_PCI33M)
++ str9100_info.pciclk = 0;
++#elif
++ str9100_info.pciclk = 2;
++#endif
++
++#if defined(CONFIG_STR9100_DRAM_64M)
++ str9100_info.dram = 2;
++#elif defined(CONFIG_STR9100_DRAM_32M)
++ str9100_info.dram = 1;
++#elif defined(CONFIG_STR9100_DRAM_16M)
++ str9100_info.dram = 0;
++#else
++ str9100_info.dram = 3;
++#endif
++
++
++ return 0;
++}
++#endif
++
++#ifdef LINUX26
++static int get_system_info(void)
++{
++ u32 temp;
++ temp = (PWRMGT_RESET_LATCH_CONFIGURATION_REG >> 6) & 0x3;
++ str9100_info.cpu = temp;
++
++ temp = (PWRMGT_REGULATOR_CONTROL_REG >> 11) & 0x7;
++ temp = ((temp >> 11)&0x7);
++ str9100_info.v18regular = temp;
++
++#if defined(CONFIG_STR9100_PCI66M)
++ str9100_info.pciclk = 1;
++#elif defined(CONFIG_STR9100_PCI33M)
++ str9100_info.pciclk = 0;
++#else
++ str9100_info.pciclk = 2;
++#endif
++
++#if defined(CONFIG_STR9100_DRAM_64M)
++ str9100_info.dram = 2;
++#elif defined(CONFIG_STR9100_DRAM_32M)
++ str9100_info.dram = 1;
++#elif defined(CONFIG_STR9100_DRAM_16M)
++ str9100_info.dram = 0;
++#else
++ str9100_info.dram = 3;
++#endif
++
++ return 0;
++}
++#endif
++
++
++#ifdef LINUX24
++static int str9100_info_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){
++ int num = 0;
++
++ volatile unsigned long remap = (unsigned long)ioremap(FLASH_BASE_ADDR, FLASH_SIZE);
++ volatile u16 *addr = (u16 *)(remap + 0);
++
++ // for human readable
++ num += sprintf(page+num, "--- CPU \n");
++ num += sprintf(page+num, "CPU Clock: Str9100 %sMhz\n",cpu_str[str9100_info.cpu]);
++ num += sprintf(page+num, "1.8V Regulator Regulated vdd Output : %sv \n",v18_str[str9100_info.v18regular]);
++ num += sprintf(page+num, "--- Device \n");
++ num += sprintf(page+num, "PCI Clock: %sMhz\n",pciclk_str[str9100_info.pciclk]);
++ num += sprintf(page+num, "--- Memory \n");
++ num += sprintf(page+num, "DRAM Size: %sMBytes\n",dram_str[str9100_info.dram]);
++#ifdef CONFIG_CPU_ISCRATCHPAD_ENABLE
++ num += sprintf(page+num, "enable I-Scratchpad\n");
++#else
++ num += sprintf(page+num, "disable I-Scratchpad\n");
++#endif
++ num += sprintf(page+num, "flash type: %s\n", get_flash_type(addr) );
++
++
++ iounmap(remap);
++
++ return num;
++}
++#endif
++
++#ifdef LINUX26
++static int str9100_info_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
++{
++ int num = 0;
++
++ // for human readable
++ num += sprintf(page+num, "--- CPU \n");
++ num += sprintf(page+num, "CPU Clock: STR9100 %sMhz\n", cpu_str[str9100_info.cpu]);
++ num += sprintf(page+num, "1.8V Regulator Regulated vdd Output : %sv \n", v18_str[str9100_info.v18regular]);
++ num += sprintf(page+num, "--- Device \n");
++ num += sprintf(page+num, "PCI Clock: %sMhz\n", pciclk_str[str9100_info.pciclk]);
++ num += sprintf(page+num, "--- Memory \n");
++ num += sprintf(page+num, "DRAM Size: %sMBytes\n", dram_str[str9100_info.dram]);
++#ifdef CONFIG_CPU_ISPAD_ENABLE
++ num += sprintf(page+num, "I-Scratchpad enable\n");
++#else
++ num += sprintf(page+num, "I-Scratchpad disable\n");
++#endif
++ num += sprintf(page+num, "flash type: %s\n", get_flash_type());
++
++ return num;
++}
++#endif
++
++int str9100_info_write_proc(struct file *file, const char *buffer, unsigned long count, void *data){
++
++ return 0;
++}
++
++// copy form drivers/net/str9100/star_gsw_phy.h
++#ifdef LINUX26
++#define GSW_VLAN_VID_0_1 GSW_VLAN_VID_0_1_REG
++#define GSW_VLAN_VID_2_3 GSW_VLAN_VID_2_3_REG
++#define GSW_VLAN_VID_4_5 GSW_VLAN_VID_4_5_REG
++#define GSW_VLAN_VID_6_7 GSW_VLAN_VID_6_7_REG
++#define GSW_HNAT_CONFIG GSW_HNAT_CONFIG_REG
++#endif
++
++
++//#define CONFIG_SWITCH_IOCTL
++#ifdef CONFIG_SWITCH_IOCTL
++
++#define GSW_SET_VLAN_0_VID(vid) \
++{ \
++ ((GSW_VLAN_VID_0_1) &= (~(0xFFF << 0))); \
++ ((GSW_VLAN_VID_0_1) |= (((vid) & 0xFFF) << 0)); \
++}
++
++#define GSW_SET_VLAN_1_VID(vid) \
++{ \
++ ((GSW_VLAN_VID_0_1) &= (~(0xFFF << 12))); \
++ ((GSW_VLAN_VID_0_1) |= (((vid) & 0xFFF) << 12)); \
++}
++
++#define GSW_SET_VLAN_2_VID(vid) \
++{ \
++ ((GSW_VLAN_VID_2_3) &= (~(0xFFF << 0))); \
++ ((GSW_VLAN_VID_2_3) |= (((vid) & 0xFFF) << 0)); \
++}
++
++#define GSW_SET_VLAN_3_VID(vid) \
++{ \
++ ((GSW_VLAN_VID_2_3) &= (~(0xFFF << 12))); \
++ ((GSW_VLAN_VID_2_3) |= (((vid) & 0xFFF) << 12)); \
++}
++
++#define GSW_SET_VLAN_4_VID(vid) \
++{ \
++ ((GSW_VLAN_VID_4_5) &= (~(0xFFF << 0))); \
++ ((GSW_VLAN_VID_4_5) |= (((vid) & 0xFFF) << 0)); \
++}
++
++#define GSW_SET_VLAN_5_VID(vid) \
++{ \
++ ((GSW_VLAN_VID_4_5) &= (~(0xFFF << 12))); \
++ ((GSW_VLAN_VID_4_5) |= (((vid) & 0xFFF) << 12)); \
++}
++
++#define GSW_SET_VLAN_6_VID(vid) \
++{ \
++ ((GSW_VLAN_VID_6_7) &= (~(0xFFF << 0))); \
++ ((GSW_VLAN_VID_6_7) |= (((vid) & 0xFFF) << 0)); \
++}
++
++#define GSW_SET_VLAN_7_VID(vid) \
++{ \
++ ((GSW_VLAN_VID_6_7) &= (~(0xFFF << 12))); \
++ ((GSW_VLAN_VID_6_7) |= (((vid) & 0xFFF) << 12)); \
++}
++
++void change_vid(u8 gid, u16 vid)
++{
++ switch (gid)
++ {
++ case 0:
++ {
++ GSW_SET_VLAN_0_VID(vid);
++ break;
++ }
++ case 1:
++ {
++ GSW_SET_VLAN_1_VID(vid);
++ break;
++ }
++ case 2:
++ {
++ GSW_SET_VLAN_2_VID(vid);
++ break;
++ }
++ case 3:
++ {
++ GSW_SET_VLAN_3_VID(vid);
++ break;
++ }
++ case 4:
++ {
++ GSW_SET_VLAN_4_VID(vid);
++ break;
++ }
++ case 5:
++ {
++ GSW_SET_VLAN_5_VID(vid);
++ break;
++ }
++ case 6:
++ {
++ GSW_SET_VLAN_6_VID(vid);
++ break;
++ }
++ case 7:
++ {
++ GSW_SET_VLAN_7_VID(vid);
++ break;
++ }
++ }
++
++}
++
++int get_vid(u8 gid)
++{
++ switch (gid)
++ {
++ case 0:
++ {
++ return (GSW_VLAN_VID_0_1 & 0x0fff);
++ }
++ case 1:
++ {
++ return ((GSW_VLAN_VID_0_1 >> 12) & 0x0fff);
++ }
++ case 2:
++ {
++ return (GSW_VLAN_VID_2_3 & 0x0fff);
++ }
++ case 3:
++ {
++ return ((GSW_VLAN_VID_2_3 >> 12) & 0x0fff);
++ }
++ case 4:
++ {
++ return (GSW_VLAN_VID_4_5 & 0x0fff);
++ }
++ case 5:
++ {
++ return ((GSW_VLAN_VID_4_5 >> 12) & 0x0fff);
++ }
++ case 6:
++ {
++ return (GSW_VLAN_VID_6_7 & 0x0fff);
++ }
++ case 7:
++ {
++ return ((GSW_VLAN_VID_6_7 >> 12) & 0x0fff);
++ }
++ }
++
++ return -1;
++}
++#endif
++
++static int str9100_info_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){
++
++#if 1
++ int count,len;
++ char temp[STR9100_INFO_SIZE];
++#ifdef CONFIG_SWITCH_IOCTL
++ int merge_int;
++ u16 vvid_num;
++ VVIDContent vvid_content;
++ VGIDPair vgid_pair;
++ VGIDMAC vgid_mac;
++ u8 gid;
++ u32 shnat_wangid;
++ u32 hnat_cfg;
++
++ extern gsw_info_t star_gsw_info;
++
++#endif
++
++
++ switch (cmd) {
++
++#ifdef CONFIG_SWITCH_IOCTL
++ case STR9100_GSW_GET_SHNAT_WANGID:
++ copy_from_user(&shnat_wangid, (u32*)arg, sizeof(u32));
++ GSW_READ_HNAT_CONFIGURATION(hnat_cfg);
++ shnat_wangid = hnat_cfg >> 16;
++
++ copy_to_user((u32*)arg, &shnat_wangid, sizeof(u32));
++
++ return 0;
++
++ case STR9100_GSW_SET_SHNAT_WANGID:
++ copy_from_user(&shnat_wangid, (u32 *)arg, sizeof(u32));
++
++
++ GSW_READ_HNAT_CONFIGURATION(hnat_cfg);
++ hnat_cfg &= (~(0xff << 16));
++ //gid_bitmap=simple_strtol(buf_param1, NULL, 16);
++ printk("[kernel mode] shnat_wangid : %x\n", shnat_wangid);
++ hnat_cfg |= (shnat_wangid << 16);
++ GSW_WRITE_HNAT_CONFIGURATION(hnat_cfg);
++ return 0;
++#if 1
++ case STR9100_GSW_LOOKUP_ARL:
++ copy_from_user(&vgid_mac, (VGIDMAC *)arg, sizeof(VGIDMAC));
++ #if 0
++ printk("[kernel mode] STR9100_GSW_LOOKUP_ARL\n");
++ printk("[kernel mode] gid : %d\n", vgid_mac.gid_);
++ printk("[kernel mode] mac # %x:%x:%x:%x:%x:%x\n", vgid_mac.mac_[0], vgid_mac.mac_[1],vgid_mac.mac_[2],vgid_mac.mac_[3],vgid_mac.mac_[4],vgid_mac.mac_[5]);
++ #endif
++
++ //memcpy(vgid_mac.mac_, star_gsw_info.vlan[vgid_mac.gid_].vlan_mac, 6);
++
++ vgid_mac.vid_ = star_gsw_info.vlan[vgid_mac.gid_].vlan_vid;
++
++ printk("[kernel mode] gid : %d\n", vgid_mac.gid_);
++ printk("[kernel mode] vid : %d\n", vgid_mac.vid_);
++ //printk("[kernel mode] mac # %x:%x:%x:%x:%x:%x\n", vgid_mac.mac_[0], vgid_mac.mac_[1],vgid_mac.mac_[2],vgid_mac.mac_[3],vgid_mac.mac_[4],vgid_mac.mac_[5]);
++
++ if (star_gsw_search_arl_table(vgid_mac.mac_, vgid_mac.gid_)) {
++ return 1; // found
++ }
++ else {
++ return 0; // found
++ }
++ return 0;
++
++ // unrelated variable star_gsw_info
++ case STR9100_GSW_ADD_VID_MAC:
++ // add a mac into arl table
++ #if 0
++ printk("[kernel mode] STR9100_GSW_ADD_VID_MAC\n");
++ #endif
++ copy_from_user(&vgid_mac, (VGIDMAC *)arg, sizeof(VGIDMAC));
++ add_mac_into_arl(vgid_mac.gid_, vgid_mac.mac_);
++ return 0;
++
++ // unrelated variable star_gsw_info
++ // unrelated hnat
++ case STR9100_GSW_PURE_DEL_VID_MAC:
++ copy_from_user(&vgid_mac, (VGIDMAC *)arg, sizeof(VGIDMAC));
++ //star_gsw_del_arl_table(vgid_mac.mac_, vgid_mac.gid_);
++ del_mac_from_arl(vgid_mac.gid_, vgid_mac.mac_);
++ return 0;
++
++
++ // related hnat
++ case STR9100_GSW_DEL_VID_MAC:
++ #if 0
++ printk("[kernel mode] STR9100_GSW_DEL_VID_MAC\n");
++ #endif
++ copy_from_user(&vgid_mac, (VGIDMAC *)arg, sizeof(VGIDMAC));
++
++ del_my_vlan_mac(vgid_mac.gid_);
++ return 0;
++#endif
++ case STR9100_GSW_SET_VID_MAC:
++ copy_from_user(&vgid_mac, (VGIDMAC *)arg, sizeof(VGIDMAC));
++ #if 0
++ printk("[kernel mode] STR9100_GSW_SET_VID_MAC\n");
++ //printk("[kernel mode] net_device_index_ : %d\n", vgid_mac.net_device_index_);
++ printk("[kernel mode] gid : %d\n", vgid_mac.gid_);
++ printk("[kernel mode] vid : %d\n", vgid_mac.vid_);
++ printk("[kernel mode] mac # %x:%x:%x:%x:%x:%x\n", vgid_mac.mac_[0], vgid_mac.mac_[1],vgid_mac.mac_[2],vgid_mac.mac_[3],vgid_mac.mac_[4],vgid_mac.mac_[5]);
++ #endif
++
++ change_vid(vgid_mac.gid_, vgid_mac.vid_);
++ del_my_vlan_mac(vgid_mac.gid_);
++ config_my_vlan_mac(vgid_mac.gid_, vgid_mac.vid_, vgid_mac.mac_);
++ star_gsw_hnat_write_vlan_src_mac(vgid_mac.gid_, vgid_mac.mac_);
++ //gid_map_ary[vgid_mac.net_device_index_]=vgid_mac.gid_;
++ return 0;
++
++
++ case STR9100_GSW_GET_VID_MAC:
++ copy_from_user(&vgid_mac, (VGIDMAC *)arg, sizeof(VGIDMAC));
++ star_gsw_info.vlan[vgid_mac.gid_].vlan_gid;
++ vgid_mac.vid_ = star_gsw_info.vlan[vgid_mac.gid_].vlan_vid;
++ //vgid_mac.net_device_index_ =
++ memcpy(vgid_mac.mac_, star_gsw_info.vlan[vgid_mac.gid_].vlan_mac, 6);
++
++ #if 0
++ printk("[kernel mode] STR9100_GSW_GET_VID_MAC\n");
++ printk("[kernel mode] gid : %d\n", vgid_mac.gid_);
++ printk("[kernel mode] vid : %d\n", vgid_mac.vid_);
++ printk("[kernel mode] mac # %x:%x:%x:%x:%x:%x\n", vgid_mac.mac_[0], vgid_mac.mac_[1],vgid_mac.mac_[2],vgid_mac.mac_[3],vgid_mac.mac_[4],vgid_mac.mac_[5]);
++ #endif
++ copy_to_user((VGIDMAC*)arg, &vgid_mac, sizeof(VGIDMAC));
++
++
++ return 0;
++
++
++ case STR9100_GSW_SET_VID:
++ copy_from_user(&vgid_pair, (VGIDPair*)arg, sizeof(VGIDPair));
++
++ //printk("SET_VID\n");
++ //printk("vgid_pair.vid_", vgid_pair.vid_);
++ //printk("vgid_pair.gid_", vgid_pair.gid_);
++ if (0 <= vgid_pair.gid_ && vgid_pair.gid_ <=7)
++ {
++ change_vid(vgid_pair.gid_, vgid_pair.vid_);
++ return 0;
++ }
++ else
++ {
++ printk("not valid gid: %d\n", vgid_pair.gid_);
++ return -ENOTTY;
++ }
++
++ case STR9100_GSW_GET_VID:
++ copy_from_user(&vgid_pair, (VGIDPair*)arg, sizeof(VGIDPair));
++
++ //printk("GET_VID\n");
++ //printk("vgid_pair.vid_", vgid_pair.vid_);
++ //printk("vgid_pair.gid_", vgid_pair.gid_);
++ if (0 <= vgid_pair.gid_ && vgid_pair.gid_ <=7)
++ {
++ u16 vid=get_vid(vgid_pair.gid_);
++ vgid_pair.vid_=vid;
++ //printk("vid : %d\n", vid);
++ copy_to_user((VGIDPair*)arg, &vgid_pair, sizeof (VGIDPair));
++ return 0;
++ }
++ else
++ {
++ printk("not valid gid: %d\n", vgid_pair.gid_);
++ return -ENOTTY;
++ }
++
++#ifdef CONFIG_VVID
++ case STR9100_GSW_SET_VVID:
++ //copy_from_user(&vvid_data, (VVID *)arg, sizeof(VVID));
++ copy_from_user(&vvid_content, (VVIDContent *)arg, sizeof(VVIDContent));
++ //printk("vvid.pri_: %d\n", vvid_data.pri_);
++ //printk("vvid.vid_: %d\n", vvid_data.vid_);
++ merge_int = (vvid_content.pri_ << 12 | vvid_content.vid_);
++ if (vvid[merge_int]==0)
++ { // insert a vvid number (vvid_szie)
++ ++vvid_size;
++ vvid[merge_int]=vvid_content.vvid_num_;
++ vvid_ary[vvid_content.vvid_num_].pri_=vvid_content.pri_;
++ vvid_ary[vvid_content.vvid_num_].vid_=vvid_content.vid_;
++ //printk("in kernel vvid_ary[%d] => (%d, %d)\n", vvid_content.vvid_num_, vvid_ary[vvid_content.vvid_num_].pri_, vvid_ary[vvid_content.vvid_num_].vid_);
++ }
++ else
++ {
++ printk("vvid[%d] already exist\n", merge_int);
++ }
++ return vvid_size;
++
++
++ case STR9100_GSW_GET_VVID:
++ copy_from_user(&vvid_content, (VVIDContent *)arg, sizeof(VVIDContent));
++ //printk("in kernel vvid_content.vvid_num_: %d\n", vvid_content.vvid_num_);
++ vvid_content.pri_ = vvid_ary[vvid_content.vvid_num_].pri_;
++ vvid_content.vid_ = vvid_ary[vvid_content.vvid_num_].vid_;
++ printk("in get kernel vvid_ary[%d] => (%d, %d)\n", vvid_content.vvid_num_, vvid_content.pri_, vvid_content.vid_);
++ copy_to_user((VVIDContent*)arg, &vvid_content, sizeof (VVIDContent));
++ return 0;
++ break;
++
++#endif // CONFIG_VVID
++#endif // end CONFIG_SWITCH_IOCTL
++
++
++ case STR9100_INFO_IOCGETD:
++ printk("STR9100_INFO_IOCGETD \n");
++ copy_to_user((unsigned char *)arg, (unsigned char *)&str9100_info, sizeof(str9100_info));
++ goto ioctlexit;
++
++ case STR9100_INFO_IOCSETD:
++ printk("STR9100_INFO_IOCSETD \n");
++ //if (copy_from_user(temp, (unsigned char *)arg, count))
++ // return -EFAULT;
++ goto ioctlexit;
++
++ case STR9100_INFO_IOCPUCLK:
++ len = strlen(cpu_str[str9100_info.cpu]);
++ strcpy(temp,cpu_str[str9100_info.cpu]);
++ break;
++
++ case STR9100_INFO_IOV18:
++ len = strlen(v18_str[str9100_info.v18regular]);
++ strcpy(temp,v18_str[str9100_info.v18regular]);
++ break;
++
++ case STR9100_INFO_IOPCICLK:
++ len = strlen(pciclk_str[str9100_info.pciclk]);
++ strcpy(temp,pciclk_str[str9100_info.pciclk]);
++ break;
++
++ case STR9100_INFO_IODRAMSZ:
++ len = strlen(dram_str[str9100_info.dram]);
++ strcpy(temp,dram_str[str9100_info.dram]);
++ break;
++
++
++
++ default:
++ return -ENOTTY;
++ /* return -EINVAL; another return option */
++ }
++
++
++ copy_to_user((unsigned char *)arg,temp,len+1);
++
++
++
++ioctlexit:
++#endif
++ return 0;
++}
++
++static int str9100_info_open(struct inode *inode, struct file *file)
++{
++ unsigned int minor = MINOR(inode->i_rdev);
++ if (minor != STR9100_INFO_MINOR)
++ return -ENODEV;
++
++#ifdef MODULE
++ MOD_INC_USE_COUNT;
++#endif
++
++ return 0;
++}
++
++
++static int str9100_info_release(struct inode *inode, struct file *file)
++{
++
++#ifdef MODULE
++ MOD_DEC_USE_COUNT;
++#endif
++
++ return 0;
++}
++
++
++/*
++ * ioctl interface
++ */
++static struct file_operations str9100_info_fops =
++{
++ owner: THIS_MODULE,
++ ioctl: str9100_info_ioctl,
++ open: str9100_info_open,
++ release: str9100_info_release,
++};
++
++/* STR9100_MINOR in include/linux/miscdevice.h */
++static struct miscdevice str9100_info_miscdev =
++{
++ STR9100_INFO_MINOR,
++ "str9100_info",
++ &str9100_info_fops
++};
++
++
++#ifdef LINUX24
++static int __init str9100_info_init(void){
++ struct proc_dir_entry *procdir=0;
++
++
++ get_system_info();
++
++ misc_register(&str9100_info_miscdev);
++
++ //proc_mkdir("str9100",0);
++ procdir= create_proc_str9100(PROC_STR);
++ if (procdir)
++ {
++ str9100_info_proc = create_proc_entry("info", S_IFREG | S_IRUGO, procdir);
++ if (str9100_info_proc) {
++ str9100_info_proc->read_proc = str9100_info_read_proc;
++ str9100_info_proc->write_proc = str9100_info_write_proc;
++ }
++ printk("Str9100 Information inited \n");
++ return 0;
++ }
++ else
++ return -1;
++
++ //str9100_info_proc=create_proc_read_entry( "str9100/info", 0, NULL, str9100_info_read_proc,NULL) ;
++ //str9100_info_proc->write_proc=star9100_info_write_proc;
++
++
++}
++#endif
++
++#ifdef LINUX26
++static int __init str9100_info_init(void)
++{
++ get_system_info();
++
++ str9100_info_proc_entry = create_proc_entry("str9100/info", S_IFREG | S_IRUGO, NULL);
++ if (str9100_info_proc_entry) {
++ str9100_info_proc_entry->read_proc = str9100_info_read_proc;
++ str9100_info_proc_entry->write_proc = str9100_info_write_proc;
++ }
++
++ misc_register(&str9100_info_miscdev);
++
++ return 1;
++}
++#endif
++
++
++static void __exit str9100_info_exit(void){
++
++ misc_deregister(&str9100_info_miscdev);
++
++ remove_proc_entry("str9100/info",NULL);
++
++ printk("Str9100 Information exit \n");
++}
++
++module_init(str9100_info_init);
++module_exit(str9100_info_exit);
++
+diff -rupN linux-2.6.35.11/drivers/star/str9100/str9100_info.c.26 linux-2.6.35.11-ts7500/drivers/star/str9100/str9100_info.c.26
+--- linux-2.6.35.11/drivers/star/str9100/str9100_info.c.26 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/star/str9100/str9100_info.c.26 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,262 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/stddef.h>
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <asm/byteorder.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/string.h>
++#include <linux/proc_fs.h>
++#include <asm/arch/hardware.h>
++#include <linux/kdev_t.h>
++#include <linux/miscdevice.h>
++#include <asm/uaccess.h>
++
++#include <linux/str9100/str9100_tool.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/system.h>
++
++static const char *cpu_str[] = {
++"175",
++"200",
++"225",
++"250"
++};
++
++static const char *v18_str[] = {
++"1.537",
++"1.594",
++"1.655",
++"1.721",
++"1.793",
++"1.871",
++"1.956",
++"2.049"
++};
++
++static const char *pciclk_str[] = {
++"33",
++"66",
++"-"
++};
++
++static const char *dram_str[] = {
++"16",
++"32",
++"64",
++"-"
++};
++
++typedef struct STR9100_INFO {
++ u32 cpu;
++ u32 v18regular;
++ u32 pciclk;
++ u32 dram;
++} STR9100_INFO;
++
++static STR9100_INFO str9100_info;
++static struct proc_dir_entry *str9100_info_proc_entry;
++
++static int get_system_info(void)
++{
++ u32 temp;
++ temp = (PWRMGT_RESET_LATCH_CONFIGURATION_REG >> 6) & 0x3;
++ str9100_info.cpu = temp;
++
++ temp = (PWRMGT_REGULATOR_CONTROL_REG >> 11) & 0x7;
++ temp = ((temp >> 11)&0x7);
++ str9100_info.v18regular = temp;
++
++#if defined(CONFIG_STR9100_PCI66M)
++ str9100_info.pciclk = 1;
++#elif defined(CONFIG_STR9100_PCI33M)
++ str9100_info.pciclk = 0;
++#else
++ str9100_info.pciclk = 2;
++#endif
++
++#if defined(CONFIG_STR9100_DRAM_64M)
++ str9100_info.dram = 2;
++#elif defined(CONFIG_STR9100_DRAM_32M)
++ str9100_info.dram = 1;
++#elif defined(CONFIG_STR9100_DRAM_16M)
++ str9100_info.dram = 0;
++#else
++ str9100_info.dram = 3;
++#endif
++
++ return 0;
++}
++
++static int str9100_info_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
++{
++ int num = 0;
++
++ // for human readable
++ num += sprintf(page+num, "--- CPU \n");
++ num += sprintf(page+num, "CPU Clock: STR9100 %sMhz\n", cpu_str[str9100_info.cpu]);
++ num += sprintf(page+num, "1.8V Regulator Regulated vdd Output : %sv \n", v18_str[str9100_info.v18regular]);
++ num += sprintf(page+num, "--- Device \n");
++ num += sprintf(page+num, "PCI Clock: %sMhz\n", pciclk_str[str9100_info.pciclk]);
++ num += sprintf(page+num, "--- Memory \n");
++ num += sprintf(page+num, "DRAM Size: %sMBytes\n", dram_str[str9100_info.dram]);
++#ifdef CONFIG_CPU_ISPAD_ENABLE
++ num += sprintf(page+num, "I-Scratchpad enable\n");
++#else
++ num += sprintf(page+num, "I-Scratchpad disable\n");
++#endif
++ num += sprintf(page+num, "flash type: %s\n", get_flash_type());
++
++ return num;
++}
++
++static int str9100_info_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
++{
++ return 0;
++}
++
++static int str9100_info_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ int count,len;
++ char temp[STR9100_INFO_SIZE];
++
++ switch (cmd) {
++ case STR9100_INFO_IOCGETD:
++ printk("STR9100_INFO_IOCGETD \n");
++ copy_to_user((unsigned char *)arg, (unsigned char *)&str9100_info, sizeof(str9100_info));
++ break;
++
++ case STR9100_INFO_IOCSETD:
++ printk("STR9100_INFO_IOCSETD \n");
++ //if (copy_from_user(temp, (unsigned char *)arg, count))
++ //return -EFAULT;
++ break;
++
++ case STR9100_INFO_IOCPUCLK:
++ len = strlen(cpu_str[str9100_info.cpu]);
++ strcpy(temp,cpu_str[str9100_info.cpu]);
++ copy_to_user((unsigned char *)arg, temp, len + 1);
++ break;
++
++ case STR9100_INFO_IOV18:
++ len = strlen(v18_str[str9100_info.v18regular]);
++ strcpy(temp,v18_str[str9100_info.v18regular]);
++ copy_to_user((unsigned char *)arg, temp, len + 1);
++ break;
++
++ case STR9100_INFO_IOPCICLK:
++ len = strlen(pciclk_str[str9100_info.pciclk]);
++ strcpy(temp,pciclk_str[str9100_info.pciclk]);
++ copy_to_user((unsigned char *)arg, temp, len + 1);
++ break;
++
++ case STR9100_INFO_IODRAMSZ:
++ len = strlen(dram_str[str9100_info.dram]);
++ strcpy(temp,dram_str[str9100_info.dram]);
++ copy_to_user((unsigned char *)arg, temp, len + 1);
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int str9100_info_open(struct inode *inode, struct file *file)
++{
++ unsigned int minor = MINOR(inode->i_rdev);
++ if (minor != STR9100_INFO_MINOR)
++ return -ENODEV;
++
++#ifdef MODULE
++ MOD_INC_USE_COUNT;
++#endif
++
++ return 0;
++}
++
++
++static int str9100_info_release(struct inode *inode, struct file *file)
++{
++#ifdef MODULE
++ MOD_DEC_USE_COUNT;
++#endif
++
++ return 0;
++}
++
++
++/*
++ * ioctl interface
++ */
++static struct file_operations str9100_info_fops =
++{
++ owner: THIS_MODULE,
++ ioctl: str9100_info_ioctl,
++ open: str9100_info_open,
++ release: str9100_info_release,
++};
++
++/* STR9100_MINOR in include/linux/miscdevice.h */
++static struct miscdevice str9100_info_miscdev =
++{
++ STR9100_INFO_MINOR,
++ "str9100_info",
++ &str9100_info_fops
++};
++
++static int __init str9100_info_init(void)
++{
++ get_system_info();
++
++ str9100_info_proc_entry = create_proc_entry("str9100/info", S_IFREG | S_IRUGO, NULL);
++ if (str9100_info_proc_entry) {
++ str9100_info_proc_entry->read_proc = str9100_info_read_proc;
++ str9100_info_proc_entry->write_proc = str9100_info_write_proc;
++ }
++
++ misc_register(&str9100_info_miscdev);
++
++ return 1;
++}
++
++static void __exit str9100_info_exit(void)
++{
++ misc_deregister(&str9100_info_miscdev);
++ remove_proc_entry("str9100/info", NULL);
++}
++
++module_init(str9100_info_init);
++module_exit(str9100_info_exit);
++
+diff -rupN linux-2.6.35.11/drivers/star/str9100/str9100_shnat_hook.c linux-2.6.35.11-ts7500/drivers/star/str9100/str9100_shnat_hook.c
+--- linux-2.6.35.11/drivers/star/str9100/str9100_shnat_hook.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/star/str9100/str9100_shnat_hook.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,78 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/config.h>
++
++#ifdef CONFIG_NETFILTER
++#include <linux/types.h>
++#include <linux/inetdevice.h>
++#include <linux/ip.h>
++#include <linux/timer.h>
++#include <linux/module.h>
++#include <linux/netfilter.h>
++#include <net/protocol.h>
++#include <net/ip.h>
++#include <net/checksum.h>
++#include <net/route.h>
++#include <linux/netfilter_ipv4.h>
++#include <linux/netfilter_ipv4/ip_nat_rule.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++
++#include <linux/str9100/star9100_shnat.h>
++#include <linux/str9100/str9100_shnat_hook.h>
++
++//#ifdef CONFIG_STAR9100_SHNAT_PCI_FASTPATH
++struct net_device *pci_netdev[MAX_FP_PCIDEV];
++EXPORT_SYMBOL(pci_netdev);
++int (*star9100_shnat_pci_fp_forward_skb_ptr)(struct sk_buff *skb);
++//#endif
++
++int star9100_shnat_hook_ready;
++int (*star9100_shnat_preadd_hnatable_hook)(u32 sip,u16 sport,u16 dport, u32 proto);
++int (*star9100_shnat_check_shnat_enable_hook)(void);
++int (*star9100_shnat_nf_nat_preadd_hnatable_hook)(const struct ip_conntrack *ct, int dir, const u16 port);
++int (*star9100_shnat_nf_remove_hnatable_hook)(struct ip_conntrack *);
++int (*star9100_shnat_nf_add_hnatable_hook)(const struct ip_conntrack *ct,const struct iphdr *iph, u16 proto);
++int (*star9100_shnat_add_arptable_hook)(u32 myip, u32 targetip);
++int (*star9100_shnat_fix_arptable_hook)(u32 myip, u32 targetip);
++int (*star9100_shnat_nf_preadd_hnatable_hook)(const struct sk_buff **pskb);
++int (*star9100_shnat_check_ftponly_enable_hook)(void);
++int (*star9100_shnat_pci_fp_getdev_hook)(struct sk_buff *skb_ptr);
++star9100_arp_table *(*star9100_shnat_getarptable_hook)( u32 ip_addr);
++
++
++EXPORT_SYMBOL(star9100_shnat_hook_ready);
++EXPORT_SYMBOL(star9100_shnat_preadd_hnatable_hook);
++EXPORT_SYMBOL(star9100_shnat_check_shnat_enable_hook);
++EXPORT_SYMBOL(star9100_shnat_nf_nat_preadd_hnatable_hook);
++EXPORT_SYMBOL(star9100_shnat_nf_remove_hnatable_hook);
++EXPORT_SYMBOL(star9100_shnat_nf_add_hnatable_hook);
++EXPORT_SYMBOL(star9100_shnat_add_arptable_hook);
++EXPORT_SYMBOL(star9100_shnat_fix_arptable_hook);
++EXPORT_SYMBOL(star9100_shnat_nf_preadd_hnatable_hook);
++EXPORT_SYMBOL(star9100_shnat_check_ftponly_enable_hook);
++EXPORT_SYMBOL(star9100_shnat_getarptable_hook);
++EXPORT_SYMBOL(star9100_shnat_pci_fp_getdev_hook);
++EXPORT_SYMBOL(star9100_shnat_pci_fp_forward_skb_ptr);
++
++#endif
+diff -rupN linux-2.6.35.11/drivers/star/str9100/str9100_tool.c linux-2.6.35.11-ts7500/drivers/star/str9100/str9100_tool.c
+--- linux-2.6.35.11/drivers/star/str9100/str9100_tool.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/star/str9100/str9100_tool.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,287 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/version.h>
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,32)
++#define LINUX24 1
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
++#define LINUX26 1
++#endif
++
++#ifdef LINUX24
++#include <asm/arch/str9100/star_tool.h>
++#endif
++
++#ifdef LINUX26
++#include <linux/str9100/str9100_tool.h>
++#endif
++
++#include <linux/proc_fs.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/system.h>
++#include <linux/delay.h>
++
++
++
++#ifdef LINUX24
++// for star_tool.h create_proc_str9100()
++//int create_proc_dir=0;
++
++
++struct proc_dir_entry *create_proc_str9100(const char* proc_str)
++{
++ struct proc_dir_entry *de;
++ struct proc_dir_entry *str9100_gsw_procdir=0;
++
++
++ de = &proc_root;
++ for (de = de->subdir; de ; de = de->next) {
++ if (strcmp(de->name, "str9100")==0) // find it
++ {
++ return de;
++ }
++ }
++
++ // not found /proc/str9100, so create it.
++
++
++ str9100_gsw_procdir=proc_mkdir(proc_str, NULL);
++ if (str9100_gsw_procdir==0)
++ return 0;
++
++
++ return str9100_gsw_procdir;
++}
++#endif
++
++
++
++#define CONFIG_GET_FLASH_VAR
++#ifdef CONFIG_GET_FLASH_VAR
++// add by descent 2006/07/20
++
++/* Add for read MAC from FLASH. */
++#ifndef __ARM_BE__
++#define B0(h) ((h) & 0xFF)
++#define B1(h) (((h) >> 8) & 0xFF)
++#else
++#define B0(h) (((h) >> 8) & 0xFF)
++#define B1(h) ((h) & 0xFF)
++#endif
++
++void copy_from_flash(unsigned long from, void *to,ssize_t len)
++{
++ int i;
++ u8 *dest = (u8*)to;
++ u16 data;
++ unsigned long remap = (unsigned long)ioremap(FLASH_BASE_ADDR,FLASH_SIZE);
++ u16 *src = (u16 *)(remap + from);
++
++ for(i = 0; i < (len / 2);i++){
++ data = src[i];
++ dest[i * 2] = B0(data);
++ dest[i * 2 + 1] = B1(data);
++
++ }
++ if(len & 1)
++ dest[len - 1] = B0(src[i]);
++ iounmap(remap);
++}
++
++#if 0
++char *get_flash_env(const char *env_name)
++{
++ const int ENV_SIZE=0x8000;
++ //const char *ENV_BEGIN=FLASH_ADDRESS(0x10000000)+0x20000;
++ //const char *ENV_BEGIN=FLASH_ADDRESS(0x10020000);
++ unsigned long from=0x20000;
++
++ volatile unsigned long remap = (unsigned long)ioremap(FLASH_BASE_ADDR, FLASH_SIZE);
++ volatile u8 *src = (u16 *)(remap + from);
++
++ int i=0;
++ char *str_p=env_name;
++ char *beg_p=src;
++ char *p;
++
++
++ while(1) {
++ p=strstr(beg_p, env_name);
++ if (p) { // found
++ char *asign_p=strchr(p, '=');
++ if (asign_p)
++ {
++ iounmap(remap);
++ return asign_p+1;
++ }
++ else
++ break; // should not this case
++ }
++ else
++ {
++ ++beg_p;
++ }
++
++ if (p > src+ENV_SIZE) {
++ break;
++ }
++ }
++ iounmap(remap);
++ return 0; // not found
++}
++#else
++// copy from 2.6.16
++char *get_flash_env(const char *env_name)
++{
++ const int ENV_SIZE = 0x8000;
++ unsigned long from = 0x20000;
++
++ u8 *remap = ioremap(FLASH_BASE_ADDR, FLASH_SIZE);
++ volatile u8 *src = (volatile u8 *)(remap + from);
++
++ char *str_p = env_name;
++ char *beg_p = src;
++ char *p;
++
++ while (1) {
++ p = strstr(beg_p, str_p);
++ if (p) { // found
++ char *asign_p = strchr(p, '=');
++ if (asign_p) {
++ iounmap(remap);
++ return asign_p + 1;
++ } else
++ break; // should not this case
++ } else {
++ ++beg_p;
++ }
++ if (p > (src + ENV_SIZE)) {
++ break;
++ }
++ }
++ iounmap(remap);
++ return 0; // not found
++}
++
++#endif
++#endif // ifdef CONFIG_GET_FLASH_VAR
++
++
++/*
++ * * MXIC's flash manufacture ID
++ * */
++#define MX_MANUFACT 0x00C200C2 /* MXIC manuf. ID in D23..D16, D7..D0 */
++
++
++#define MXIC_MANUFACTURE_ID 0x00C20000
++
++/*
++ * * MXIC's flash device ID
++ * */
++#define MXIC_DEVICE_ID_MX29LV320B 0x000000A8
++#define MX_ID_LV640BB 0x22CB22CB /* 29LV640BB by Macronix, AMD compatible */
++#define MX_ID_LV640BT 0x22C922C9 /* 29LV640BT by Macronix, AMD compatible */
++
++#ifdef LINUX24
++const char *get_flash_type(volatile u16 *saddr)
++{
++ short i;
++ u16 mid;
++ u16 did;
++ int name_index=0;
++ const char *flash_name[]={
++ 0,
++ "EON_EN29LV640HL(8MB)",
++ "MXIC_MX29LV640BT(8MB)"
++ };
++ //u32 base = (u32)addr;
++
++ //volatile unsigned long remap = (unsigned long)ioremap(FLASH_BASE_ADDR, FLASH_SIZE);
++ //volatile u16 *saddr = (u16 *)(remap + 0);
++
++ //volatile u8 *src = (u16 *)(remap + 0);
++ //volatile u8 *saddr = src;
++
++ /* Write auto select command: read Manufacturer ID */
++ saddr[0x555] = 0xAA;
++ saddr[0x2AA] = 0x55;
++ saddr[0x555] = 0x90;
++
++ mid = saddr[0];
++ did = saddr[1];
++
++ if ( ((mid & 0xffff) == 0x007f) && ((did & 0xFFFF) == 0x227e) ) // "EON_EN29LV640HL(8MB)"
++ name_index=1;
++ if ( ((mid & 0xffff) == 0x00c2) && ((did & 0xFFFF) == 0x22c9) ) // "MXIC_MX29LV640BT(8MB)"
++ name_index=2;
++
++
++
++ /* reset to read mode */
++ saddr[0] = 0xF0; /* reset the bank */
++ udelay(10000);
++
++ return flash_name[name_index];
++}
++#endif
++
++#ifdef LINUX26
++const char *get_flash_type(void)
++{
++ u8 *remap = ioremap(FLASH_BASE_ADDR, FLASH_SIZE);
++ volatile u16 *saddr = (volatile u16 *)remap;
++ u16 mid;
++ u16 did;
++ int name_index = 0;
++ const char *flash_name[] = {
++ 0,
++ "EON_EN29LV640HL(8MB)",
++ "MXIC_MX29LV640BT(8MB)"
++ };
++
++ /* Write auto select command: read Manufacturer ID */
++ saddr[0x555] = 0xAA;
++ saddr[0x2AA] = 0x55;
++ saddr[0x555] = 0x90;
++
++ mid = saddr[0];
++ did = saddr[1];
++
++ if (((mid & 0xffff) == 0x007f) && ((did & 0xFFFF) == 0x227e) ) // "EON_EN29LV640HL(8MB)"
++ name_index=1;
++ if (((mid & 0xffff) == 0x00c2) && ((did & 0xFFFF) == 0x22c9) ) // "MXIC_MX29LV640BT(8MB)"
++ name_index=2;
++
++ /* reset to read mode */
++ saddr[0] = 0xF0; /* reset the bank */
++ udelay(1000);
++
++ iounmap(remap);
++
++ return flash_name[name_index];
++}
++#endif
++
+diff -rupN linux-2.6.35.11/drivers/star/str9100/str9100_tool.c.26 linux-2.6.35.11-ts7500/drivers/star/str9100/str9100_tool.c.26
+--- linux-2.6.35.11/drivers/star/str9100/str9100_tool.c.26 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/star/str9100/str9100_tool.c.26 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,145 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/proc_fs.h>
++#include <linux/delay.h>
++
++//#include <asm/arch/star_tool.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/system.h>
++
++#define CONFIG_GET_FLASH_VAR
++
++#ifdef CONFIG_GET_FLASH_VAR
++// add by descent 2006/07/20
++/* Add for read MAC from FLASH. */
++#ifndef __ARM_BE__
++#define B0(h) ((h) & 0xFF)
++#define B1(h) (((h) >> 8) & 0xFF)
++#else
++#define B0(h) (((h) >> 8) & 0xFF)
++#define B1(h) ((h) & 0xFF)
++#endif
++
++void copy_from_flash(unsigned long from, void *to, ssize_t len)
++{
++ int i;
++ u8 *dest = (u8*)to;
++ u16 data;
++ u8 *remap = ioremap(FLASH_BASE_ADDR, FLASH_SIZE);
++ volatile u16 *src = (volatile u16 *)(remap + from);
++
++ for (i = 0; i < (len / 2); i++) {
++ data = src[i];
++ dest[i * 2] = B0(data);
++ dest[i * 2 + 1] = B1(data);
++ }
++
++ if (len & 1)
++ dest[len - 1] = B0(src[i]);
++
++ iounmap(remap);
++}
++
++char *get_flash_env(const char *env_name)
++{
++ const int ENV_SIZE = 0x8000;
++ unsigned long from = 0x20000;
++
++ u8 *remap = ioremap(FLASH_BASE_ADDR, FLASH_SIZE);
++ volatile u8 *src = (volatile u8 *)(remap + from);
++
++ char *str_p = env_name;
++ char *beg_p = src;
++ char *p;
++
++ while (1) {
++ p = strstr(beg_p, str_p);
++ if (p) { // found
++ char *asign_p = strchr(p, '=');
++ if (asign_p) {
++ iounmap(remap);
++ return asign_p + 1;
++ } else
++ break; // should not this case
++ } else {
++ ++beg_p;
++ }
++ if (p > (src + ENV_SIZE)) {
++ break;
++ }
++ }
++ iounmap(remap);
++ return 0; // not found
++}
++#endif
++
++/*
++ * MXIC's flash manufacture ID
++ */
++#define MX_MANUFACT 0x00C200C2 /* MXIC manuf. ID in D23..D16, D7..D0 */
++#define MXIC_MANUFACTURE_ID 0x00C20000
++
++/*
++ * MXIC's flash device ID
++ */
++#define MXIC_DEVICE_ID_MX29LV320B 0x000000A8
++#define MX_ID_LV640BB 0x22CB22CB /* 29LV640BB by Macronix, AMD compatible */
++#define MX_ID_LV640BT 0x22C922C9 /* 29LV640BT by Macronix, AMD compatible */
++
++const char *get_flash_type(void)
++{
++ u8 *remap = ioremap(FLASH_BASE_ADDR, FLASH_SIZE);
++ volatile u16 *saddr = (volatile u16 *)remap;
++ u16 mid;
++ u16 did;
++ int name_index = 0;
++ const char *flash_name[] = {
++ 0,
++ "EON_EN29LV640HL(8MB)",
++ "MXIC_MX29LV640BT(8MB)"
++ };
++
++ /* Write auto select command: read Manufacturer ID */
++ saddr[0x555] = 0xAA;
++ saddr[0x2AA] = 0x55;
++ saddr[0x555] = 0x90;
++
++ mid = saddr[0];
++ did = saddr[1];
++
++ if (((mid & 0xffff) == 0x007f) && ((did & 0xFFFF) == 0x227e) ) // "EON_EN29LV640HL(8MB)"
++ name_index=1;
++ if (((mid & 0xffff) == 0x00c2) && ((did & 0xFFFF) == 0x22c9) ) // "MXIC_MX29LV640BT(8MB)"
++ name_index=2;
++
++ /* reset to read mode */
++ saddr[0] = 0xF0; /* reset the bank */
++ udelay(1000);
++
++ iounmap(remap);
++
++ return flash_name[name_index];
++}
++
+diff -rupN linux-2.6.35.11/drivers/usb/core/buffer.c linux-2.6.35.11-ts7500/drivers/usb/core/buffer.c
+--- linux-2.6.35.11/drivers/usb/core/buffer.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/usb/core/buffer.c 2011-03-14 11:18:24.000000000 -0400
+@@ -53,9 +53,11 @@ int hcd_buffer_create(struct usb_hcd *hc
+ char name[16];
+ int i, size;
+
++#if !defined(CONFIG_ARCH_STR9100) && !defined(CONFIG_ARCH_STR8100)
+ if (!hcd->self.controller->dma_mask &&
+ !(hcd->driver->flags & HCD_LOCAL_MEM))
+ return 0;
++#endif
+
+ for (i = 0; i < HCD_BUFFER_POOLS; i++) {
+ size = pool_max[i];
+diff -rupN linux-2.6.35.11/drivers/usb/host/ehci-hcd.c linux-2.6.35.11-ts7500/drivers/usb/host/ehci-hcd.c
+--- linux-2.6.35.11/drivers/usb/host/ehci-hcd.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/usb/host/ehci-hcd.c 2011-03-14 11:18:24.000000000 -0400
+@@ -722,7 +722,12 @@ static irqreturn_t ehci_irq (struct usb_
+ masked_status = status & INTR_MASK;
+ if (!masked_status) { /* irq sharing? */
+ spin_unlock(&ehci->lock);
+- return IRQ_NONE;
++#ifdef CONFIG_VIC_INTERRUPT
++ return IRQ_HANDLED;
++#else
++ return IRQ_NONE;
++#endif
++
+ }
+
+ /* clear (just) interrupts */
+@@ -1143,6 +1148,11 @@ MODULE_LICENSE ("GPL");
+ #define PLATFORM_DRIVER ehci_orion_driver
+ #endif
+
++#ifdef CONFIG_ARCH_STR8100
++#include "ehci-str8100.c"
++#define PLATFORM_DRIVER str8100_ehci_hcd_driver
++#endif
++
+ #ifdef CONFIG_ARCH_IXP4XX
+ #include "ehci-ixp4xx.c"
+ #define PLATFORM_DRIVER ixp4xx_ehci_driver
+diff -rupN linux-2.6.35.11/drivers/usb/host/ehci-hcd.c.orig linux-2.6.35.11-ts7500/drivers/usb/host/ehci-hcd.c.orig
+--- linux-2.6.35.11/drivers/usb/host/ehci-hcd.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/usb/host/ehci-hcd.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,1278 @@
++/*
++ * Copyright (c) 2000-2004 by David Brownell
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by the
++ * Free Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software Foundation,
++ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/pci.h>
++#include <linux/dmapool.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/ioport.h>
++#include <linux/sched.h>
++#include <linux/vmalloc.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/timer.h>
++#include <linux/ktime.h>
++#include <linux/list.h>
++#include <linux/interrupt.h>
++#include <linux/usb.h>
++#include <linux/usb/hcd.h>
++#include <linux/moduleparam.h>
++#include <linux/dma-mapping.h>
++#include <linux/debugfs.h>
++#include <linux/slab.h>
++
++#include <asm/byteorder.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++#include <asm/unaligned.h>
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * EHCI hc_driver implementation ... experimental, incomplete.
++ * Based on the final 1.0 register interface specification.
++ *
++ * USB 2.0 shows up in upcoming www.pcmcia.org technology.
++ * First was PCMCIA, like ISA; then CardBus, which is PCI.
++ * Next comes "CardBay", using USB 2.0 signals.
++ *
++ * Contains additional contributions by Brad Hards, Rory Bolt, and others.
++ * Special thanks to Intel and VIA for providing host controllers to
++ * test this driver on, and Cypress (including In-System Design) for
++ * providing early devices for those host controllers to talk to!
++ */
++
++#define DRIVER_AUTHOR "David Brownell"
++#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
++
++static const char hcd_name [] = "ehci_hcd";
++
++
++#undef VERBOSE_DEBUG
++#undef EHCI_URB_TRACE
++
++#ifdef DEBUG
++#define EHCI_STATS
++#endif
++
++/* magic numbers that can affect system performance */
++#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */
++#define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */
++#define EHCI_TUNE_RL_TT 0
++#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */
++#define EHCI_TUNE_MULT_TT 1
++#define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */
++
++#define EHCI_IAA_MSECS 10 /* arbitrary */
++#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */
++#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */
++#define EHCI_SHRINK_FRAMES 5 /* async qh unlink delay */
++
++/* Initial IRQ latency: faster than hw default */
++static int log2_irq_thresh = 0; // 0 to 6
++module_param (log2_irq_thresh, int, S_IRUGO);
++MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
++
++/* initial park setting: slower than hw default */
++static unsigned park = 0;
++module_param (park, uint, S_IRUGO);
++MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
++
++/* for flakey hardware, ignore overcurrent indicators */
++static int ignore_oc = 0;
++module_param (ignore_oc, bool, S_IRUGO);
++MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
++
++#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
++
++/*-------------------------------------------------------------------------*/
++
++#include "ehci.h"
++#include "ehci-dbg.c"
++
++/*-------------------------------------------------------------------------*/
++
++static void
++timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
++{
++ /* Don't override timeouts which shrink or (later) disable
++ * the async ring; just the I/O watchdog. Note that if a
++ * SHRINK were pending, OFF would never be requested.
++ */
++ if (timer_pending(&ehci->watchdog)
++ && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
++ & ehci->actions))
++ return;
++
++ if (!test_and_set_bit(action, &ehci->actions)) {
++ unsigned long t;
++
++ switch (action) {
++ case TIMER_IO_WATCHDOG:
++ if (!ehci->need_io_watchdog)
++ return;
++ t = EHCI_IO_JIFFIES;
++ break;
++ case TIMER_ASYNC_OFF:
++ t = EHCI_ASYNC_JIFFIES;
++ break;
++ /* case TIMER_ASYNC_SHRINK: */
++ default:
++ /* add a jiffie since we synch against the
++ * 8 KHz uframe counter.
++ */
++ t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
++ break;
++ }
++ mod_timer(&ehci->watchdog, t + jiffies);
++ }
++}
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * handshake - spin reading hc until handshake completes or fails
++ * @ptr: address of hc register to be read
++ * @mask: bits to look at in result of read
++ * @done: value of those bits when handshake succeeds
++ * @usec: timeout in microseconds
++ *
++ * Returns negative errno, or zero on success
++ *
++ * Success happens when the "mask" bits have the specified value (hardware
++ * handshake done). There are two failure modes: "usec" have passed (major
++ * hardware flakeout), or the register reads as all-ones (hardware removed).
++ *
++ * That last failure should_only happen in cases like physical cardbus eject
++ * before driver shutdown. But it also seems to be caused by bugs in cardbus
++ * bridge shutdown: shutting down the bridge before the devices using it.
++ */
++static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
++ u32 mask, u32 done, int usec)
++{
++ u32 result;
++
++ do {
++ result = ehci_readl(ehci, ptr);
++ if (result == ~(u32)0) /* card removed */
++ return -ENODEV;
++ result &= mask;
++ if (result == done)
++ return 0;
++ udelay (1);
++ usec--;
++ } while (usec > 0);
++ return -ETIMEDOUT;
++}
++
++/* force HC to halt state from unknown (EHCI spec section 2.3) */
++static int ehci_halt (struct ehci_hcd *ehci)
++{
++ u32 temp = ehci_readl(ehci, &ehci->regs->status);
++
++ /* disable any irqs left enabled by previous code */
++ ehci_writel(ehci, 0, &ehci->regs->intr_enable);
++
++ if ((temp & STS_HALT) != 0)
++ return 0;
++
++ temp = ehci_readl(ehci, &ehci->regs->command);
++ temp &= ~CMD_RUN;
++ ehci_writel(ehci, temp, &ehci->regs->command);
++ return handshake (ehci, &ehci->regs->status,
++ STS_HALT, STS_HALT, 16 * 125);
++}
++
++static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr,
++ u32 mask, u32 done, int usec)
++{
++ int error;
++
++ error = handshake(ehci, ptr, mask, done, usec);
++ if (error) {
++ ehci_halt(ehci);
++ ehci_to_hcd(ehci)->state = HC_STATE_HALT;
++ ehci_err(ehci, "force halt; handshake %p %08x %08x -> %d\n",
++ ptr, mask, done, error);
++ }
++
++ return error;
++}
++
++/* put TDI/ARC silicon into EHCI mode */
++static void tdi_reset (struct ehci_hcd *ehci)
++{
++ u32 __iomem *reg_ptr;
++ u32 tmp;
++
++ reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE);
++ tmp = ehci_readl(ehci, reg_ptr);
++ tmp |= USBMODE_CM_HC;
++ /* The default byte access to MMR space is LE after
++ * controller reset. Set the required endian mode
++ * for transfer buffers to match the host microprocessor
++ */
++ if (ehci_big_endian_mmio(ehci))
++ tmp |= USBMODE_BE;
++ ehci_writel(ehci, tmp, reg_ptr);
++}
++
++/* reset a non-running (STS_HALT == 1) controller */
++static int ehci_reset (struct ehci_hcd *ehci)
++{
++ int retval;
++ u32 command = ehci_readl(ehci, &ehci->regs->command);
++
++ /* If the EHCI debug controller is active, special care must be
++ * taken before and after a host controller reset */
++ if (ehci->debug && !dbgp_reset_prep())
++ ehci->debug = NULL;
++
++ command |= CMD_RESET;
++ dbg_cmd (ehci, "reset", command);
++ ehci_writel(ehci, command, &ehci->regs->command);
++ ehci_to_hcd(ehci)->state = HC_STATE_HALT;
++ ehci->next_statechange = jiffies;
++ retval = handshake (ehci, &ehci->regs->command,
++ CMD_RESET, 0, 250 * 1000);
++
++ if (ehci->has_hostpc) {
++ ehci_writel(ehci, USBMODE_EX_HC | USBMODE_EX_VBPS,
++ (u32 __iomem *)(((u8 *)ehci->regs) + USBMODE_EX));
++ ehci_writel(ehci, TXFIFO_DEFAULT,
++ (u32 __iomem *)(((u8 *)ehci->regs) + TXFILLTUNING));
++ }
++ if (retval)
++ return retval;
++
++ if (ehci_is_TDI(ehci))
++ tdi_reset (ehci);
++
++ if (ehci->debug)
++ dbgp_external_startup();
++
++ return retval;
++}
++
++/* idle the controller (from running) */
++static void ehci_quiesce (struct ehci_hcd *ehci)
++{
++ u32 temp;
++
++#ifdef DEBUG
++ if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
++ BUG ();
++#endif
++
++ /* wait for any schedule enables/disables to take effect */
++ temp = ehci_readl(ehci, &ehci->regs->command) << 10;
++ temp &= STS_ASS | STS_PSS;
++ if (handshake_on_error_set_halt(ehci, &ehci->regs->status,
++ STS_ASS | STS_PSS, temp, 16 * 125))
++ return;
++
++ /* then disable anything that's still active */
++ temp = ehci_readl(ehci, &ehci->regs->command);
++ temp &= ~(CMD_ASE | CMD_IAAD | CMD_PSE);
++ ehci_writel(ehci, temp, &ehci->regs->command);
++
++ /* hardware can take 16 microframes to turn off ... */
++ handshake_on_error_set_halt(ehci, &ehci->regs->status,
++ STS_ASS | STS_PSS, 0, 16 * 125);
++}
++
++/*-------------------------------------------------------------------------*/
++
++static void end_unlink_async(struct ehci_hcd *ehci);
++static void ehci_work(struct ehci_hcd *ehci);
++
++#include "ehci-hub.c"
++#include "ehci-mem.c"
++#include "ehci-q.c"
++#include "ehci-sched.c"
++
++/*-------------------------------------------------------------------------*/
++
++static void ehci_iaa_watchdog(unsigned long param)
++{
++ struct ehci_hcd *ehci = (struct ehci_hcd *) param;
++ unsigned long flags;
++
++ spin_lock_irqsave (&ehci->lock, flags);
++
++ /* Lost IAA irqs wedge things badly; seen first with a vt8235.
++ * So we need this watchdog, but must protect it against both
++ * (a) SMP races against real IAA firing and retriggering, and
++ * (b) clean HC shutdown, when IAA watchdog was pending.
++ */
++ if (ehci->reclaim
++ && !timer_pending(&ehci->iaa_watchdog)
++ && HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
++ u32 cmd, status;
++
++ /* If we get here, IAA is *REALLY* late. It's barely
++ * conceivable that the system is so busy that CMD_IAAD
++ * is still legitimately set, so let's be sure it's
++ * clear before we read STS_IAA. (The HC should clear
++ * CMD_IAAD when it sets STS_IAA.)
++ */
++ cmd = ehci_readl(ehci, &ehci->regs->command);
++ if (cmd & CMD_IAAD)
++ ehci_writel(ehci, cmd & ~CMD_IAAD,
++ &ehci->regs->command);
++
++ /* If IAA is set here it either legitimately triggered
++ * before we cleared IAAD above (but _way_ late, so we'll
++ * still count it as lost) ... or a silicon erratum:
++ * - VIA seems to set IAA without triggering the IRQ;
++ * - IAAD potentially cleared without setting IAA.
++ */
++ status = ehci_readl(ehci, &ehci->regs->status);
++ if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
++ COUNT (ehci->stats.lost_iaa);
++ ehci_writel(ehci, STS_IAA, &ehci->regs->status);
++ }
++
++ ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n",
++ status, cmd);
++ end_unlink_async(ehci);
++ }
++
++ spin_unlock_irqrestore(&ehci->lock, flags);
++}
++
++static void ehci_watchdog(unsigned long param)
++{
++ struct ehci_hcd *ehci = (struct ehci_hcd *) param;
++ unsigned long flags;
++
++ spin_lock_irqsave(&ehci->lock, flags);
++
++ /* stop async processing after it's idled a bit */
++ if (test_bit (TIMER_ASYNC_OFF, &ehci->actions))
++ start_unlink_async (ehci, ehci->async);
++
++ /* ehci could run by timer, without IRQs ... */
++ ehci_work (ehci);
++
++ spin_unlock_irqrestore (&ehci->lock, flags);
++}
++
++/* On some systems, leaving remote wakeup enabled prevents system shutdown.
++ * The firmware seems to think that powering off is a wakeup event!
++ * This routine turns off remote wakeup and everything else, on all ports.
++ */
++static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
++{
++ int port = HCS_N_PORTS(ehci->hcs_params);
++
++ while (port--)
++ ehci_writel(ehci, PORT_RWC_BITS,
++ &ehci->regs->port_status[port]);
++}
++
++/*
++ * Halt HC, turn off all ports, and let the BIOS use the companion controllers.
++ * Should be called with ehci->lock held.
++ */
++static void ehci_silence_controller(struct ehci_hcd *ehci)
++{
++ ehci_halt(ehci);
++ ehci_turn_off_all_ports(ehci);
++
++ /* make BIOS/etc use companion controller during reboot */
++ ehci_writel(ehci, 0, &ehci->regs->configured_flag);
++
++ /* unblock posted writes */
++ ehci_readl(ehci, &ehci->regs->configured_flag);
++}
++
++/* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
++ * This forcibly disables dma and IRQs, helping kexec and other cases
++ * where the next system software may expect clean state.
++ */
++static void ehci_shutdown(struct usb_hcd *hcd)
++{
++ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
++
++ del_timer_sync(&ehci->watchdog);
++ del_timer_sync(&ehci->iaa_watchdog);
++
++ spin_lock_irq(&ehci->lock);
++ ehci_silence_controller(ehci);
++ spin_unlock_irq(&ehci->lock);
++}
++
++static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
++{
++ unsigned port;
++
++ if (!HCS_PPC (ehci->hcs_params))
++ return;
++
++ ehci_dbg (ehci, "...power%s ports...\n", is_on ? "up" : "down");
++ for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; )
++ (void) ehci_hub_control(ehci_to_hcd(ehci),
++ is_on ? SetPortFeature : ClearPortFeature,
++ USB_PORT_FEAT_POWER,
++ port--, NULL, 0);
++ /* Flush those writes */
++ ehci_readl(ehci, &ehci->regs->command);
++ msleep(20);
++}
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * ehci_work is called from some interrupts, timers, and so on.
++ * it calls driver completion functions, after dropping ehci->lock.
++ */
++static void ehci_work (struct ehci_hcd *ehci)
++{
++ timer_action_done (ehci, TIMER_IO_WATCHDOG);
++
++ /* another CPU may drop ehci->lock during a schedule scan while
++ * it reports urb completions. this flag guards against bogus
++ * attempts at re-entrant schedule scanning.
++ */
++ if (ehci->scanning)
++ return;
++ ehci->scanning = 1;
++ scan_async (ehci);
++ if (ehci->next_uframe != -1)
++ scan_periodic (ehci);
++ ehci->scanning = 0;
++
++ /* the IO watchdog guards against hardware or driver bugs that
++ * misplace IRQs, and should let us run completely without IRQs.
++ * such lossage has been observed on both VT6202 and VT8235.
++ */
++ if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
++ (ehci->async->qh_next.ptr != NULL ||
++ ehci->periodic_sched != 0))
++ timer_action (ehci, TIMER_IO_WATCHDOG);
++}
++
++/*
++ * Called when the ehci_hcd module is removed.
++ */
++static void ehci_stop (struct usb_hcd *hcd)
++{
++ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
++
++ ehci_dbg (ehci, "stop\n");
++
++ /* no more interrupts ... */
++ del_timer_sync (&ehci->watchdog);
++ del_timer_sync(&ehci->iaa_watchdog);
++
++ spin_lock_irq(&ehci->lock);
++ if (HC_IS_RUNNING (hcd->state))
++ ehci_quiesce (ehci);
++
++ ehci_silence_controller(ehci);
++ ehci_reset (ehci);
++ spin_unlock_irq(&ehci->lock);
++
++ remove_companion_file(ehci);
++ remove_debug_files (ehci);
++
++ /* root hub is shut down separately (first, when possible) */
++ spin_lock_irq (&ehci->lock);
++ if (ehci->async)
++ ehci_work (ehci);
++ spin_unlock_irq (&ehci->lock);
++ ehci_mem_cleanup (ehci);
++
++#ifdef EHCI_STATS
++ ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
++ ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
++ ehci->stats.lost_iaa);
++ ehci_dbg (ehci, "complete %ld unlink %ld\n",
++ ehci->stats.complete, ehci->stats.unlink);
++#endif
++
++ dbg_status (ehci, "ehci_stop completed",
++ ehci_readl(ehci, &ehci->regs->status));
++}
++
++/* one-time init, only for memory state */
++static int ehci_init(struct usb_hcd *hcd)
++{
++ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
++ u32 temp;
++ int retval;
++ u32 hcc_params;
++ struct ehci_qh_hw *hw;
++
++ spin_lock_init(&ehci->lock);
++
++ /*
++ * keep io watchdog by default, those good HCDs could turn off it later
++ */
++ ehci->need_io_watchdog = 1;
++ init_timer(&ehci->watchdog);
++ ehci->watchdog.function = ehci_watchdog;
++ ehci->watchdog.data = (unsigned long) ehci;
++
++ init_timer(&ehci->iaa_watchdog);
++ ehci->iaa_watchdog.function = ehci_iaa_watchdog;
++ ehci->iaa_watchdog.data = (unsigned long) ehci;
++
++ /*
++ * hw default: 1K periodic list heads, one per frame.
++ * periodic_size can shrink by USBCMD update if hcc_params allows.
++ */
++ ehci->periodic_size = DEFAULT_I_TDPS;
++ INIT_LIST_HEAD(&ehci->cached_itd_list);
++ INIT_LIST_HEAD(&ehci->cached_sitd_list);
++ if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0)
++ return retval;
++
++ /* controllers may cache some of the periodic schedule ... */
++ hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
++ if (HCC_ISOC_CACHE(hcc_params)) // full frame cache
++ ehci->i_thresh = 2 + 8;
++ else // N microframes cached
++ ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
++
++ ehci->reclaim = NULL;
++ ehci->next_uframe = -1;
++ ehci->clock_frame = -1;
++
++ /*
++ * dedicate a qh for the async ring head, since we couldn't unlink
++ * a 'real' qh without stopping the async schedule [4.8]. use it
++ * as the 'reclamation list head' too.
++ * its dummy is used in hw_alt_next of many tds, to prevent the qh
++ * from automatically advancing to the next td after short reads.
++ */
++ ehci->async->qh_next.qh = NULL;
++ hw = ehci->async->hw;
++ hw->hw_next = QH_NEXT(ehci, ehci->async->qh_dma);
++ hw->hw_info1 = cpu_to_hc32(ehci, QH_HEAD);
++ hw->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
++ hw->hw_qtd_next = EHCI_LIST_END(ehci);
++ ehci->async->qh_state = QH_STATE_LINKED;
++ hw->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma);
++
++ /* clear interrupt enables, set irq latency */
++ if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
++ log2_irq_thresh = 0;
++ temp = 1 << (16 + log2_irq_thresh);
++ if (HCC_CANPARK(hcc_params)) {
++ /* HW default park == 3, on hardware that supports it (like
++ * NVidia and ALI silicon), maximizes throughput on the async
++ * schedule by avoiding QH fetches between transfers.
++ *
++ * With fast usb storage devices and NForce2, "park" seems to
++ * make problems: throughput reduction (!), data errors...
++ */
++ if (park) {
++ park = min(park, (unsigned) 3);
++ temp |= CMD_PARK;
++ temp |= park << 8;
++ }
++ ehci_dbg(ehci, "park %d\n", park);
++ }
++ if (HCC_PGM_FRAMELISTLEN(hcc_params)) {
++ /* periodic schedule size can be smaller than default */
++ temp &= ~(3 << 2);
++ temp |= (EHCI_TUNE_FLS << 2);
++ switch (EHCI_TUNE_FLS) {
++ case 0: ehci->periodic_size = 1024; break;
++ case 1: ehci->periodic_size = 512; break;
++ case 2: ehci->periodic_size = 256; break;
++ default: BUG();
++ }
++ }
++ ehci->command = temp;
++
++ /* Accept arbitrarily long scatter-gather lists */
++ hcd->self.sg_tablesize = ~0;
++ return 0;
++}
++
++/* start HC running; it's halted, ehci_init() has been run (once) */
++static int ehci_run (struct usb_hcd *hcd)
++{
++ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
++ int retval;
++ u32 temp;
++ u32 hcc_params;
++
++ hcd->uses_new_polling = 1;
++ hcd->poll_rh = 0;
++
++ /* EHCI spec section 4.1 */
++ if ((retval = ehci_reset(ehci)) != 0) {
++ ehci_mem_cleanup(ehci);
++ return retval;
++ }
++ ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
++ ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next);
++
++ /*
++ * hcc_params controls whether ehci->regs->segment must (!!!)
++ * be used; it constrains QH/ITD/SITD and QTD locations.
++ * pci_pool consistent memory always uses segment zero.
++ * streaming mappings for I/O buffers, like pci_map_single(),
++ * can return segments above 4GB, if the device allows.
++ *
++ * NOTE: the dma mask is visible through dma_supported(), so
++ * drivers can pass this info along ... like NETIF_F_HIGHDMA,
++ * Scsi_Host.highmem_io, and so forth. It's readonly to all
++ * host side drivers though.
++ */
++ hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
++ if (HCC_64BIT_ADDR(hcc_params)) {
++ ehci_writel(ehci, 0, &ehci->regs->segment);
++#if 0
++// this is deeply broken on almost all architectures
++ if (!dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64)))
++ ehci_info(ehci, "enabled 64bit DMA\n");
++#endif
++ }
++
++
++ // Philips, Intel, and maybe others need CMD_RUN before the
++ // root hub will detect new devices (why?); NEC doesn't
++ ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
++ ehci->command |= CMD_RUN;
++ ehci_writel(ehci, ehci->command, &ehci->regs->command);
++ dbg_cmd (ehci, "init", ehci->command);
++
++ /*
++ * Start, enabling full USB 2.0 functionality ... usb 1.1 devices
++ * are explicitly handed to companion controller(s), so no TT is
++ * involved with the root hub. (Except where one is integrated,
++ * and there's no companion controller unless maybe for USB OTG.)
++ *
++ * Turning on the CF flag will transfer ownership of all ports
++ * from the companions to the EHCI controller. If any of the
++ * companions are in the middle of a port reset at the time, it
++ * could cause trouble. Write-locking ehci_cf_port_reset_rwsem
++ * guarantees that no resets are in progress. After we set CF,
++ * a short delay lets the hardware catch up; new resets shouldn't
++ * be started before the port switching actions could complete.
++ */
++ down_write(&ehci_cf_port_reset_rwsem);
++ hcd->state = HC_STATE_RUNNING;
++ ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
++ ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
++ msleep(5);
++ up_write(&ehci_cf_port_reset_rwsem);
++ ehci->last_periodic_enable = ktime_get_real();
++
++ temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
++ ehci_info (ehci,
++ "USB %x.%x started, EHCI %x.%02x%s\n",
++ ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
++ temp >> 8, temp & 0xff,
++ ignore_oc ? ", overcurrent ignored" : "");
++
++ ehci_writel(ehci, INTR_MASK,
++ &ehci->regs->intr_enable); /* Turn On Interrupts */
++
++ /* GRR this is run-once init(), being done every time the HC starts.
++ * So long as they're part of class devices, we can't do it init()
++ * since the class device isn't created that early.
++ */
++ create_debug_files(ehci);
++ create_companion_file(ehci);
++
++ return 0;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static irqreturn_t ehci_irq (struct usb_hcd *hcd)
++{
++ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
++ u32 status, masked_status, pcd_status = 0, cmd;
++ int bh;
++
++ spin_lock (&ehci->lock);
++
++ status = ehci_readl(ehci, &ehci->regs->status);
++
++ /* e.g. cardbus physical eject */
++ if (status == ~(u32) 0) {
++ ehci_dbg (ehci, "device removed\n");
++ goto dead;
++ }
++
++ masked_status = status & INTR_MASK;
++ if (!masked_status) { /* irq sharing? */
++ spin_unlock(&ehci->lock);
++ return IRQ_NONE;
++ }
++
++ /* clear (just) interrupts */
++ ehci_writel(ehci, masked_status, &ehci->regs->status);
++ cmd = ehci_readl(ehci, &ehci->regs->command);
++ bh = 0;
++
++#ifdef VERBOSE_DEBUG
++ /* unrequested/ignored: Frame List Rollover */
++ dbg_status (ehci, "irq", status);
++#endif
++
++ /* INT, ERR, and IAA interrupt rates can be throttled */
++
++ /* normal [4.15.1.2] or error [4.15.1.1] completion */
++ if (likely ((status & (STS_INT|STS_ERR)) != 0)) {
++ if (likely ((status & STS_ERR) == 0))
++ COUNT (ehci->stats.normal);
++ else
++ COUNT (ehci->stats.error);
++ bh = 1;
++ }
++
++ /* complete the unlinking of some qh [4.15.2.3] */
++ if (status & STS_IAA) {
++ /* guard against (alleged) silicon errata */
++ if (cmd & CMD_IAAD) {
++ ehci_writel(ehci, cmd & ~CMD_IAAD,
++ &ehci->regs->command);
++ ehci_dbg(ehci, "IAA with IAAD still set?\n");
++ }
++ if (ehci->reclaim) {
++ COUNT(ehci->stats.reclaim);
++ end_unlink_async(ehci);
++ } else
++ ehci_dbg(ehci, "IAA with nothing to reclaim?\n");
++ }
++
++ /* remote wakeup [4.3.1] */
++ if (status & STS_PCD) {
++ unsigned i = HCS_N_PORTS (ehci->hcs_params);
++
++ /* kick root hub later */
++ pcd_status = status;
++
++ /* resume root hub? */
++ if (!(cmd & CMD_RUN))
++ usb_hcd_resume_root_hub(hcd);
++
++ while (i--) {
++ int pstatus = ehci_readl(ehci,
++ &ehci->regs->port_status [i]);
++
++ if (pstatus & PORT_OWNER)
++ continue;
++ if (!(test_bit(i, &ehci->suspended_ports) &&
++ ((pstatus & PORT_RESUME) ||
++ !(pstatus & PORT_SUSPEND)) &&
++ (pstatus & PORT_PE) &&
++ ehci->reset_done[i] == 0))
++ continue;
++
++ /* start 20 msec resume signaling from this port,
++ * and make khubd collect PORT_STAT_C_SUSPEND to
++ * stop that signaling. Use 5 ms extra for safety,
++ * like usb_port_resume() does.
++ */
++ ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
++ ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
++ mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
++ }
++ }
++
++ /* PCI errors [4.15.2.4] */
++ if (unlikely ((status & STS_FATAL) != 0)) {
++ ehci_err(ehci, "fatal error\n");
++ dbg_cmd(ehci, "fatal", cmd);
++ dbg_status(ehci, "fatal", status);
++ ehci_halt(ehci);
++dead:
++ ehci_reset(ehci);
++ ehci_writel(ehci, 0, &ehci->regs->configured_flag);
++ /* generic layer kills/unlinks all urbs, then
++ * uses ehci_stop to clean up the rest
++ */
++ bh = 1;
++ }
++
++ if (bh)
++ ehci_work (ehci);
++ spin_unlock (&ehci->lock);
++ if (pcd_status)
++ usb_hcd_poll_rh_status(hcd);
++ return IRQ_HANDLED;
++}
++
++/*-------------------------------------------------------------------------*/
++
++/*
++ * non-error returns are a promise to giveback() the urb later
++ * we drop ownership so next owner (or urb unlink) can get it
++ *
++ * urb + dev is in hcd.self.controller.urb_list
++ * we're queueing TDs onto software and hardware lists
++ *
++ * hcd-specific init for hcpriv hasn't been done yet
++ *
++ * NOTE: control, bulk, and interrupt share the same code to append TDs
++ * to a (possibly active) QH, and the same QH scanning code.
++ */
++static int ehci_urb_enqueue (
++ struct usb_hcd *hcd,
++ struct urb *urb,
++ gfp_t mem_flags
++) {
++ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
++ struct list_head qtd_list;
++
++ INIT_LIST_HEAD (&qtd_list);
++
++ switch (usb_pipetype (urb->pipe)) {
++ case PIPE_CONTROL:
++ /* qh_completions() code doesn't handle all the fault cases
++ * in multi-TD control transfers. Even 1KB is rare anyway.
++ */
++ if (urb->transfer_buffer_length > (16 * 1024))
++ return -EMSGSIZE;
++ /* FALLTHROUGH */
++ /* case PIPE_BULK: */
++ default:
++ if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
++ return -ENOMEM;
++ return submit_async(ehci, urb, &qtd_list, mem_flags);
++
++ case PIPE_INTERRUPT:
++ if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
++ return -ENOMEM;
++ return intr_submit(ehci, urb, &qtd_list, mem_flags);
++
++ case PIPE_ISOCHRONOUS:
++ if (urb->dev->speed == USB_SPEED_HIGH)
++ return itd_submit (ehci, urb, mem_flags);
++ else
++ return sitd_submit (ehci, urb, mem_flags);
++ }
++}
++
++static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
++{
++ /* failfast */
++ if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state) && ehci->reclaim)
++ end_unlink_async(ehci);
++
++ /* If the QH isn't linked then there's nothing we can do
++ * unless we were called during a giveback, in which case
++ * qh_completions() has to deal with it.
++ */
++ if (qh->qh_state != QH_STATE_LINKED) {
++ if (qh->qh_state == QH_STATE_COMPLETING)
++ qh->needs_rescan = 1;
++ return;
++ }
++
++ /* defer till later if busy */
++ if (ehci->reclaim) {
++ struct ehci_qh *last;
++
++ for (last = ehci->reclaim;
++ last->reclaim;
++ last = last->reclaim)
++ continue;
++ qh->qh_state = QH_STATE_UNLINK_WAIT;
++ last->reclaim = qh;
++
++ /* start IAA cycle */
++ } else
++ start_unlink_async (ehci, qh);
++}
++
++/* remove from hardware lists
++ * completions normally happen asynchronously
++ */
++
++static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
++{
++ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
++ struct ehci_qh *qh;
++ unsigned long flags;
++ int rc;
++
++ spin_lock_irqsave (&ehci->lock, flags);
++ rc = usb_hcd_check_unlink_urb(hcd, urb, status);
++ if (rc)
++ goto done;
++
++ switch (usb_pipetype (urb->pipe)) {
++ // case PIPE_CONTROL:
++ // case PIPE_BULK:
++ default:
++ qh = (struct ehci_qh *) urb->hcpriv;
++ if (!qh)
++ break;
++ switch (qh->qh_state) {
++ case QH_STATE_LINKED:
++ case QH_STATE_COMPLETING:
++ unlink_async(ehci, qh);
++ break;
++ case QH_STATE_UNLINK:
++ case QH_STATE_UNLINK_WAIT:
++ /* already started */
++ break;
++ case QH_STATE_IDLE:
++ /* QH might be waiting for a Clear-TT-Buffer */
++ qh_completions(ehci, qh);
++ break;
++ }
++ break;
++
++ case PIPE_INTERRUPT:
++ qh = (struct ehci_qh *) urb->hcpriv;
++ if (!qh)
++ break;
++ switch (qh->qh_state) {
++ case QH_STATE_LINKED:
++ case QH_STATE_COMPLETING:
++ intr_deschedule (ehci, qh);
++ break;
++ case QH_STATE_IDLE:
++ qh_completions (ehci, qh);
++ break;
++ default:
++ ehci_dbg (ehci, "bogus qh %p state %d\n",
++ qh, qh->qh_state);
++ goto done;
++ }
++ break;
++
++ case PIPE_ISOCHRONOUS:
++ // itd or sitd ...
++
++ // wait till next completion, do it then.
++ // completion irqs can wait up to 1024 msec,
++ break;
++ }
++done:
++ spin_unlock_irqrestore (&ehci->lock, flags);
++ return rc;
++}
++
++/*-------------------------------------------------------------------------*/
++
++// bulk qh holds the data toggle
++
++static void
++ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
++{
++ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
++ unsigned long flags;
++ struct ehci_qh *qh, *tmp;
++
++ /* ASSERT: any requests/urbs are being unlinked */
++ /* ASSERT: nobody can be submitting urbs for this any more */
++
++rescan:
++ spin_lock_irqsave (&ehci->lock, flags);
++ qh = ep->hcpriv;
++ if (!qh)
++ goto done;
++
++ /* endpoints can be iso streams. for now, we don't
++ * accelerate iso completions ... so spin a while.
++ */
++ if (qh->hw == NULL) {
++ ehci_vdbg (ehci, "iso delay\n");
++ goto idle_timeout;
++ }
++
++ if (!HC_IS_RUNNING (hcd->state))
++ qh->qh_state = QH_STATE_IDLE;
++ switch (qh->qh_state) {
++ case QH_STATE_LINKED:
++ case QH_STATE_COMPLETING:
++ for (tmp = ehci->async->qh_next.qh;
++ tmp && tmp != qh;
++ tmp = tmp->qh_next.qh)
++ continue;
++ /* periodic qh self-unlinks on empty, and a COMPLETING qh
++ * may already be unlinked.
++ */
++ if (tmp)
++ unlink_async(ehci, qh);
++ /* FALL THROUGH */
++ case QH_STATE_UNLINK: /* wait for hw to finish? */
++ case QH_STATE_UNLINK_WAIT:
++idle_timeout:
++ spin_unlock_irqrestore (&ehci->lock, flags);
++ schedule_timeout_uninterruptible(1);
++ goto rescan;
++ case QH_STATE_IDLE: /* fully unlinked */
++ if (qh->clearing_tt)
++ goto idle_timeout;
++ if (list_empty (&qh->qtd_list)) {
++ qh_put (qh);
++ break;
++ }
++ /* else FALL THROUGH */
++ default:
++ /* caller was supposed to have unlinked any requests;
++ * that's not our job. just leak this memory.
++ */
++ ehci_err (ehci, "qh %p (#%02x) state %d%s\n",
++ qh, ep->desc.bEndpointAddress, qh->qh_state,
++ list_empty (&qh->qtd_list) ? "" : "(has tds)");
++ break;
++ }
++ ep->hcpriv = NULL;
++done:
++ spin_unlock_irqrestore (&ehci->lock, flags);
++ return;
++}
++
++static void
++ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
++{
++ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
++ struct ehci_qh *qh;
++ int eptype = usb_endpoint_type(&ep->desc);
++ int epnum = usb_endpoint_num(&ep->desc);
++ int is_out = usb_endpoint_dir_out(&ep->desc);
++ unsigned long flags;
++
++ if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT)
++ return;
++
++ spin_lock_irqsave(&ehci->lock, flags);
++ qh = ep->hcpriv;
++
++ /* For Bulk and Interrupt endpoints we maintain the toggle state
++ * in the hardware; the toggle bits in udev aren't used at all.
++ * When an endpoint is reset by usb_clear_halt() we must reset
++ * the toggle bit in the QH.
++ */
++ if (qh) {
++ usb_settoggle(qh->dev, epnum, is_out, 0);
++ if (!list_empty(&qh->qtd_list)) {
++ WARN_ONCE(1, "clear_halt for a busy endpoint\n");
++ } else if (qh->qh_state == QH_STATE_LINKED ||
++ qh->qh_state == QH_STATE_COMPLETING) {
++
++ /* The toggle value in the QH can't be updated
++ * while the QH is active. Unlink it now;
++ * re-linking will call qh_refresh().
++ */
++ if (eptype == USB_ENDPOINT_XFER_BULK)
++ unlink_async(ehci, qh);
++ else
++ intr_deschedule(ehci, qh);
++ }
++ }
++ spin_unlock_irqrestore(&ehci->lock, flags);
++}
++
++static int ehci_get_frame (struct usb_hcd *hcd)
++{
++ struct ehci_hcd *ehci = hcd_to_ehci (hcd);
++ return (ehci_readl(ehci, &ehci->regs->frame_index) >> 3) %
++ ehci->periodic_size;
++}
++
++/*-------------------------------------------------------------------------*/
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_AUTHOR (DRIVER_AUTHOR);
++MODULE_LICENSE ("GPL");
++
++#ifdef CONFIG_PCI
++#include "ehci-pci.c"
++#define PCI_DRIVER ehci_pci_driver
++#endif
++
++#ifdef CONFIG_USB_EHCI_FSL
++#include "ehci-fsl.c"
++#define PLATFORM_DRIVER ehci_fsl_driver
++#endif
++
++#ifdef CONFIG_USB_EHCI_MXC
++#include "ehci-mxc.c"
++#define PLATFORM_DRIVER ehci_mxc_driver
++#endif
++
++#ifdef CONFIG_SOC_AU1200
++#include "ehci-au1xxx.c"
++#define PLATFORM_DRIVER ehci_hcd_au1xxx_driver
++#endif
++
++#ifdef CONFIG_ARCH_OMAP3
++#include "ehci-omap.c"
++#define PLATFORM_DRIVER ehci_hcd_omap_driver
++#endif
++
++#ifdef CONFIG_PPC_PS3
++#include "ehci-ps3.c"
++#define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver
++#endif
++
++#ifdef CONFIG_USB_EHCI_HCD_PPC_OF
++#include "ehci-ppc-of.c"
++#define OF_PLATFORM_DRIVER ehci_hcd_ppc_of_driver
++#endif
++
++#ifdef CONFIG_XPS_USB_HCD_XILINX
++#include "ehci-xilinx-of.c"
++#define XILINX_OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver
++#endif
++
++#ifdef CONFIG_PLAT_ORION
++#include "ehci-orion.c"
++#define PLATFORM_DRIVER ehci_orion_driver
++#endif
++
++#ifdef CONFIG_ARCH_IXP4XX
++#include "ehci-ixp4xx.c"
++#define PLATFORM_DRIVER ixp4xx_ehci_driver
++#endif
++
++#ifdef CONFIG_USB_W90X900_EHCI
++#include "ehci-w90x900.c"
++#define PLATFORM_DRIVER ehci_hcd_w90x900_driver
++#endif
++
++#ifdef CONFIG_ARCH_AT91
++#include "ehci-atmel.c"
++#define PLATFORM_DRIVER ehci_atmel_driver
++#endif
++
++#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
++ !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
++ !defined(XILINX_OF_PLATFORM_DRIVER)
++#error "missing bus glue for ehci-hcd"
++#endif
++
++static int __init ehci_hcd_init(void)
++{
++ int retval = 0;
++
++ if (usb_disabled())
++ return -ENODEV;
++
++ printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name);
++ set_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
++ if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) ||
++ test_bit(USB_OHCI_LOADED, &usb_hcds_loaded))
++ printk(KERN_WARNING "Warning! ehci_hcd should always be loaded"
++ " before uhci_hcd and ohci_hcd, not after\n");
++
++ pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
++ hcd_name,
++ sizeof(struct ehci_qh), sizeof(struct ehci_qtd),
++ sizeof(struct ehci_itd), sizeof(struct ehci_sitd));
++
++#ifdef DEBUG
++ ehci_debug_root = debugfs_create_dir("ehci", usb_debug_root);
++ if (!ehci_debug_root) {
++ retval = -ENOENT;
++ goto err_debug;
++ }
++#endif
++
++#ifdef PLATFORM_DRIVER
++ retval = platform_driver_register(&PLATFORM_DRIVER);
++ if (retval < 0)
++ goto clean0;
++#endif
++
++#ifdef PCI_DRIVER
++ retval = pci_register_driver(&PCI_DRIVER);
++ if (retval < 0)
++ goto clean1;
++#endif
++
++#ifdef PS3_SYSTEM_BUS_DRIVER
++ retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
++ if (retval < 0)
++ goto clean2;
++#endif
++
++#ifdef OF_PLATFORM_DRIVER
++ retval = of_register_platform_driver(&OF_PLATFORM_DRIVER);
++ if (retval < 0)
++ goto clean3;
++#endif
++
++#ifdef XILINX_OF_PLATFORM_DRIVER
++ retval = of_register_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
++ if (retval < 0)
++ goto clean4;
++#endif
++ return retval;
++
++#ifdef XILINX_OF_PLATFORM_DRIVER
++ /* of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); */
++clean4:
++#endif
++#ifdef OF_PLATFORM_DRIVER
++ of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
++clean3:
++#endif
++#ifdef PS3_SYSTEM_BUS_DRIVER
++ ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
++clean2:
++#endif
++#ifdef PCI_DRIVER
++ pci_unregister_driver(&PCI_DRIVER);
++clean1:
++#endif
++#ifdef PLATFORM_DRIVER
++ platform_driver_unregister(&PLATFORM_DRIVER);
++clean0:
++#endif
++#ifdef DEBUG
++ debugfs_remove(ehci_debug_root);
++ ehci_debug_root = NULL;
++err_debug:
++#endif
++ clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
++ return retval;
++}
++module_init(ehci_hcd_init);
++
++static void __exit ehci_hcd_cleanup(void)
++{
++#ifdef XILINX_OF_PLATFORM_DRIVER
++ of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
++#endif
++#ifdef OF_PLATFORM_DRIVER
++ of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
++#endif
++#ifdef PLATFORM_DRIVER
++ platform_driver_unregister(&PLATFORM_DRIVER);
++#endif
++#ifdef PCI_DRIVER
++ pci_unregister_driver(&PCI_DRIVER);
++#endif
++#ifdef PS3_SYSTEM_BUS_DRIVER
++ ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
++#endif
++#ifdef DEBUG
++ debugfs_remove(ehci_debug_root);
++#endif
++ clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
++}
++module_exit(ehci_hcd_cleanup);
++
+diff -rupN linux-2.6.35.11/drivers/usb/host/ehci-str8100.c linux-2.6.35.11-ts7500/drivers/usb/host/ehci-str8100.c
+--- linux-2.6.35.11/drivers/usb/host/ehci-str8100.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/drivers/usb/host/ehci-str8100.c 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,190 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#include <linux/platform_device.h>
++#include <asm/arch/hardware.h>
++
++static int str8100_ehci_setup(struct usb_hcd *hcd)
++{
++ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
++ int retval;
++
++ ehci->caps = hcd->regs;
++ ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
++ dbg_hcs_params(ehci, "reset");
++ dbg_hcc_params(ehci, "reset");
++
++ /* cache this readonly data; minimize chip reads */
++ ehci->hcs_params = readl(&ehci->caps->hcs_params);
++
++ retval = ehci_halt(ehci);
++ if (retval)
++ return retval;
++
++ return ehci_init(hcd);
++}
++#ifdef CONFIG_PM
++//mkl070226: the functionality of suspend/resume is not complete
++static int ehci_suspend (struct usb_hcd *hcd)
++{
++ printk("%s: not implemented, just pass it\n",__FUNCTION__);
++ return 0;
++}
++static int ehci_resume (struct usb_hcd *hcd)
++{
++ printk("%s: not implemented, just pass it\n",__FUNCTION__);
++ return 0;
++}
++#endif
++
++static const struct hc_driver str8100_ehci_driver = {
++ .description = hcd_name,
++ .product_desc = "str8100-ehci",
++ .hcd_priv_size = sizeof(struct ehci_hcd),
++ /*
++ * generic hardware linkage
++ */
++ .irq = ehci_irq,
++ .flags = HCD_MEMORY | HCD_USB2,
++
++ /*
++ * basic lifecycle operations
++ */
++ .reset = str8100_ehci_setup,
++ .start = ehci_run,
++#ifdef CONFIG_PM
++//mkl070226: the functionality of suspend/resume is not complete
++ .suspend = ehci_suspend,
++ .resume = ehci_resume,
++
++ .bus_suspend = ehci_suspend,
++ .bus_resume = ehci_resume,
++#endif
++ .stop = ehci_stop,
++
++ /*
++ * managing i/o requests and associated device resources
++ */
++ .urb_enqueue = ehci_urb_enqueue,
++ .urb_dequeue = ehci_urb_dequeue,
++ .endpoint_disable = ehci_endpoint_disable,
++
++ /*
++ * scheduling support
++ */
++ .get_frame_number = ehci_get_frame,
++
++ /*
++ * root hub support
++ */
++ .hub_status_data = ehci_hub_status_data,
++ .hub_control = ehci_hub_control,
++};
++
++static void str8100_usb20_config_reg_init(void)
++{
++#if 0
++ __asm__ __volatile__(
++ "mov r1, #0 \n"
++ "mcr p15, 0, r1, c7, c5, 0 \n"
++ "mov r1, #0 \n"
++ "mcr p15, 0, r1, c7, c14, 0 \n"
++ );
++#endif
++ __raw_writel(0x106, SYSVA_USB20_CONFIG_BASE_ADDR + 0x04);
++ __raw_writel((3 << 5) | 0x20000, SYSVA_USB20_OPERATION_BASE_ADDR + 0x40);
++ mdelay(100);
++}
++
++int str8100_ehci_usb_hcd_probe(const struct hc_driver *driver,
++ struct platform_device *pdev)
++{
++ struct usb_hcd *hcd;
++ char *name = "str8100-ehci";
++ int retval = 0;
++
++ str8100_usb20_config_reg_init();
++ hcd = usb_create_hcd(driver, &pdev->dev, name);
++ if (!hcd) {
++ retval = -ENOMEM;
++ return retval;
++ }
++ hcd->regs = (unsigned int *)SYSVA_USB20_OPERATION_BASE_ADDR;
++ hcd->rsrc_start = SYSPA_USB20_OPERATION_BASE_ADDR;
++ hcd->rsrc_len = 4096;
++ hcd->driver = driver;
++ /* scott.usb
++ retval = usb_add_hcd(hcd, INTC_USB20_BIT_INDEX, SA_INTERRUPT);
++ */
++ retval = usb_add_hcd(hcd, INTC_USB20_BIT_INDEX, IRQF_SHARED);
++ if (retval == 0) {
++ return retval;
++ }
++ printk("str8100 ehci init fail, %d\n", retval);
++ usb_put_hcd(hcd);
++ return retval;
++}
++
++int str8100_ehci_usb_hcd_remove(struct platform_device *pdev)
++{
++ struct usb_hcd *hcd = platform_get_drvdata(pdev);
++ usb_remove_hcd(hcd);
++ usb_put_hcd(hcd);
++ return 0;
++}
++
++static int str8100_ehci_hcd_drv_probe(struct platform_device *pdev)
++{
++ return str8100_ehci_usb_hcd_probe(&str8100_ehci_driver, pdev);
++}
++
++static struct platform_driver str8100_ehci_hcd_driver = {
++ .probe = str8100_ehci_hcd_drv_probe,
++ .remove = str8100_ehci_usb_hcd_remove,
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "str8100-ehci",
++ },
++};
++
++/*
++static int __init str8100_ehci_hcd_init(void)
++{
++ if (usb_disabled())
++ return -ENODEV;
++
++ pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
++ hcd_name,
++ sizeof(struct ehci_qh), sizeof(struct ehci_qtd),
++ sizeof(struct ehci_itd), sizeof(struct ehci_sitd));
++
++ return platform_driver_register(&str8100_ehci_hcd_driver);
++}
++module_init(str8100_ehci_hcd_init);
++
++static void __exit str8100_ehci_hcd_cleanup(void)
++{
++ platform_driver_unregister(&str8100_ehci_hcd_driver);
++}
++module_exit(str8100_ehci_hcd_cleanup);
++*/
+diff -rupN linux-2.6.35.11/files.txt linux-2.6.35.11-ts7500/files.txt
+--- linux-2.6.35.11/files.txt 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/files.txt 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,97 @@
++../linux-2.6.24-cavium/arch/arm/mm/Kconfig
++../linux-2.6.24-cavium/arch/arm/boot/compressed/Makefile
++../linux-2.6.24-cavium/arch/arm/boot/compressed/head.S
++../linux-2.6.24-cavium/arch/arm/boot/compressed/misc.c
++../linux-2.6.24-cavium/arch/arm/boot/compressed/head-str8100.S
++../linux-2.6.24-cavium/arch/arm/boot/initrd
++../linux-2.6.24-cavium/arch/arm/mach-str8100/Makefile
++../linux-2.6.24-cavium/arch/arm/mach-str8100/str8100_pm.c
++../linux-2.6.24-cavium/arch/arm/mach-str8100/str8100_hsdma.c
++../linux-2.6.24-cavium/arch/arm/mach-str8100/str8100_gpio.c
++../linux-2.6.24-cavium/arch/arm/mach-str8100/str8100_intc.c
++../linux-2.6.24-cavium/arch/arm/mach-str8100/str8100_misc.c
++../linux-2.6.24-cavium/arch/arm/mach-str8100/Kconfig
++../linux-2.6.24-cavium/arch/arm/mach-str8100/str8100_demo_i2s_wm8772_config.c
++../linux-2.6.24-cavium/arch/arm/mach-str8100/str8100_setup.c
++../linux-2.6.24-cavium/arch/arm/mach-str8100/str8100_demo_i2s_config.c
++../linux-2.6.24-cavium/arch/arm/mach-str8100/str8100_demo_pcm_legerity_config_2phone.c
++../linux-2.6.24-cavium/arch/arm/mach-str8100/str8100_timer.c
++../linux-2.6.24-cavium/arch/arm/mach-str8100/str8100_i2s.c
++../linux-2.6.24-cavium/arch/arm/mach-str8100/str8100_dma.c
++../linux-2.6.24-cavium/arch/arm/mach-str8100/str8100_demo_dma.c
++../linux-2.6.24-cavium/arch/arm/mach-str8100/str8100_pci.c
++../linux-2.6.24-cavium/arch/arm/mach-str8100/str8100_counter.c
++../linux-2.6.24-cavium/arch/arm/mach-str8100/str8100_rtc.c
++../linux-2.6.24-cavium/arch/arm/configs/str8133_defconfig
++../linux-2.6.24-cavium/arch/arm/configs/str9100_defconfig
++../linux-2.6.24-cavium/arch/arm/configs/ts7500_defconfig
++../linux-2.6.24-cavium/arch/arm/Makefile
++../linux-2.6.24-cavium/arch/arm/tools/mach-types
++../linux-2.6.24-cavium/arch/arm/Kconfig
++../linux-2.6.24-cavium/arch/arm/kernel/setup.c
++../linux-2.6.24-cavium/arch/arm/kernel/head.S
++../linux-2.6.24-cavium/drivers/i2c/busses/Makefile
++../linux-2.6.24-cavium/drivers/i2c/busses/Kconfig
++../linux-2.6.24-cavium/drivers/i2c/busses/i2c-str8100.c
++../linux-2.6.24-cavium/drivers/i2c/busses/i2c-str8100.h
++../linux-2.6.24-cavium/drivers/ide/arm/Makefile
++../linux-2.6.24-cavium/drivers/ide/arm/str8100-ide.c
++../linux-2.6.24-cavium/drivers/ide/ide-lib.c
++../linux-2.6.24-cavium/drivers/ide/ide.c
++../linux-2.6.24-cavium/drivers/ide/ide-io.c
++../linux-2.6.24-cavium/drivers/ide/Kconfig
++../linux-2.6.24-cavium/drivers/ide/setup-pci.c
++../linux-2.6.24-cavium/drivers/ide/ide-probe.c
++../linux-2.6.24-cavium/drivers/ide/ide-dma.c
++../linux-2.6.24-cavium/drivers/net/Makefile
++../linux-2.6.24-cavium/drivers/net/e1000/e1000_main.c
++../linux-2.6.24-cavium/drivers/net/Kconfig
++../linux-2.6.24-cavium/drivers/net/str8100/star_nic.c
++../linux-2.6.24-cavium/drivers/net/str8100/Kconfig
++../linux-2.6.24-cavium/drivers/mtd/maps/Makefile
++../linux-2.6.24-cavium/drivers/mtd/maps/Kconfig
++../linux-2.6.24-cavium/drivers/mtd/maps/str8100.c
++../linux-2.6.24-cavium/drivers/pci/setup-bus.c
++../linux-2.6.24-cavium/drivers/spi/Makefile
++../linux-2.6.24-cavium/drivers/spi/spi.c
++../linux-2.6.24-cavium/drivers/spi/spi_bitbang.c
++../linux-2.6.24-cavium/drivers/spi/Kconfig
++../linux-2.6.24-cavium/drivers/spi/spi_str8100.c
++../linux-2.6.24-cavium/drivers/usb/core/buffer.c
++../linux-2.6.24-cavium/drivers/usb/host/ehci-hcd.c
++../linux-2.6.24-cavium/drivers/usb/host/ehci-str8100.c
++../linux-2.6.24-cavium/drivers/usb/host/ohci-hcd.c
++../linux-2.6.24-cavium/drivers/usb/host/ohci-str8100.c
++../linux-2.6.24-cavium/drivers/usb/gadget/Makefile
++../linux-2.6.24-cavium/drivers/usb/gadget/gadget_chips.h
++../linux-2.6.24-cavium/drivers/usb/gadget/file_storage.c
++../linux-2.6.24-cavium/drivers/usb/gadget/Kconfig
++../linux-2.6.24-cavium/drivers/usb/gadget/str8100_udc.c
++../linux-2.6.24-cavium/drivers/usb/gadget/str8100_udc.h
++../linux-2.6.24-cavium/drivers/star/Makefile
++../linux-2.6.24-cavium/drivers/star/str8100/int28handler.c
++../linux-2.6.24-cavium/drivers/star/str8100/Makefile
++../linux-2.6.24-cavium/drivers/star/str8100/crash.c
++../linux-2.6.24-cavium/drivers/star/str8100/str8100_gpio_test.c
++../linux-2.6.24-cavium/drivers/star/str8100/str8100_led.c
++../linux-2.6.24-cavium/drivers/star/str8100/inthandler.c
++../linux-2.6.24-cavium/drivers/watchdog/Makefile
++../linux-2.6.24-cavium/drivers/watchdog/Kconfig
++../linux-2.6.24-cavium/drivers/watchdog/str8100_ebwdt.c
++../linux-2.6.24-cavium/drivers/watchdog/str8100_wdt.c
++../linux-2.6.24-cavium/drivers/serial/Kconfig
++../linux-2.6.24-cavium/drivers/serial/8250_early.c
++../linux-2.6.24-cavium/drivers/serial/8250.c
++../linux-2.6.24-cavium/include/linux/spi/spi.h
++../linux-2.6.24-cavium/include/linux/i2c.h
++../linux-2.6.24-cavium/include/linux/ide.h
++../linux-2.6.24-cavium/include/linux/skbuff.h
++../linux-2.6.24-cavium/include/linux/sysctl.h
++../linux-2.6.24-cavium/include/asm-arm/arch-str8100/star_spi.h
++../linux-2.6.24-cavium/include/asm-arm/arch-str8100/system.h
++../linux-2.6.24-cavium/include/asm-arm/arch-str8100/star_demo_dma.h
++../linux-2.6.24-cavium/include/asm-arm/arch-str8100/memory.h
++../linux-2.6.24-cavium/include/asm-arm/pci.h
++../linux-2.6.24-cavium/kernel/sysctl_check.c
++../linux-2.6.24-cavium/net/core/skbuff.c
++../linux-2.6.24-cavium/sound/drivers/star-i2s-wm8759.c
+diff -rupN linux-2.6.35.11/fs/char_dev.c linux-2.6.35.11-ts7500/fs/char_dev.c
+--- linux-2.6.35.11/fs/char_dev.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/fs/char_dev.c 2011-03-14 11:18:24.000000000 -0400
+@@ -568,6 +568,8 @@ static struct kobject *base_probe(dev_t
+
+ void __init chrdev_init(void)
+ {
++ //printk("chrdev_init(), calling kobj_map_init()\n");
++
+ cdev_map = kobj_map_init(base_probe, &chrdevs_lock);
+ bdi_init(&directly_mappable_cdev_bdi);
+ }
+diff -rupN linux-2.6.35.11/include/asm/arch/hardware.h linux-2.6.35.11-ts7500/include/asm/arch/hardware.h
+--- linux-2.6.35.11/include/asm/arch/hardware.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/hardware.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,18 @@
++/*
++ * linux/include/asm-arm/hardware.h
++ *
++ * Copyright (C) 1996 Russell King
++ *
++ * 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.
++ *
++ * Common hardware definitions
++ */
++
++#ifndef __ASM_HARDWARE_H
++#define __ASM_HARDWARE_H
++
++#include <asm/arch/hardware.h>
++
++#endif
+diff -rupN linux-2.6.35.11/include/asm/arch/star_demo_dma.h linux-2.6.35.11-ts7500/include/asm/arch/star_demo_dma.h
+--- linux-2.6.35.11/include/asm/arch/star_demo_dma.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_demo_dma.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,189 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef __DEMO_DMA_H__
++#define __DEMO_DMA_H__
++#include <linux/types.h> /* size_t */
++#include <linux/interrupt.h>
++#include <linux/module.h>
++
++#include <mach/star_dmac.h>
++
++/*
++ * defines for each channel
++ */
++#define DMAC_CH_DISABLE 0
++#define DMAC_CH_ENABLE 1
++
++#define DMAC_CH_DST_SEL_M0 0
++#define DMAC_CH_DST_SEL_M1 1
++
++#define DMAC_CH_SRC_SEL_M0 0
++#define DMAC_CH_SRC_SEL_M1 1
++
++#define DMAC_CH_DSTAD_CTL_INC 0
++#define DMAC_CH_DSTAD_CTL_DEC 1
++#define DMAC_CH_DSTAD_CTL_FIX 2
++
++#define DMAC_CH_SRCAD_CTL_INC 0
++#define DMAC_CH_SRCAD_CTL_DEC 1
++#define DMAC_CH_SRCAD_CTL_FIX 2
++
++#define DMAC_CH_MODE_HW_HANDSHAKE 1
++
++#define DMAC_CH_SRC_WIDTH_8_BITS 0
++#define DMAC_CH_SRC_WIDTH_16_BITS 1
++#define DMAC_CH_SRC_WIDTH_32_BITS 2
++
++#define DMAC_CH_DST_WIDTH_8_BITS 0
++#define DMAC_CH_DST_WIDTH_16_BITS 1
++#define DMAC_CH_DST_WIDTH_32_BITS 2
++
++#define DMAC_CH_ABT_TRANSFER 1
++
++#define DMAC_CH_PROT1_PRIVILEGED_MODE 1
++#define DMAC_CH_PROT1_USER_MODE 0
++
++#define DMAC_CH_PROT2_BUFFERABLE 1
++#define DMAC_CH_PROT2_NON_BUFFERABLE 0
++
++#define DMAC_CH_PROT3_CACHEABLE 1
++#define DMAC_CH_PROT3_NON_CACHEABLE 0
++
++#define DMAC_CH_PRI_LEVEL_0 0
++#define DMAC_CH_PRI_LEVEL_1 1
++#define DMAC_CH_PRI_LEVEL_2 2
++#define DMAC_CH_PRI_LEVEL_3 3
++
++#define DMAC_CH_TC_MASK_DISABLE 0
++#define DMAC_CH_TC_MASK_ENABLE 1
++
++#define DMAC_MAX_CHANNEL_NUM (8)
++
++
++#define DMAC_CH0_ID (1 << 0)
++#define DMAC_CH1_ID (1 << 1)
++#define DMAC_CH2_ID (1 << 2)
++#define DMAC_CH3_ID (1 << 3)
++#define DMAC_CH4_ID (1 << 4)
++#define DMAC_CH5_ID (1 << 5)
++#define DMAC_CH6_ID (1 << 6)
++#define DMAC_CH7_ID (1 << 7)
++#define DMAC_CH_ID(idx) (1 << idx)
++
++#define DMAC_LITTLE_ENDIAN (0)
++#define DMAC_BIG_ENDIAN (1)
++
++/*
++ * DMAC LLP Descriptor
++ */
++typedef struct _DMAC_LLP_CONTROL_ DMAC_LLP_CONTROL_T;
++
++struct _DMAC_LLP_CONTROL_
++{
++//#if (ENDIAN_MODE == LITTLE_ENDIAN)
++#if 1
++ unsigned int tot_size : 12;//b11-0
++ unsigned int reserved_1 : 4; //b15-12
++ unsigned int dst_sel : 1; //b16
++ unsigned int src_sel : 1; //b17
++ unsigned int dstad_ctl : 2; //b19-18
++ unsigned int srcad_ctl : 2; //b21-20
++ unsigned int dst_width : 3; //b24-22
++ unsigned int src_width : 3; //b27-25
++ unsigned int tc_status_mask : 1; //b28
++ unsigned int reserved_0 : 3; //b31-29
++
++#else
++
++
++ unsigned int reserved_0 : 3; //b31-29
++ unsigned int tc_status_mask : 1; //b28
++ unsigned int src_width : 3; //b27-25
++ unsigned int dst_width : 3; //b24-22
++ unsigned int srcad_ctl : 2; //b21-20
++ unsigned int dstad_ctl : 2; //b19-18
++ unsigned int src_sel : 1; //b17
++ unsigned int dst_sel : 1; //b16
++ unsigned int reserved_1 : 4; //b15-12
++ unsigned int tot_size : 12;//b11-0
++
++
++#endif
++};
++
++
++/*
++ * DMAC LLP Descriptor object
++ */
++typedef struct _DMAC_LLP_ DMAC_LLP_T;
++struct _DMAC_LLP_
++{
++ unsigned int SrcAddr;
++
++ unsigned int DstAddr;
++
++ DMAC_LLP_T *LLP;
++
++ DMAC_LLP_CONTROL_T Ctrl_TotSize;
++};
++
++typedef struct _DMAC_HARDWARE_HANDSHAKE_OBJ_ DMAC_HARDWARE_HANDSHAKE_OBJ_T;
++struct _DMAC_HARDWARE_HANDSHAKE_OBJ_
++{
++ unsigned int src_addr; //Src address
++ unsigned int dst_addr; //Dst address
++ unsigned int src_master; //0:AHB0, 1:AHB1
++ unsigned int dst_master; //0:AHB0, 1:AHB1
++ unsigned int dstad_ctl; //0:Incr, 1:Decr, 2:Fix
++ unsigned int srcad_ctl; //0:Incr, 1:Decr, 2:Fix
++ unsigned int src_width; //0:8bits, 1:16bits, 2:32bits
++ unsigned int dst_width; //0:8bits, 1:16bits, 2:32bits
++ unsigned int transfer_bytes; //Byte Count to be transferred
++ unsigned int channel_id; //0~7 for Channel0-7 selection
++ unsigned int channel_num; //0~7
++ unsigned int target_select; //target ID
++ unsigned int src_burst_size; //number of transfer
++ unsigned int llp_addr; //LLP address
++
++ void * private_data;
++ DMAC_LLP_T* llp_head;
++};
++
++
++extern void Hal_Dmac_Configure_DMA_Handshake(DMAC_HARDWARE_HANDSHAKE_OBJ_T *dmac_obj);
++extern irqreturn_t str8100_dma_err_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs);
++//extern int str8100_i2s_init(int sampling_rate);
++extern int str8100_i2s_init(int sampling_rate,u32 i2s_sdata_width, u32 i2s_mode,
++ u32 i2s_tranfer_timing_ctrl, u32 i2s_sclk_mode);
++extern u32 Hal_Dmac_Get_Channel_Transfer_Unit_Number(u32 byte_size, u32 src_width);
++
++extern u32 I2s_Gpio_SSP_Initialise(void);
++extern void I2s_Gpio_SSP_Write(u16);
++extern void I2s_Gpio_SSP_Switch_To_Record_Data(void);
++extern void I2s_Gpio_SSP_Switcg_To_Playback_Data(void);
++
++
++#endif //#ifndef __DEMO_DMA_H__
++
++
+diff -rupN linux-2.6.35.11/include/asm/arch/star_dmac.h linux-2.6.35.11-ts7500/include/asm/arch/star_dmac.h
+--- linux-2.6.35.11/include/asm/arch/star_dmac.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_dmac.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,409 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_DMAC_H_
++#define _STAR_DMAC_H_
++
++
++#include "star_sys_memory_map.h"
++
++
++#if defined(__UBOOT__)
++#define DMAC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_GDMAC_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define DMAC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_GDMAC_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define DMAC_INT_STATUS_REG DMAC_MEM_MAP_VALUE(0x000)
++
++#define DMAC_INT_TC_STATUS_REG DMAC_MEM_MAP_VALUE(0x004)
++#define DMAC_INT_TC_STATUS_CLR_REG DMAC_MEM_MAP_VALUE(0x008)
++
++#define DMAC_INT_ERR_STATUS_REG DMAC_MEM_MAP_VALUE(0x00C)
++#define DMAC_INT_ERR_STATUS_CLR_REG DMAC_MEM_MAP_VALUE(0x010)
++
++#define DMAC_TC_STATUS_REG DMAC_MEM_MAP_VALUE(0x014)
++#define DMAC_ERR_STATUS_REG DMAC_MEM_MAP_VALUE(0x018)
++
++#define DMAC_CH_ENABLE_STATUS_REG DMAC_MEM_MAP_VALUE(0x01C)
++#define DMAC_CH_BUSY_STATUS_REG DMAC_MEM_MAP_VALUE(0x020)
++
++#define DMAC_CSR_REG DMAC_MEM_MAP_VALUE(0x024)
++#define DMAC_SYNC_REG DMAC_MEM_MAP_VALUE(0x028)
++
++#define DMAC_CH0_CSR_REG DMAC_MEM_MAP_VALUE(0x100)
++#define DMAC_CH0_CFG_REG DMAC_MEM_MAP_VALUE(0x104)
++#define DMAC_CH0_SRC_ADDR_REG DMAC_MEM_MAP_VALUE(0x108)
++#define DMAC_CH0_DST_ADDR_REG DMAC_MEM_MAP_VALUE(0x10C)
++#define DMAC_CH0_LLP_REG DMAC_MEM_MAP_VALUE(0x110)
++#define DMAC_CH0_SIZE_REG DMAC_MEM_MAP_VALUE(0x114)
++
++#define DMAC_CH1_CSR_REG DMAC_MEM_MAP_VALUE(0x120)
++#define DMAC_CH1_CFG_REG DMAC_MEM_MAP_VALUE(0x124)
++#define DMAC_CH1_SRC_ADDR_REG DMAC_MEM_MAP_VALUE(0x128)
++#define DMAC_CH1_DST_ADDR_REG DMAC_MEM_MAP_VALUE(0x12C)
++#define DMAC_CH1_LLP_REG DMAC_MEM_MAP_VALUE(0x130)
++#define DMAC_CH1_SIZE_REG DMAC_MEM_MAP_VALUE(0x134)
++
++#define DMAC_CH2_CSR_REG DMAC_MEM_MAP_VALUE(0x140)
++#define DMAC_CH2_CFG_REG DMAC_MEM_MAP_VALUE(0x144)
++#define DMAC_CH2_SRC_ADDR_REG DMAC_MEM_MAP_VALUE(0x148)
++#define DMAC_CH2_DST_ADDR_REG DMAC_MEM_MAP_VALUE(0x14C)
++#define DMAC_CH2_LLP_REG DMAC_MEM_MAP_VALUE(0x150)
++#define DMAC_CH2_SIZE_REG DMAC_MEM_MAP_VALUE(0x154)
++
++#define DMAC_CH3_CSR_REG DMAC_MEM_MAP_VALUE(0x160)
++#define DMAC_CH3_CFG_REG DMAC_MEM_MAP_VALUE(0x164)
++#define DMAC_CH3_SRC_ADDR_REG DMAC_MEM_MAP_VALUE(0x168)
++#define DMAC_CH3_DST_ADDR_REG DMAC_MEM_MAP_VALUE(0x16C)
++#define DMAC_CH3_LLP_REG DMAC_MEM_MAP_VALUE(0x170)
++#define DMAC_CH3_SIZE_REG DMAC_MEM_MAP_VALUE(0x174)
++
++#define DMAC_CH4_CSR_REG DMAC_MEM_MAP_VALUE(0x180)
++#define DMAC_CH4_CFG_REG DMAC_MEM_MAP_VALUE(0x184)
++#define DMAC_CH4_SRC_ADDR_REG DMAC_MEM_MAP_VALUE(0x188)
++#define DMAC_CH4_DST_ADDR_REG DMAC_MEM_MAP_VALUE(0x18C)
++#define DMAC_CH4_LLP_REG DMAC_MEM_MAP_VALUE(0x190)
++#define DMAC_CH4_SIZE_REG DMAC_MEM_MAP_VALUE(0x194)
++
++#define DMAC_CH5_CSR_REG DMAC_MEM_MAP_VALUE(0x1A0)
++#define DMAC_CH5_CFG_REG DMAC_MEM_MAP_VALUE(0x1A4)
++#define DMAC_CH5_SRC_ADDR_REG DMAC_MEM_MAP_VALUE(0x1A8)
++#define DMAC_CH5_DST_ADDR_REG DMAC_MEM_MAP_VALUE(0x1AC)
++#define DMAC_CH5_LLP_REG DMAC_MEM_MAP_VALUE(0x1B0)
++#define DMAC_CH5_SIZE_REG DMAC_MEM_MAP_VALUE(0x1B4)
++
++#define DMAC_CH6_CSR_REG DMAC_MEM_MAP_VALUE(0x1C0)
++#define DMAC_CH6_CFG_REG DMAC_MEM_MAP_VALUE(0x1C4)
++#define DMAC_CH6_SRC_ADDR_REG DMAC_MEM_MAP_VALUE(0x1C8)
++#define DMAC_CH6_DST_ADDR_REG DMAC_MEM_MAP_VALUE(0x1CC)
++#define DMAC_CH6_LLP_REG DMAC_MEM_MAP_VALUE(0x1D0)
++#define DMAC_CH6_SIZE_REG DMAC_MEM_MAP_VALUE(0x1D4)
++
++#define DMAC_CH7_CSR_REG DMAC_MEM_MAP_VALUE(0x1E0)
++#define DMAC_CH7_CFG_REG DMAC_MEM_MAP_VALUE(0x1E4)
++#define DMAC_CH7_SRC_ADDR_REG DMAC_MEM_MAP_VALUE(0x1E8)
++#define DMAC_CH7_DST_ADDR_REG DMAC_MEM_MAP_VALUE(0x1EC)
++#define DMAC_CH7_LLP_REG DMAC_MEM_MAP_VALUE(0x1F0)
++#define DMAC_CH7_SIZE_REG DMAC_MEM_MAP_VALUE(0x1F4)
++
++
++#define DMAC_CH0_INT_BIT_INDEX 0
++#define DMAC_CH1_INT_BIT_INDEX 1
++#define DMAC_CH2_INT_BIT_INDEX 2
++#define DMAC_CH3_INT_BIT_INDEX 3
++#define DMAC_CH4_INT_BIT_INDEX 4
++#define DMAC_CH5_INT_BIT_INDEX 5
++#define DMAC_CH6_INT_BIT_INDEX 6
++#define DMAC_CH7_INT_BIT_INDEX 7
++
++#define DMAC_CH0_INT_TC_BIT_INDEX 0
++#define DMAC_CH1_INT_TC_BIT_INDEX 1
++#define DMAC_CH2_INT_TC_BIT_INDEX 2
++#define DMAC_CH3_INT_TC_BIT_INDEX 3
++#define DMAC_CH4_INT_TC_BIT_INDEX 4
++#define DMAC_CH5_INT_TC_BIT_INDEX 5
++#define DMAC_CH6_INT_TC_BIT_INDEX 6
++#define DMAC_CH7_INT_TC_BIT_INDEX 7
++
++#define DMAC_CH0_INT_TC_CLR_BIT_INDEX 0
++#define DMAC_CH1_INT_TC_CLR_BIT_INDEX 1
++#define DMAC_CH2_INT_TC_CLR_BIT_INDEX 2
++#define DMAC_CH3_INT_TC_CLR_BIT_INDEX 3
++#define DMAC_CH4_INT_TC_CLR_BIT_INDEX 4
++#define DMAC_CH5_INT_TC_CLR_BIT_INDEX 5
++#define DMAC_CH6_INT_TC_CLR_BIT_INDEX 6
++#define DMAC_CH7_INT_TC_CLR_BIT_INDEX 7
++
++#define DMAC_CH0_INT_ERR_BIT_INDEX 0
++#define DMAC_CH1_INT_ERR_BIT_INDEX 1
++#define DMAC_CH2_INT_ERR_BIT_INDEX 2
++#define DMAC_CH3_INT_ERR_BIT_INDEX 3
++#define DMAC_CH4_INT_ERR_BIT_INDEX 4
++#define DMAC_CH5_INT_ERR_BIT_INDEX 5
++#define DMAC_CH6_INT_ERR_BIT_INDEX 6
++#define DMAC_CH7_INT_ERR_BIT_INDEX 7
++
++#define DMAC_CH0_INT_ERR_CLR_BIT_INDEX 0
++#define DMAC_CH1_INT_ERR_CLR_BIT_INDEX 1
++#define DMAC_CH2_INT_ERR_CLR_BIT_INDEX 2
++#define DMAC_CH3_INT_ERR_CLR_BIT_INDEX 3
++#define DMAC_CH4_INT_ERR_CLR_BIT_INDEX 4
++#define DMAC_CH5_INT_ERR_CLR_BIT_INDEX 5
++#define DMAC_CH6_INT_ERR_CLR_BIT_INDEX 6
++#define DMAC_CH7_INT_ERR_CLR_BIT_INDEX 7
++
++#define DMAC_CH0_TC_STATUS_BIT_INDEX 0
++#define DMAC_CH1_TC_STATUS_BIT_INDEX 1
++#define DMAC_CH2_TC_STATUS_BIT_INDEX 2
++#define DMAC_CH3_TC_STATUS_BIT_INDEX 3
++#define DMAC_CH4_TC_STATUS_BIT_INDEX 4
++#define DMAC_CH5_TC_STATUS_BIT_INDEX 5
++#define DMAC_CH6_TC_STATUS_BIT_INDEX 6
++#define DMAC_CH7_TC_STATUS_BIT_INDEX 7
++
++#define DMAC_CH0_ERR_STATUS_BIT_INDEX 0
++#define DMAC_CH1_ERR_STATUS_BIT_INDEX 1
++#define DMAC_CH2_ERR_STATUS_BIT_INDEX 2
++#define DMAC_CH3_ERR_STATUS_BIT_INDEX 3
++#define DMAC_CH4_ERR_STATUS_BIT_INDEX 4
++#define DMAC_CH5_ERR_STATUS_BIT_INDEX 5
++#define DMAC_CH6_ERR_STATUS_BIT_INDEX 6
++#define DMAC_CH7_ERR_STATUS_BIT_INDEX 7
++
++#define DMAC_CH0_ENABLE_STATUS_BIT_INDEX 0
++#define DMAC_CH1_ENABLE_STATUS_BIT_INDEX 1
++#define DMAC_CH2_ENABLE_STATUS_BIT_INDEX 2
++#define DMAC_CH3_ENABLE_STATUS_BIT_INDEX 3
++#define DMAC_CH4_ENABLE_STATUS_BIT_INDEX 4
++#define DMAC_CH5_ENABLE_STATUS_BIT_INDEX 5
++#define DMAC_CH6_ENABLE_STATUS_BIT_INDEX 6
++#define DMAC_CH7_ENABLE_STATUS_BIT_INDEX 7
++
++#define DMAC_CH0_BUSY_STATUS_BIT_INDEX 0
++#define DMAC_CH1_BUSY_STATUS_BIT_INDEX 1
++#define DMAC_CH2_BUSY_STATUS_BIT_INDEX 2
++#define DMAC_CH3_BUSY_STATUS_BIT_INDEX 3
++#define DMAC_CH4_BUSY_STATUS_BIT_INDEX 4
++#define DMAC_CH5_BUSY_STATUS_BIT_INDEX 5
++#define DMAC_CH6_BUSY_STATUS_BIT_INDEX 6
++#define DMAC_CH7_BUSY_STATUS_BIT_INDEX 7
++
++#define DMAC_ENABLE_BIT_INDEX 0
++#define DMAC_MASTER0_ENDIAN_BIT_INDEX 1
++#define DMAC_MASTER1_ENDIAN_BIT_INDEX 2
++
++#define DMAC_CH0_SYNC_ENABLE_BIT_INDEX 0
++#define DMAC_CH1_SYNC_ENABLE_BIT_INDEX 1
++#define DMAC_CH2_SYNC_ENABLE_BIT_INDEX 2
++#define DMAC_CH3_SYNC_ENABLE_BIT_INDEX 3
++#define DMAC_CH4_SYNC_ENABLE_BIT_INDEX 4
++#define DMAC_CH5_SYNC_ENABLE_BIT_INDEX 5
++#define DMAC_CH6_SYNC_ENABLE_BIT_INDEX 6
++#define DMAC_CH7_SYNC_ENABLE_BIT_INDEX 7
++
++#define DMAC_CH_INT_TC_MASK_BIT_INDEX 0
++#define DMAC_CH_INT_ERR_MASK_BIT_INDEX 1
++#define DMAC_CH_INT_ABT_MASK_BIT_INDEX 2
++#define DMAC_CH_BUSY_BIT_INDEX 8
++
++#define DMAC_CH_ENABLE_BIT_INDEX 0
++#define DMAC_CH_DST_SEL_BIT_INDEX 1
++#define DMAC_CH_SRC_SEL_BIT_INDEX 2
++#define DMAC_CH_DST_ADDR_CTL_BIT_INDEX 3
++#define DMAC_CH_SRC_ADDR_CTL_BIT_INDEX 5
++#define DMAC_CH_MODE_BIT_INDEX 7
++#define DMAC_CH_DST_WIDTH_BIT_INDEX 8
++#define DMAC_CH_SRC_WIDTH_BIT_INDEX 11
++#define DMAC_CH_ABT_BIT_INDEX 15
++#define DMAC_CH_SRC_BURST_SIZE_BIT_INDEX 16
++#define DMAC_CH_PROTECT_MODE_BIT_INDEX 19
++#define DMAC_CH_PROTECT_BUFFERABLE_BIT_INDEX 20
++#define DMAC_CH_PROTECT_CACHEABLE_BIT_INDEX 21
++#define DMAC_CH_PRIORITY_BIT_INDEX 22
++#define DMAC_CH_HHST_SEL_BIT_INDEX 25
++
++#define DMAC_CH_DST_ADDR_CTL_MASK 0x3
++#define DMAC_CH_DST_ADDR_CTL_INC 0x0
++#define DMAC_CH_DST_ADDR_CTL_DEC 0x1
++#define DMAC_CH_DST_ADDR_CTL_FIXED 0x2
++
++#define DMAC_CH_SRC_ADDR_CTL_MASK 0x3
++#define DMAC_CH_SRC_ADDR_CTL_INC 0x0
++#define DMAC_CH_SRC_ADDR_CTL_DEC 0x1
++#define DMAC_CH_SRC_ADDR_CTL_FIXED 0x2
++
++#define DMAC_CH_MODE_NORMAL 0x0
++#define DMAC_CH_MODE_HANDSHAKE 0x1
++
++#define DMAC_CH_DST_WIDTH_MASK 0x3
++#define DMAC_CH_DST_WIDTH_8BIT 0x0
++#define DMAC_CH_DST_WIDTH_16BIT 0x1
++#define DMAC_CH_DST_WIDTH_32BIT 0x2
++
++#define DMAC_CH_SRC_WIDTH_MASK 0x3
++#define DMAC_CH_SRC_WIDTH_8BIT 0x0
++#define DMAC_CH_SRC_WIDTH_16BIT 0x1
++#define DMAC_CH_SRC_WIDTH_32BIT 0x2
++
++#define DMAC_CH_SRC_BURST_SIZE_MASK 0x8
++#define DMAC_CH_SRC_BURST_SIZE_1 0x0
++#define DMAC_CH_SRC_BURST_SIZE_4 0x1
++#define DMAC_CH_SRC_BURST_SIZE_8 0x2
++#define DMAC_CH_SRC_BURST_SIZE_16 0x3
++#define DMAC_CH_SRC_BURST_SIZE_32 0x4
++#define DMAC_CH_SRC_BURST_SIZE_64 0x5
++#define DMAC_CH_SRC_BURST_SIZE_128 0x6
++#define DMAC_CH_SRC_BURST_SIZE_256 0x7
++
++#define DMAC_CH_PRIORITY_MASK 0x4
++#define DMAC_CH_PRIORITY_0 0x0 /* lowest priority */
++#define DMAC_CH_PRIORITY_1 0x1
++#define DMAC_CH_PRIORITY_2 0x2
++#define DMAC_CH_PRIORITY_3 0x3 /* highest priority */
++
++
++#define DMAC_CH_CSR_REG(idx) DMAC_MEM_MAP_VALUE(0x100+0x20*(idx))
++#define DMAC_CH_CFG_REG(idx) DMAC_MEM_MAP_VALUE(0x104+0x20*(idx))
++#define DMAC_CH_SRC_ADDR_REG(idx) DMAC_MEM_MAP_VALUE(0x108+0x20*(idx))
++#define DMAC_CH_DST_ADDR_REG(idx) DMAC_MEM_MAP_VALUE(0x10C+0x20*(idx))
++#define DMAC_CH_LLP_REG(idx) DMAC_MEM_MAP_VALUE(0x110+0x20*(idx))
++#define DMAC_CH_SIZE_REG(idx) DMAC_MEM_MAP_VALUE(0x114+0x20*(idx))
++
++
++#define HAL_DMAC_ENABLE_CHANNEL(idx) ((DMAC_CH_CSR_REG(idx)) |= (0x1))
++
++#define HAL_DMAC_DISABLE_CHANNEL(idx) ((DMAC_CH_CSR_REG(idx)) &= ~(0x1))
++
++#define HAL_GET_DMAC_CHANNEL_LLP_COUNTER(ch) ((DMAC_CH_CFG_REG(ch) >> 16) & 0xF)
++
++
++/*DMAC HW Hand-shake target ID*/
++#define DMAC_HW_HAND_SHAKE_PCM_TX0_ID 0x0
++#define DMAC_HW_HAND_SHAKE_PCM_RX0_ID 0x1
++
++#define DMAC_HW_HAND_SHAKE_SPI_TX_ID 0x2
++#define DMAC_HW_HAND_SHAKE_SPI_RX_ID 0x3
++
++#define DMAC_HW_HAND_SHAKE_I2S_TX_LEFT_ID 0x4
++#define DMAC_HW_HAND_SHAKE_I2S_TX_RIGHT_ID 0x5
++
++#define DMAC_HW_HAND_SHAKE_UART0_TX_ID 0x6
++#define DMAC_HW_HAND_SHAKE_UART0_RX_ID 0x7
++
++#define DMAC_HW_HAND_SHAKE_UART1_TX_ID 0x8
++#define DMAC_HW_HAND_SHAKE_UART1_RX_ID 0x9
++
++#define DMAC_HW_HAND_SHAKE_USBDEV_ID 0xA
++
++#define DMAC_HW_HAND_SHAKE_I2S_RX_LEFT_ID 0xB
++#define DMAC_HW_HAND_SHAKE_I2S_RX_RIGHT_ID 0xC
++
++#define DMAC_HW_HAND_SHAKE_PCM_TX1_ID 0xD
++#define DMAC_HW_HAND_SHAKE_PCM_RX1_ID 0xE
++
++
++#define MAX_DMA_VEC 32
++
++#define DMAC_DST_SEL_MASTER0 0
++#define DMAC_DST_SEL_MASTER1 1
++#define DMAC_SRC_SEL_MASTER0 0
++#define DMAC_SRC_SEL_MASTER1 1
++
++#define DMAC_RESPONSE_OK 0
++#define DMAC_RESPONSE_ERR -1
++
++struct dma_xfer;
++typedef struct dma_xfer dma_xfer_t;
++typedef void (*dma_end_io_t)(dma_xfer_t *dma_xfer, int err);
++typedef struct
++{
++ u32 src_addr; // virtual addr
++ u32 dst_addr; // virtual addr
++ u32 size; // bytes
++ u8 dst_sel;
++ u8 src_sel;
++ u8 dst_addr_ctl;
++ u8 src_addr_ctl;
++ u8 dst_width;
++ u8 src_width;
++} dma_vec_t;
++
++struct dma_xfer
++{
++ u8 nr_vec;
++ dma_vec_t vec[MAX_DMA_VEC];
++ dma_end_io_t dma_end_io;
++ void *private;
++};
++
++/*
++ * DMAC LLP Descriptor
++ */
++typedef struct
++{
++ u32 src_addr; // physical addr
++ u32 dst_addr; // physical addr
++ u32 llp;
++ u32 tot_size : 12;
++ u32 reserved0 : 4;
++ u32 dst_sel : 1;
++ u32 src_sel : 1;
++ u32 dst_addr_ctl : 2;
++ u32 src_addr_ctl : 2;
++ u32 dst_width : 3;
++ u32 src_width : 3;
++ u32 tc_mask : 1;
++ u32 reserved1 : 3;
++} __attribute__((packed)) dma_llp_descr_t;
++
++#define HAL_DMAC_ENABLE() \
++ ((DMAC_CSR_REG) |= (1<<DMAC_ENABLE_BIT_INDEX))
++
++
++#define HAL_DMAC_DISABLE() \
++ ((DMAC_CSR_REG) &= ~(1<<DMAC_ENABLE_BIT_INDEX))
++
++
++#define HAL_DMAC_SET_MASTER0_BIG_ENDIAN() \
++ ((DMAC_CSR_REG) |= (1<<DMAC_MASTER0_ENDIAN_BIT_INDEX))
++
++
++#define HAL_DMAC_SET_MASTER0_LITTLE_ENDIAN() \
++ ((DMAC_CSR_REG) &= ~(1<<DMAC_MASTER0_ENDIAN_BIT_INDEX))
++
++
++#define HAL_DMAC_SET_MASTER1_BIG_ENDIAN() \
++ ((DMAC_CSR_REG) |= (1<<DMAC_MASTER1_ENDIAN_BIT_INDEX))
++
++
++#define HAL_DMAC_SET_MASTER1_LITTLE_ENDIAN() \
++ ((DMAC_CSR_REG) &= ~(1<<DMAC_MASTER1_ENDIAN_BIT_INDEX))
++
++#define HAL_DMAC_READ_ERROR_ABORT_INTERRUPT_STATUS(err_abt_status) \
++ ((err_abt_status) = (DMAC_INT_ERR_STATUS_REG))
++
++
++#define HAL_DMAC_CLEAR_ERROR_ABORT_INTERRUPT_STATUS(err_abt_status) \
++ ((DMAC_INT_ERR_STATUS_CLR_REG) = (err_abt_status))
++
++
++#define HAL_DMAC_READ_TERMINAL_COUNT_INTERRUPT_STATUS(tc_status) \
++ ((tc_status) = (DMAC_INT_TC_STATUS_REG) & 0xFF)
++
++
++#define HAL_DMAC_CLEAR_TERMINAL_COUNT_INTERRUPT_STATUS(tc_status) \
++ ((DMAC_INT_TC_STATUS_CLR_REG) = (tc_status) & 0xFF)
++
++
++
++
++
++
++#endif // end of #ifndef _STAR_DMAC_H_
+diff -rupN linux-2.6.35.11/include/asm/arch/star_gpio.h linux-2.6.35.11-ts7500/include/asm/arch/star_gpio.h
+--- linux-2.6.35.11/include/asm/arch/star_gpio.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_gpio.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,327 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_GPIO_H_
++#define _STAR_GPIO_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define GPIOA_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_GPIOA_BASE_ADDR + reg_offset)))
++#define GPIOB_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_GPIOB_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define GPIOA_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_GPIOA_BASE_ADDR + reg_offset)))
++#define GPIOB_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_GPIOB_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * For GPIO Set A
++ */
++#define GPIOA_DATA_OUTPUT_REG GPIOA_MEM_MAP_VALUE(0x00)
++#define GPIOA_DATA_INPUT_REG GPIOA_MEM_MAP_VALUE(0x04)
++#define GPIOA_DIRECTION_REG GPIOA_MEM_MAP_VALUE(0x08)
++
++#define GPIOA_DATA_BIT_SET_REG GPIOA_MEM_MAP_VALUE(0x10)
++#define GPIOA_DATA_BIT_CLEAR_REG GPIOA_MEM_MAP_VALUE(0x14)
++
++#define GPIOA_INTERRUPT_ENABLE_REG GPIOA_MEM_MAP_VALUE(0x20)
++#define GPIOA_INTERRUPT_RAW_STATUS_REG GPIOA_MEM_MAP_VALUE(0x24)
++#define GPIOA_INTERRUPT_MASKED_STATUS_REG GPIOA_MEM_MAP_VALUE(0x28)
++#define GPIOA_INTERRUPT_MASK_REG GPIOA_MEM_MAP_VALUE(0x2C)
++#define GPIOA_INTERRUPT_CLEAR_REG GPIOA_MEM_MAP_VALUE(0x30)
++#define GPIOA_INTERRUPT_TRIGGER_METHOD_REG GPIOA_MEM_MAP_VALUE(0x34)
++#define GPIOA_INTERRUPT_TRIGGER_BOTH_EDGES_REG GPIOA_MEM_MAP_VALUE(0x38)
++#define GPIOA_INTERRUPT_TRIGGER_TYPE_REG GPIOA_MEM_MAP_VALUE(0x3C)
++
++#define GPIOA_BOUNCE_ENABLE_REG GPIOA_MEM_MAP_VALUE(0x40)
++#define GPIOA_BOUNCE_CLOCK_PRESCALE_REG GPIOA_MEM_MAP_VALUE(0x44)
++
++
++/*
++ * For GPIO Set B
++ */
++#define GPIOB_DATA_OUTPUT_REG GPIOB_MEM_MAP_VALUE(0x00)
++#define GPIOB_DATA_INPUT_REG GPIOB_MEM_MAP_VALUE(0x04)
++#define GPIOB_DIRECTION_REG GPIOB_MEM_MAP_VALUE(0x08)
++
++#define GPIOB_DATA_BIT_SET_REG GPIOB_MEM_MAP_VALUE(0x10)
++#define GPIOB_DATA_BIT_CLEAR_REG GPIOB_MEM_MAP_VALUE(0x14)
++
++#define GPIOB_INTERRUPT_ENABLE_REG GPIOB_MEM_MAP_VALUE(0x20)
++#define GPIOB_INTERRUPT_RAW_STATUS_REG GPIOB_MEM_MAP_VALUE(0x24)
++#define GPIOB_INTERRUPT_MASKED_STATUS_REG GPIOB_MEM_MAP_VALUE(0x28)
++#define GPIOB_INTERRUPT_MASK_REG GPIOB_MEM_MAP_VALUE(0x2C)
++#define GPIOB_INTERRUPT_CLEAR_REG GPIOB_MEM_MAP_VALUE(0x30)
++#define GPIOB_INTERRUPT_TRIGGER_METHOD_REG GPIOB_MEM_MAP_VALUE(0x34)
++#define GPIOB_INTERRUPT_TRIGGER_BOTH_EDGES_REG GPIOB_MEM_MAP_VALUE(0x38)
++#define GPIOB_INTERRUPT_TRIGGER_TYPE_REG GPIOB_MEM_MAP_VALUE(0x3C)
++
++#define GPIOB_BOUNCE_ENABLE_REG GPIOB_MEM_MAP_VALUE(0x40)
++#define GPIOB_BOUNCE_CLOCK_PRESCALE_REG GPIOB_MEM_MAP_VALUE(0x44)
++
++
++/*
++ * define constant macros
++ */
++
++#define MAX_GPIO_PINS (32)
++
++#define GPIO_0_MASK (1 << 0)
++#define GPIO_1_MASK (1 << 1)
++#define GPIO_2_MASK (1 << 2)
++#define GPIO_3_MASK (1 << 3)
++#define GPIO_4_MASK (1 << 4)
++#define GPIO_5_MASK (1 << 5)
++#define GPIO_6_MASK (1 << 6)
++#define GPIO_7_MASK (1 << 7)
++#define GPIO_8_MASK (1 << 8)
++#define GPIO_9_MASK (1 << 9)
++#define GPIO_10_MASK (1 << 10)
++#define GPIO_11_MASK (1 << 11)
++#define GPIO_12_MASK (1 << 12)
++#define GPIO_13_MASK (1 << 13)
++#define GPIO_14_MASK (1 << 14)
++#define GPIO_15_MASK (1 << 15)
++#define GPIO_16_MASK (1 << 16)
++#define GPIO_17_MASK (1 << 17)
++#define GPIO_18_MASK (1 << 18)
++#define GPIO_19_MASK (1 << 19)
++#define GPIO_20_MASK (1 << 20)
++#define GPIO_21_MASK (1 << 21)
++#define GPIO_22_MASK (1 << 22)
++#define GPIO_23_MASK (1 << 23)
++#define GPIO_24_MASK (1 << 24)
++#define GPIO_25_MASK (1 << 25)
++#define GPIO_26_MASK (1 << 26)
++#define GPIO_27_MASK (1 << 27)
++#define GPIO_28_MASK (1 << 28)
++#define GPIO_29_MASK (1 << 29)
++#define GPIO_30_MASK (1 << 30)
++#define GPIO_31_MASK (1 << 31)
++
++
++/*
++ * macro declarations for GPIO Set A
++ */
++#define HAL_GPIOA_READ_DATA_OUT_STATUS(data_out_state) \
++ ((data_out_state) = (GPIOA_DATA_OUTPUT_REG))
++
++#define HAL_GPIOA_READ_DATA_IN_STATUS(data_in_state) \
++ ((data_in_state) = (GPIOA_DATA_INPUT_REG))
++
++#define HAL_GPIOA_SET_DIRECTION_OUTPUT(gpio_index) \
++ ((GPIOA_DIRECTION_REG) |= (gpio_index))
++
++#define HAL_GPIOA_SET_DIRECTION_INPUT(gpio_index) \
++ ((GPIOA_DIRECTION_REG) &= ~(gpio_index))
++
++#define HAL_GPIOA_SET_DATA_OUT_HIGH(gpio_index) \
++ ((GPIOA_DATA_BIT_SET_REG) = (gpio_index))
++
++#define HAL_GPIOA_SET_DATA_OUT_LOW(gpio_index) \
++ ((GPIOA_DATA_BIT_CLEAR_REG) = (gpio_index))
++
++#define HAL_GPIOA_ENABLE_INTERRUPT(gpio_index) \
++ ((GPIOA_INTERRUPT_ENABLE_REG) |= (gpio_index))
++
++#define HAL_GPIOA_DISABLE_INTERRUPT(gpio_index) \
++ ((GPIOA_INTERRUPT_ENABLE_REG) &= ~(gpio_index))
++
++#define HAL_GPIOA_READ_INTERRUPT_RAW_STATUS(raw_state) \
++ ((raw_state) = (GPIOA_INTERRUPT_RAW_STATUS_REG))
++
++#define HAL_GPIOA_READ_INTERRUPT_MASKED_STATUS(masked_raw_state) \
++ ((masked_raw_state) = (GPIOA_INTERRUPT_MASKED_STATUS_REG))
++
++#define HAL_GPIOA_DISABLE_INTERRUPT_MASK(gpio_index) \
++ ((GPIOA_INTERRUPT_MASK_REG) &= ~(gpio_index))
++
++#define HAL_GPIOA_ENABLE_INTERRUPT_MASK(gpio_index) \
++ ((GPIOA_INTERRUPT_MASK_REG) |= (gpio_index))
++
++#define HAL_GPIOA_CLEAR_INTERRUPT(gpio_index) \
++ ((GPIOA_INTERRUPT_CLEAR_REG) = (gpio_index))
++
++#define HAL_GPIOA_SET_INTERRUPT_EDGE_TRIGGER_MODE(gpio_index) \
++ ((GPIOA_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index))
++
++#define HAL_GPIOA_SET_INTERRUPT_LEVEL_TRIGGER_MODE(gpio_index) \
++ ((GPIOA_INTERRUPT_TRIGGER_METHOD_REG) |= (gpio_index))
++
++#define HAL_GPIOA_SET_INTERRUPT_SINGLE_EDGE_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOA_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index)); \
++ ((GPIOA_INTERRUPT_TRIGGER_BOTH_EDGES_REG) &= ~(gpio_index)); \
++}
++
++#define HAL_GPIOA_SET_INTERRUPT_BOTH_EDGE_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOA_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index)); \
++ ((GPIOA_INTERRUPT_TRIGGER_BOTH_EDGES_REG) |= (gpio_index)); \
++}
++
++#define HAL_GPIOA_SET_INTERRUPT_SINGLE_RISING_EDGE_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOA_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index)); \
++ ((GPIOA_INTERRUPT_TRIGGER_BOTH_EDGES_REG) &= ~(gpio_index)); \
++ ((GPIOA_INTERRUPT_TRIGGER_TYPE_REG) &= ~(gpio_index)); \
++}
++
++#define HAL_GPIOA_SET_INTERRUPT_SINGLE_FALLING_EDGE_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOA_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index)); \
++ ((GPIOA_INTERRUPT_TRIGGER_BOTH_EDGES_REG) &= ~(gpio_index)); \
++ ((GPIOA_INTERRUPT_TRIGGER_TYPE_REG) |= (gpio_index)); \
++}
++
++#define HAL_GPIOA_SET_INTERRUPT_HIGH_LEVEL_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOA_INTERRUPT_TRIGGER_METHOD_REG) |= (gpio_index)); \
++ ((GPIOA_INTERRUPT_TRIGGER_TYPE_REG) &= ~(gpio_index)); \
++}
++
++#define HAL_GPIOA_SET_INTERRUPT_LOW_LEVEL_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOA_INTERRUPT_TRIGGER_METHOD_REG) |= (gpio_index)); \
++ ((GPIOA_INTERRUPT_TRIGGER_TYPE_REG) |= (gpio_index)); \
++}
++
++#define HAL_GPIOA_ENABLE_BOUNCE(gpio_index) \
++ ((GPIOA_BOUNCE_ENABLE_REG) |= (gpio_index))
++
++#define HAL_GPIOA_DISABLE_BOUNCE(gpio_index) \
++ ((GPIOA_BOUNCE_ENABLE_REG) &= ~(gpio_index))
++
++#define HAL_GPIOA_READ_BOUNCE_PRESCALE_RATIO(prescale_ratio) \
++ ((prescale_ratio) = ((GPIOA_BOUNCE_CLOCK_PRESCALE_REG) & 0x0000FFFF))
++
++#define HAL_GPIOA_WRITE_BOUNCE_PRESCALE_RATIO(prescale_ratio) \
++ ((GPIOA_BOUNCE_CLOCK_PRESCALE_REG) = (prescale_ratio & 0x0000FFFF))
++
++
++
++/*
++ * macro declarations for GPIO Set B
++ */
++#define HAL_GPIOB_READ_DATA_OUT_STATUS(data_out_state) \
++ ((data_out_state) = (GPIOB_DATA_OUTPUT_REG))
++
++#define HAL_GPIOB_READ_DATA_IN_STATUS(data_in_state) \
++ ((data_in_state) = (GPIOB_DATA_INPUT_REG))
++
++#define HAL_GPIOB_SET_DIRECTION_OUTPUT(gpio_index) \
++ ((GPIOB_DIRECTION_REG) |= (gpio_index))
++
++#define HAL_GPIOB_SET_DIRECTION_INPUT(gpio_index) \
++ ((GPIOB_DIRECTION_REG) &= ~(gpio_index))
++
++#define HAL_GPIOB_SET_DATA_OUT_HIGH(gpio_index) \
++ ((GPIOB_DATA_BIT_SET_REG) = (gpio_index))
++
++#define HAL_GPIOB_SET_DATA_OUT_LOW(gpio_index) \
++ ((GPIOB_DATA_BIT_CLEAR_REG) = (gpio_index))
++
++#define HAL_GPIOB_ENABLE_INTERRUPT(gpio_index) \
++ ((GPIOB_INTERRUPT_ENABLE_REG) |= (gpio_index))
++
++#define HAL_GPIOB_DISABLE_INTERRUPT(gpio_index) \
++ ((GPIOB_INTERRUPT_ENABLE_REG) &= ~(gpio_index))
++
++#define HAL_GPIOB_READ_INTERRUPT_RAW_STATUS(raw_state) \
++ ((raw_state) = (GPIOB_INTERRUPT_RAW_STATUS_REG))
++
++#define HAL_GPIOB_READ_INTERRUPT_MASKED_STATUS(masked_raw_state) \
++ ((masked_raw_state) = (GPIOB_INTERRUPT_MASKED_STATUS_REG))
++
++#define HAL_GPIOB_DISABLE_INTERRUPT_MASK(gpio_index) \
++ ((GPIOB_INTERRUPT_MASK_REG) &= ~(gpio_index))
++
++#define HAL_GPIOB_ENABLE_INTERRUPT_MASK(gpio_index) \
++ ((GPIOB_INTERRUPT_MASK_REG) |= (gpio_index))
++
++#define HAL_GPIOB_CLEAR_INTERRUPT(gpio_index) \
++ ((GPIOB_INTERRUPT_CLEAR_REG) = (gpio_index))
++
++#define HAL_GPIOB_SET_INTERRUPT_EDGE_TRIGGER_MODE(gpio_index) \
++ ((GPIOB_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index))
++
++#define HAL_GPIOB_SET_INTERRUPT_LEVEL_TRIGGER_MODE(gpio_index) \
++ ((GPIOB_INTERRUPT_TRIGGER_METHOD_REG) |= (gpio_index))
++
++#define HAL_GPIOB_SET_INTERRUPT_SINGLE_EDGE_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOB_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index)); \
++ ((GPIOB_INTERRUPT_TRIGGER_BOTH_EDGES_REG) &= ~(gpio_index)); \
++}
++
++#define HAL_GPIOB_SET_INTERRUPT_BOTH_EDGE_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOB_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index)); \
++ ((GPIOB_INTERRUPT_TRIGGER_BOTH_EDGES_REG) |= (gpio_index)); \
++}
++
++#define HAL_GPIOB_SET_INTERRUPT_SINGLE_RISING_EDGE_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOB_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index)); \
++ ((GPIOB_INTERRUPT_TRIGGER_BOTH_EDGES_REG) &= ~(gpio_index)); \
++ ((GPIOB_INTERRUPT_TRIGGER_TYPE_REG) &= ~(gpio_index)); \
++}
++
++#define HAL_GPIOB_SET_INTERRUPT_SINGLE_FALLING_EDGE_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOB_INTERRUPT_TRIGGER_METHOD_REG) &= ~(gpio_index)); \
++ ((GPIOB_INTERRUPT_TRIGGER_BOTH_EDGES_REG) &= ~(gpio_index)); \
++ ((GPIOB_INTERRUPT_TRIGGER_TYPE_REG) |= (gpio_index)); \
++}
++
++#define HAL_GPIOB_SET_INTERRUPT_HIGH_LEVEL_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOB_INTERRUPT_TRIGGER_METHOD_REG) |= (gpio_index)); \
++ ((GPIOB_INTERRUPT_TRIGGER_TYPE_REG) &= ~(gpio_index)); \
++}
++
++#define HAL_GPIOB_SET_INTERRUPT_LOW_LEVEL_TRIGGER_MODE(gpio_index) \
++{ \
++ ((GPIOB_INTERRUPT_TRIGGER_METHOD_REG) |= (gpio_index)); \
++ ((GPIOB_INTERRUPT_TRIGGER_TYPE_REG) |= (gpio_index)); \
++}
++
++#define HAL_GPIOB_ENABLE_BOUNCE(gpio_index) \
++ ((GPIOB_BOUNCE_ENABLE_REG) |= (gpio_index))
++
++#define HAL_GPIOB_DISABLE_BOUNCE(gpio_index) \
++ ((GPIOB_BOUNCE_ENABLE_REG) &= ~(gpio_index))
++
++#define HAL_GPIOB_READ_BOUNCE_PRESCALE_RATIO(prescale_ratio) \
++ ((prescale_ratio) = ((GPIOB_BOUNCE_CLOCK_PRESCALE_REG) & 0x0000FFFF))
++
++#define HAL_GPIOB_WRITE_BOUNCE_PRESCALE_RATIO(prescale_ratio) \
++ ((GPIOB_BOUNCE_CLOCK_PRESCALE_REG) = (prescale_ratio & 0x0000FFFF))
++
++
++#endif // end of _STAR_GPIO_H_
+diff -rupN linux-2.6.35.11/include/asm/arch/star_hsdmac.h linux-2.6.35.11-ts7500/include/asm/arch/star_hsdmac.h
+--- linux-2.6.35.11/include/asm/arch/star_hsdmac.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_hsdmac.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,106 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_HSDMAC_H_
++#define _STAR_HSDMAC_H_
++
++
++#include "star_sys_memory_map.h"
++
++
++#if defined(__UBOOT__)
++#define HSDMAC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_MISC_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define HSDMAC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_MISC_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define HSDMAC_CONTROL_STATUS_REG HSDMAC_MEM_MAP_VALUE(0x040)
++
++#define HSDMAC_MASTER0_ADDR_REG HSDMAC_MEM_MAP_VALUE(0x050)
++
++#define HSDMAC_MASTER1_ADDR_REG HSDMAC_MEM_MAP_VALUE(0x054)
++
++#define HSDMAC_LLP_REG HSDMAC_MEM_MAP_VALUE(0x058)
++
++#define HSDMAC_TOT_SIZE_REG HSDMAC_MEM_MAP_VALUE(0x05C)
++
++
++#define HAL_GET_HSDMAC_LLP_COUNTER ((HSDMAC_CONTROL_STATUS_REG >> 8) & 0xF)
++
++#define HAL_HSDMAC_ENABLE() ((HSDMAC_CONTROL_STATUS_REG) |= (0x1))
++
++#define HAL_HSDMAC_DISABLE() ((HSDMAC_CONTROL_STATUS_REG) &= ~(0x1))
++
++
++#define HSDMAC_MASTER0_TO_MASTER1 0
++#define HSDMAC_MASTER1_TO_MASTER0 1
++
++#define HSDMAC_RESPONSE_OK 0
++#define HSDMAC_RESPONSE_ERR -1
++
++#define MAX_HSDMA_VEC 32
++
++#define MAX_HSDMA_XFER_SIZE (0xFFF << 2)
++
++struct hsdma_xfer;
++typedef struct hsdma_xfer hsdma_xfer_t;
++typedef void (*hsdma_end_io_t)(hsdma_xfer_t *hsdma_xfer, int err);
++typedef struct
++{
++ u8 data_direction;
++ u32 src_addr; // virtual
++ u32 dst_addr; // virtual
++ u32 size; // bytes
++} __attribute__((packed)) hsdma_vec_t;
++
++struct hsdma_xfer
++{
++ u8 nr_vec;
++ hsdma_vec_t vec[MAX_HSDMA_VEC];
++ hsdma_end_io_t hsdma_end_io;
++ void *private;
++};
++
++/*
++ * HSDMAC LLP Descriptor object
++ */
++typedef struct
++{
++ u32 src_addr; // physical
++ u32 dst_addr; // physical
++ u32 llp;
++ u32 tot_size : 16;//b15-b0
++ u32 reserved0 : 12;//b27-b16
++ u32 tc_mask : 1; //b28
++ u32 data_direction : 1; //b29
++ u32 reserved1 : 2; //b31-30
++} __attribute__((packed)) hsdma_llp_descr_t;
++
++
++#endif // end of #ifndef _STAR_HSDMAC_H_
+diff -rupN linux-2.6.35.11/include/asm/arch/star_i2c.h linux-2.6.35.11-ts7500/include/asm/arch/star_i2c.h
+--- linux-2.6.35.11/include/asm/arch/star_i2c.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_i2c.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,69 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_I2C_H_
++#define _STAR_I2C_H_
++
++#include <mach/star_sys_memory_map.h>
++
++#define I2C_MEM_MAP_ADDR(reg_offset) (SYSVA_I2C_BASE_ADDR + reg_offset)
++#define I2C_MEM_MAP_VALUE(reg_offset) (*((unsigned int volatile *)I2C_MEM_MAP_ADDR(reg_offset)))
++
++#define I2C_CONTROLLER_REG_ADDR I2C_MEM_MAP_ADDR(0x20)
++#define I2C_TIME_OUT_REG_ADDR I2C_MEM_MAP_ADDR(0x24)
++#define I2C_SLAVE_ADDRESS_REG_ADDR I2C_MEM_MAP_ADDR(0x28)
++#define I2C_WRITE_DATA_REG_ADDR I2C_MEM_MAP_ADDR(0x2C)
++#define I2C_READ_DATA_REG_ADDR I2C_MEM_MAP_ADDR(0x30)
++#define I2C_INTERRUPT_STATUS_REG_ADDR I2C_MEM_MAP_ADDR(0x34)
++#define I2C_INTERRUPT_ENABLE_REG_ADDR I2C_MEM_MAP_ADDR(0x38)
++
++#define I2C_CONTROLLER_REG I2C_MEM_MAP_VALUE(0x20)
++#define I2C_TIME_OUT_REG I2C_MEM_MAP_VALUE(0x24)
++#define I2C_SLAVE_ADDRESS_REG I2C_MEM_MAP_VALUE(0x28)
++#define I2C_WRITE_DATA_REG I2C_MEM_MAP_VALUE(0x2C)
++#define I2C_READ_DATA_REG I2C_MEM_MAP_VALUE(0x30)
++#define I2C_INTERRUPT_STATUS_REG I2C_MEM_MAP_VALUE(0x34)
++#define I2C_INTERRUPT_ENABLE_REG I2C_MEM_MAP_VALUE(0x38)
++
++#define I2C_READ_ONLY_CMD (0)
++#define I2C_WRITE_ONLY_CMD (1)
++#define I2C_WRITE_READ_CMD (2)
++#define I2C_READ_WRITE_CMD (3)
++
++#define I2C_DATA_LEN_1_BYTE (0)
++#define I2C_DATA_LEN_2_BYTE (1)
++#define I2C_DATA_LEN_3_BYTE (2)
++#define I2C_DATA_LEN_4_BYTE (3)
++
++#define I2C_BUS_ERROR_FLAG (0x1)
++#define I2C_ACTION_DONE_FLAG (0x2)
++
++#define HAL_I2C_ENABLE_I2C() (I2C_CONTROLLER_REG) |= ((unsigned int)0x1 << 31);
++#define HAL_I2C_DISABLE_I2C() (I2C_CONTROLLER_REG) &= ~((unsigned int)0x1 << 31);
++#define HAL_I2C_ENABLE_DATA_SWAP() (I2C_CONTROLLER_REG) |= (0x1 << 24);
++#define HAL_I2C_DISABLE_DATA_SWAP() (I2C_CONTROLLER_REG) &= ~(0x1 << 24);
++#define HAL_I2C_START_TRANSFER() (I2C_CONTROLLER_REG) |= (0x1 << 6);
++#define HAL_I2C_STOP_TRANSFER() (I2C_CONTROLLER_REG) &= ~(0x1 << 6);
++
++#endif
++
+diff -rupN linux-2.6.35.11/include/asm/arch/star_i2s.h linux-2.6.35.11-ts7500/include/asm/arch/star_i2s.h
+--- linux-2.6.35.11/include/asm/arch/star_i2s.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_i2s.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,176 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_I2S_H_
++#define _STAR_I2S_H_
++
++/******************************************************************************
++ * MODULE NAME: star_i2s.h
++ * PROJECT CODE: Orion
++ * DESCRIPTION:
++ * MAINTAINER: MJLIU
++ * DATE: 15 September 2005
++ *
++ * SOURCE CONTROL:
++ *
++ * REVISION HISTORY:
++ * 15 September 2005 - MJLIU - Initial Version v1.0
++ *
++ *
++ * SOURCE:
++ * ISSUES:
++ * NOTES TO USERS:
++ ******************************************************************************/
++
++#include <mach/star_sys_memory_map.h>
++
++#define I2S_MEM_MAP_ADDR(reg_offset) (SYSVA_I2S_BASE_ADDR + reg_offset)
++#define I2S_MEM_MAP_VALUE(reg_offset) (*((unsigned int volatile *)I2S_MEM_MAP_ADDR(reg_offset)))
++
++//#define I2S_BASE_ADDR (SYS_I2S_BASE_ADDR)
++
++
++/*
++ * define access macros
++ */
++#define I2S_CONFIGURATION_REG_ADDR I2S_MEM_MAP_ADDR(0xC0)
++#define I2S_RIGHT_TRANSMIT_DATA_REG_ADDR I2S_MEM_MAP_ADDR(0xC4)
++#define I2S_LEFT_TRANSMIT_DATA_REG_ADDR I2S_MEM_MAP_ADDR(0xC8)
++#define I2S_RIGHT_RECEIVE_DATA_REG_ADDR I2S_MEM_MAP_ADDR(0xCC)
++#define I2S_LEFT_RECEIVE_DATA_REG_ADDR I2S_MEM_MAP_ADDR(0xD0)
++#define I2S_INTERRUPT_STATUS_REG_ADDR I2S_MEM_MAP_ADDR(0xD4)
++#define I2S_INTERRUPT_ENABLE_REG_ADDR I2S_MEM_MAP_ADDR(0xD8)
++
++#define I2S_CONFIGURATION_REG I2S_MEM_MAP_VALUE(0xC0)
++#define I2S_RIGHT_TRANSMIT_DATA_REG I2S_MEM_MAP_VALUE(0xC4)
++#define I2S_LEFT_TRANSMIT_DATA_REG I2S_MEM_MAP_VALUE(0xC8)
++#define I2S_RIGHT_RECEIVE_DATA_REG I2S_MEM_MAP_VALUE(0xCC)
++#define I2S_LEFT_RECEIVE_DATA_REG I2S_MEM_MAP_VALUE(0xD0)
++#define I2S_INTERRUPT_STATUS_REG I2S_MEM_MAP_VALUE(0xD4)
++#define I2S_INTERRUPT_ENABLE_REG I2S_MEM_MAP_VALUE(0xD8)
++
++
++/*
++ * define constants macros
++ */
++#define I2S_DATA_16_BIT (0)
++#define I2S_DATA_32_BIT (1)
++
++#define I2S_RXBF_R_FULL_FLAG (0x01)
++#define I2S_TXBF_R_EMPTY_FLAG (0x02)
++#define I2S_RXBF_L_FULL_FLAG (0x04)
++#define I2S_TXBF_L_EMPTY_FLAG (0x08)
++
++#define I2S_RXBF_R_OR_FLAG (0x10)
++#define I2S_TXBF_R_UR_FLAG (0x20)
++#define I2S_RXBF_L_OR_FLAG (0x40)
++#define I2S_TXBF_L_UR_FLAG (0x80)
++
++
++#define I2S_MASTER_MODE (1)
++#define I2S_SLAVE_MODE (0)
++
++#define I2S_I2S_MODE (1)
++#define I2S_RJF_MODE (2)
++#define I2S_LJF_MODE (3)
++
++#define I2S_CLOCK_CONTINUOUS_MODE (0)
++#define I2S_CLOCK_256S_MODE (1)
++
++
++#define I2S_WS_RATE_32KHZ (1) /* 8.192 MHz */
++#define I2S_WS_RATE_44_1KHZ (2) /* 11.2896 MHz */
++#define I2S_WS_RATE_48KHZ (3) /* 12.288 MHz */
++
++
++/*
++ * define data structure
++ */
++#if 0
++typedef struct _I2S_OBJECT_ I2S_OBJECT_T;
++
++struct _I2S_OBJECT_
++{
++ u_int32 config;
++ u_int32 interrupt_config;
++
++
++ /*
++ * For interrupt setting
++ */
++ INTC_OBJECT_T intc_obj;
++};
++
++
++/*
++ * function declarations
++ */
++void Hal_I2s_Initialize(I2S_OBJECT_T *);
++#endif
++
++
++/*
++ * macro declarations
++ */
++#define HAL_I2S_ENABLE_I2S() \
++{ \
++ (I2S_CONFIGURATION_REG) |= ((u32)0x1 << 31); \
++}
++
++#define HAL_I2S_DISABLE_I2S() \
++{ \
++ (I2S_CONFIGURATION_REG) &= ~((u32)0x1 << 31); \
++}
++
++#define HAL_I2S_ENABLE_DATA_SWAP() \
++{ \
++ (I2S_CONFIGURATION_REG) |= (0x1 << 24); \
++}
++
++#define HAL_I2S_DISABLE_DATA_SWAP() \
++{ \
++ (I2S_CONFIGURATION_REG) &= ~(0x1 << 24); \
++}
++
++#define HAL_I2S_DISABLE_LEFT_CHANNEL_TRANSMIT_BUFFER_UNDERRUN_INTERRUPT() \
++{ \
++ (I2S_INTERRUPT_ENABLE_REG) &= ~(I2S_TXBF_L_UR_FLAG); \
++}
++
++#define HAL_I2S_DISABLE_RIGHT_CHANNEL_TRANSMIT_BUFFER_UNDERRUN_INTERRUPT() \
++{ \
++ (I2S_INTERRUPT_ENABLE_REG) &= ~(I2S_TXBF_R_UR_FLAG); \
++}
++
++#define HAL_I2S_DISABLE_LEFT_CHANNEL_RECEIVE_BUFFER_OVERRUN_INTERRUPT() \
++{ \
++ (I2S_INTERRUPT_ENABLE_REG) &= ~(I2S_RXBF_L_OR_FLAG); \
++}
++
++#define HAL_I2S_DISABLE_RIGHT_CHANNEL_RECEIVE_BUFFER_OVERRUN_INTERRUPT() \
++{ \
++ (I2S_INTERRUPT_ENABLE_REG) &= ~(I2S_RXBF_R_OR_FLAG); \
++}
++
++
++#endif // end of #ifndef _STAR_I2S_H_
+diff -rupN linux-2.6.35.11/include/asm/arch/star_ide.h linux-2.6.35.11-ts7500/include/asm/arch/star_ide.h
+--- linux-2.6.35.11/include/asm/arch/star_ide.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_ide.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,245 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_IDE_H_
++#define _STAR_IDE_H_
++
++
++#include "star_sys_memory_map.h"
++
++
++#if defined(__UBOOT__)
++#define IDE_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_IDE_CONTROLLER_BASE_ADDR + reg_offset)))
++#define IDE_BUS_MEM_MAP_VALUE(reg_offset) (*((u8 volatile *)(SYSPA_IDE_DEVICE_BASE_ADDR + reg_offset)))
++#define IDE_DATA_MEM_MAP_VALUE(reg_offset) (*((u16 volatile *)(SYSPA_IDE_DEVICE_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define IDE_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_IDE_CONTROLLER_BASE_ADDR + reg_offset)))
++#define IDE_BUS_MEM_MAP_VALUE(reg_offset) (*((u8 volatile *)(SYSVA_IDE_DEVICE_BASE_ADDR + reg_offset)))
++#define IDE_DATA_MEM_MAP_VALUE(reg_offset) (*((u16 volatile *)(SYSVA_IDE_DEVICE_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * IDE Controller Registers
++ */
++#define IDE_PIO_CONTROL_REG IDE_MEM_MAP_VALUE(0x00)
++#define IDE_DRIVE0_PIO_TIMING_CONFIG_REG IDE_MEM_MAP_VALUE(0x04)
++#define IDE_DRIVE1_PIO_TIMING_CONFIG_REG IDE_MEM_MAP_VALUE(0x08)
++#define IDE_DRIVE0_DMA_TIMING_CONFIG_REG IDE_MEM_MAP_VALUE(0x0C)
++#define IDE_DRIVE1_DMA_TIMING_CONFIG_REG IDE_MEM_MAP_VALUE(0x10)
++#define IDE_UDMA_TIMING_CONFIG_REG IDE_MEM_MAP_VALUE(0x14)
++#define IDE_DMA_UDMA_CONTROL_REG IDE_MEM_MAP_VALUE(0x18)
++#define IDE_STATUS_CONTROL_REG IDE_MEM_MAP_VALUE(0x1C)
++#define IDE_BUS_MASTER_DTP_REG IDE_MEM_MAP_VALUE(0x20)
++#define IDE_FAST_PATH_ACCESS_WINDOW_REG IDE_MEM_MAP_VALUE(0x24)
++#define IDE_FAST_PATH_DMA_BURST_SIZE_REG IDE_MEM_MAP_VALUE(0x28)
++
++
++/*
++ * IDE Command Block Registers
++ */
++#define _IDE_DATA_REG IDE_DATA_MEM_MAP_VALUE(0x20)
++#define _IDE_ERROR_REG IDE_BUS_MEM_MAP_VALUE(0x24)
++#define _IDE_FEATURES_REG IDE_BUS_MEM_MAP_VALUE(0x24)
++#define _IDE_SECTOR_COUNT_REG IDE_BUS_MEM_MAP_VALUE(0x28)
++#define _IDE_LBA_LOW_REG IDE_BUS_MEM_MAP_VALUE(0x2C)
++#define _IDE_LBA_MID_REG IDE_BUS_MEM_MAP_VALUE(0x30)
++#define _IDE_LBA_HIGH_REG IDE_BUS_MEM_MAP_VALUE(0x34)
++#define _IDE_DEVICE_REG IDE_BUS_MEM_MAP_VALUE(0x38)
++#define _IDE_COMMAND_REG IDE_BUS_MEM_MAP_VALUE(0x3C)
++#define _IDE_STATUS_REG IDE_BUS_MEM_MAP_VALUE(0x3C)
++
++
++/*
++ * IDE Control Block Registers
++ */
++#define IDE_DEVICE_CONTROL_REG IDE_BUS_MEM_MAP_VALUE(0x40)
++#define IDE_ALTERNATE_STATUS_REG IDE_BUS_MEM_MAP_VALUE(0x40)
++
++
++#define IDE_CD (0x01)
++#define IDE_IO (0x02)
++#define IDE_REL (0x04)
++#define IDE_OVL (0x02)
++#define IDE_BSY (0x80)
++#define IDE_DRQ (0x08)
++#define IDE_SERV (0x10)
++#define IDE_DMRD (0x20)
++#define IDE_ERR (0x01)
++#define IDE_SRST (0x04)
++
++/*
++ * macro declarations for IDE Controller
++ */
++#define HAL_IDE_DRIVE0_IORDY_SAMPLE_ENABLE() \
++{ \
++ (IDE_PIO_CONTROL_REG) |= (0x1 << 0); \
++}
++
++#define HAL_IDE_DRIVE0_IORDY_SAMPLE_DISABLE() \
++{ \
++ (IDE_PIO_CONTROL_REG) &= ~(0x1 << 0); \
++}
++
++#define HAL_IDE_DRIVE1_IORDY_SAMPLE_ENABLE() \
++{ \
++ (IDE_PIO_CONTROL_REG) |= (0x1 << 1); \
++}
++
++#define HAL_IDE_DRIVE1_IORDY_SAMPLE_DISABLE() \
++{ \
++ (IDE_PIO_CONTROL_REG) &= ~(0x1 << 1); \
++}
++
++#define HAL_IDE_DRIVE0_UDMA_ENABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) |= (0x1 << 0); \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 2); \
++}
++
++#define HAL_IDE_DRIVE0_UDMA_DISABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 0); \
++}
++
++#define HAL_IDE_DRIVE1_UDMA_ENABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) |= (0x1 << 1); \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 3); \
++}
++
++#define HAL_IDE_DRIVE1_UDMA_DISABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 1); \
++}
++
++#define HAL_IDE_DRIVE0_DMA_ENABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) |= (0x1 << 2); \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 0); \
++}
++
++#define HAL_IDE_DRIVE0_DMA_DISABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 2); \
++}
++
++#define HAL_IDE_DRIVE1_DMA_ENABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) |= (0x1 << 3); \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 1); \
++}
++
++#define HAL_IDE_TO_USB_FAST_PATH_ENABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) |= (0x1 << 4); \
++}
++
++#define HAL_IDE_TO_USB_FAST_PATH_DISABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 4); \
++}
++
++#define HAL_IDE_DRIVE1_DMA_DISABLE() \
++{ \
++ (IDE_DMA_UDMA_CONTROL_REG) &= ~(0x1 << 3); \
++}
++
++#define HAL_IDE_DMA_UDMA_START() \
++{ \
++ (IDE_STATUS_CONTROL_REG) |= (0x1); \
++}
++
++#define HAL_IDE_DMA_UDMA_STOP() \
++{ \
++ (IDE_STATUS_CONTROL_REG) &= ~(0x1); \
++}
++
++#define HAL_IDE_CLEAR_PRD_INTERRUPT_STATUS() \
++{ \
++ (IDE_STATUS_CONTROL_REG) |= (0x1 << 2); \
++}
++
++#define HAL_IDE_CLEAR_INTRQ_INTERRUPT_STATUS() \
++{ \
++ (IDE_STATUS_CONTROL_REG) |= (0x1 << 1); \
++}
++
++#define HAL_IDE_HOST_TRANSFER_WRITE_OUT() \
++{ \
++ (IDE_STATUS_CONTROL_REG) |= (0x1 << 3); \
++}
++
++#define HAL_IDE_HOST_TRANSFER_READ_IN() \
++{ \
++ (IDE_STATUS_CONTROL_REG) &= ~(0x1 << 3); \
++}
++
++#define HAL_IDE_MASK_PRD_INTERRUPT() \
++{ \
++ (IDE_STATUS_CONTROL_REG) |= (0x1 << 6); \
++}
++
++#define HAL_IDE_UNMASK_PRD_INTERRUPT() \
++{ \
++ (IDE_STATUS_CONTROL_REG) &= ~(0x1 << 6); \
++}
++
++#define HAL_IDE_SET_DESCRIPTOR_TABLE_POINTER(dtp) \
++{ \
++ (IDE_BUS_MASTER_DTP_REG) = (dtp); \
++}
++
++#define HAL_IDE_SET_FAST_PATH_ACCESS_WINDOW(fp_access_window) \
++{ \
++ (IDE_FAST_PATH_ACCESS_WINDOW_REG) = (fp_access_window); \
++}
++
++/*
++ * macro declarations for IDE Device
++ */
++#define HAL_IDE_SELECT_DEVICE_0() \
++{ \
++ (_IDE_DEVICE_REG) = 0; \
++}
++
++#define HAL_IDE_SELECT_DEVICE_1() \
++{ \
++ (_IDE_DEVICE_REG) = (0x1 << 4); \
++}
++
++#define HAL_IDE_ENABLE_DEVICE_INTRQ() \
++{ \
++ (IDE_DEVICE_CONTROL_REG) = (0); \
++}
++
++#define HAL_IDE_DISABLE_DEVICE_INTRQ() \
++{ \
++ (IDE_DEVICE_CONTROL_REG) = (0x2); \
++}
++
++
++#endif // end of #ifndef _STAR_IDE_H_
++
+diff -rupN linux-2.6.35.11/include/asm/arch/star_intc.h linux-2.6.35.11-ts7500/include/asm/arch/star_intc.h
+--- linux-2.6.35.11/include/asm/arch/star_intc.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_intc.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,328 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_INTC_H_
++#define _STAR_INTC_H_
++
++
++//#include <mach/star_sys_memory_map.h>
++#include <mach/star_sys_memory_map.h>
++
++#if defined(__UBOOT__)
++#define INTC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_VIC_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define INTC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_VIC_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define INTC_INTERRUPT_RAW_STATUS_REG INTC_MEM_MAP_VALUE(0x000)
++#define INTC_EDGE_INTERRUPT_SOURCE_CLEAR_REG INTC_MEM_MAP_VALUE(0x004)
++#define INTC_INTERRUPT_MASK_REG INTC_MEM_MAP_VALUE(0x008)
++#define INTC_INTERRUPT_MASK_CLEAR_REG INTC_MEM_MAP_VALUE(0x00C)
++#define INTC_INTERRUPT_TRIGGER_MODE_REG INTC_MEM_MAP_VALUE(0x010)
++#define INTC_INTERRUPT_TRIGGER_LEVEL_REG INTC_MEM_MAP_VALUE(0x014)
++#define INTC_FIQ_SELECT_REG INTC_MEM_MAP_VALUE(0x018)
++#define INTC_IRQ_STATUS_REG INTC_MEM_MAP_VALUE(0x01C)
++#define INTC_FIQ_STATUS_REG INTC_MEM_MAP_VALUE(0x020)
++#define INTC_SOFTWARE_INTERRUPT_REG INTC_MEM_MAP_VALUE(0x024)
++#define INTC_SOFTWARE_INTERRUPT_CLEAR_REG INTC_MEM_MAP_VALUE(0x028)
++#define INTC_SOFTWARE_PRIORITY_MASK_REG INTC_MEM_MAP_VALUE(0x02C)
++#define INTC_POWER_MANAGEMENT_INTERRUPT_REG INTC_MEM_MAP_VALUE(0x034)
++
++#define INTC_VECTOR_ADDRESS_0_REG INTC_MEM_MAP_VALUE(0x040)
++#define INTC_VECTOR_ADDRESS_1_REG INTC_MEM_MAP_VALUE(0x044)
++#define INTC_VECTOR_ADDRESS_2_REG INTC_MEM_MAP_VALUE(0x048)
++#define INTC_VECTOR_ADDRESS_3_REG INTC_MEM_MAP_VALUE(0x04C)
++#define INTC_VECTOR_ADDRESS_4_REG INTC_MEM_MAP_VALUE(0x050)
++#define INTC_VECTOR_ADDRESS_5_REG INTC_MEM_MAP_VALUE(0x054)
++#define INTC_VECTOR_ADDRESS_6_REG INTC_MEM_MAP_VALUE(0x058)
++#define INTC_VECTOR_ADDRESS_7_REG INTC_MEM_MAP_VALUE(0x05C)
++#define INTC_VECTOR_ADDRESS_8_REG INTC_MEM_MAP_VALUE(0x060)
++#define INTC_VECTOR_ADDRESS_9_REG INTC_MEM_MAP_VALUE(0x064)
++#define INTC_VECTOR_ADDRESS_10_REG INTC_MEM_MAP_VALUE(0x068)
++#define INTC_VECTOR_ADDRESS_11_REG INTC_MEM_MAP_VALUE(0x06C)
++#define INTC_VECTOR_ADDRESS_12_REG INTC_MEM_MAP_VALUE(0x070)
++#define INTC_VECTOR_ADDRESS_13_REG INTC_MEM_MAP_VALUE(0x074)
++#define INTC_VECTOR_ADDRESS_14_REG INTC_MEM_MAP_VALUE(0x078)
++#define INTC_VECTOR_ADDRESS_15_REG INTC_MEM_MAP_VALUE(0x07C)
++#define INTC_VECTOR_ADDRESS_16_REG INTC_MEM_MAP_VALUE(0x080)
++#define INTC_VECTOR_ADDRESS_17_REG INTC_MEM_MAP_VALUE(0x084)
++#define INTC_VECTOR_ADDRESS_18_REG INTC_MEM_MAP_VALUE(0x088)
++#define INTC_VECTOR_ADDRESS_19_REG INTC_MEM_MAP_VALUE(0x08C)
++#define INTC_VECTOR_ADDRESS_20_REG INTC_MEM_MAP_VALUE(0x090)
++#define INTC_VECTOR_ADDRESS_21_REG INTC_MEM_MAP_VALUE(0x094)
++#define INTC_VECTOR_ADDRESS_22_REG INTC_MEM_MAP_VALUE(0x098)
++#define INTC_VECTOR_ADDRESS_23_REG INTC_MEM_MAP_VALUE(0x09C)
++#define INTC_VECTOR_ADDRESS_24_REG INTC_MEM_MAP_VALUE(0x0A0)
++#define INTC_VECTOR_ADDRESS_25_REG INTC_MEM_MAP_VALUE(0x0A4)
++#define INTC_VECTOR_ADDRESS_26_REG INTC_MEM_MAP_VALUE(0x0A8)
++#define INTC_VECTOR_ADDRESS_27_REG INTC_MEM_MAP_VALUE(0x0AC)
++#define INTC_VECTOR_ADDRESS_28_REG INTC_MEM_MAP_VALUE(0x0B0)
++#define INTC_VECTOR_ADDRESS_29_REG INTC_MEM_MAP_VALUE(0x0B4)
++#define INTC_VECTOR_ADDRESS_30_REG INTC_MEM_MAP_VALUE(0x0B8)
++#define INTC_VECTOR_ADDRESS_31_REG INTC_MEM_MAP_VALUE(0x0BC)
++
++#define INTC_INTERRUPT_PRIORITY_0_REG INTC_MEM_MAP_VALUE(0x0C0)
++#define INTC_INTERRUPT_PRIORITY_1_REG INTC_MEM_MAP_VALUE(0x0C4)
++#define INTC_INTERRUPT_PRIORITY_2_REG INTC_MEM_MAP_VALUE(0x0C8)
++#define INTC_INTERRUPT_PRIORITY_3_REG INTC_MEM_MAP_VALUE(0x0CC)
++#define INTC_INTERRUPT_PRIORITY_4_REG INTC_MEM_MAP_VALUE(0x0D0)
++#define INTC_INTERRUPT_PRIORITY_5_REG INTC_MEM_MAP_VALUE(0x0D4)
++#define INTC_INTERRUPT_PRIORITY_6_REG INTC_MEM_MAP_VALUE(0x0D8)
++#define INTC_INTERRUPT_PRIORITY_7_REG INTC_MEM_MAP_VALUE(0x0DC)
++#define INTC_INTERRUPT_PRIORITY_8_REG INTC_MEM_MAP_VALUE(0x0E0)
++#define INTC_INTERRUPT_PRIORITY_9_REG INTC_MEM_MAP_VALUE(0x0E4)
++#define INTC_INTERRUPT_PRIORITY_10_REG INTC_MEM_MAP_VALUE(0x0E8)
++#define INTC_INTERRUPT_PRIORITY_11_REG INTC_MEM_MAP_VALUE(0x0EC)
++#define INTC_INTERRUPT_PRIORITY_12_REG INTC_MEM_MAP_VALUE(0x0F0)
++#define INTC_INTERRUPT_PRIORITY_13_REG INTC_MEM_MAP_VALUE(0x0F4)
++#define INTC_INTERRUPT_PRIORITY_14_REG INTC_MEM_MAP_VALUE(0x0F8)
++#define INTC_INTERRUPT_PRIORITY_15_REG INTC_MEM_MAP_VALUE(0x0FC)
++#define INTC_INTERRUPT_PRIORITY_16_REG INTC_MEM_MAP_VALUE(0x100)
++#define INTC_INTERRUPT_PRIORITY_17_REG INTC_MEM_MAP_VALUE(0x104)
++#define INTC_INTERRUPT_PRIORITY_18_REG INTC_MEM_MAP_VALUE(0x108)
++#define INTC_INTERRUPT_PRIORITY_19_REG INTC_MEM_MAP_VALUE(0x10C)
++#define INTC_INTERRUPT_PRIORITY_20_REG INTC_MEM_MAP_VALUE(0x110)
++#define INTC_INTERRUPT_PRIORITY_21_REG INTC_MEM_MAP_VALUE(0x114)
++#define INTC_INTERRUPT_PRIORITY_22_REG INTC_MEM_MAP_VALUE(0x118)
++#define INTC_INTERRUPT_PRIORITY_23_REG INTC_MEM_MAP_VALUE(0x11C)
++#define INTC_INTERRUPT_PRIORITY_24_REG INTC_MEM_MAP_VALUE(0x120)
++#define INTC_INTERRUPT_PRIORITY_25_REG INTC_MEM_MAP_VALUE(0x124)
++#define INTC_INTERRUPT_PRIORITY_26_REG INTC_MEM_MAP_VALUE(0x128)
++#define INTC_INTERRUPT_PRIORITY_27_REG INTC_MEM_MAP_VALUE(0x12C)
++#define INTC_INTERRUPT_PRIORITY_28_REG INTC_MEM_MAP_VALUE(0x130)
++#define INTC_INTERRUPT_PRIORITY_29_REG INTC_MEM_MAP_VALUE(0x134)
++#define INTC_INTERRUPT_PRIORITY_30_REG INTC_MEM_MAP_VALUE(0x138)
++#define INTC_INTERRUPT_PRIORITY_31_REG INTC_MEM_MAP_VALUE(0x13C)
++
++#define INTC_IRQ_VECTOR_ADDRESS_REG INTC_MEM_MAP_VALUE(0x140)
++
++#define INTC_VECTOR_INTERRUPT_ENABLE_REG INTC_MEM_MAP_VALUE(0x144)
++
++
++
++/*
++ * define constants macros
++ */
++#define INTC_TIMER1_BIT_INDEX (0)
++#define INTC_TIMER2_BIT_INDEX (1)
++
++#define INTC_CLOCK_SCALE_BIT_INDEX (2)
++
++#define INTC_WATCHDOG_TIMER_BIT_INDEX (3)
++
++#define INTC_GPIO_EXTERNAL_INT_BIT_INDEX (4)
++
++#define INTC_PCI_INTA_BIT_INDEX (5)
++#define INTC_PCI_INTB_BIT_INDEX (6)
++#define INTC_PCI_BROKEN_BIT_INDEX (7)
++#define INTC_PCI_AHB2BRIDGE_BIT_INDEX (8)
++
++#define INTC_UART0_BIT_INDEX (9)
++#define INTC_UART1_BIT_INDEX (10)
++
++#define INTC_GDMAC_TC_BIT_INDEX (11)
++#define INTC_GDMAC_ERROR_BIT_INDEX (12)
++
++#define INTC_PCMCIA_BRIDGE_BIT_INDEX (13)
++
++#define INTC_RTC_BIT_INDEX (14)
++
++#define INTC_PCM_BIT_INDEX (15)
++
++#define INTC_USB20_DEVICE_BIT_INDEX (16)
++
++#define INTC_IDE_BIT_INDEX (17)
++
++#define INTC_NIC_STATUS_BIT_INDEX (18)
++#define INTC_NIC_TXTC_BIT_INDEX (19)
++#define INTC_NIC_RXRC_BIT_INDEX (20)
++#define INTC_NIC_TXQE_BIT_INDEX (21)
++#define INTC_NIC_RXQF_BIT_INDEX (22)
++
++#define INTC_USB11_BIT_INDEX (23)
++#define INTC_USB20_BIT_INDEX (24)
++
++#define INTC_I2S_BIT_INDEX (25)
++#define INTC_SPI_BIT_INDEX (26)
++#define INTC_I2C_BIT_INDEX (27)
++
++#define INTC_USB_DEVICE_VBUS_BIT_INDEX (28)
++
++#define INTC_EXT_INT29_BIT_INDEX (29)
++#define INTC_EXT_INT30_BIT_INDEX (30)
++#define INTC_HSDMAC_BIT_INDEX (31)
++
++
++/*
++ * define interrupt types
++ */
++#define INTC_IRQ_INTERRUPT (0)
++#define INTC_FIQ_INTERRUPT (1)
++
++/*
++ * define interrupt trigger mode
++ */
++#define INTC_LEVEL_TRIGGER (0)
++#define INTC_EDGE_TRIGGER (1)
++
++/*
++ * define rising/falling edge for edge trigger mode
++ */
++#define INTC_RISING_EDGE (0)
++#define INTC_FALLING_EDGE (1)
++
++/*
++ * define active High/Low for level trigger mode
++ */
++#define INTC_ACTIVE_HIGH (0)
++#define INTC_ACTIVE_LOW (1)
++
++/*
++ * macro declarations
++ */
++#define HAL_INTC_READ_INTERRUPT_RAW_STATUS(int_raw_status) \
++{ \
++ (int_raw_status) = (INTC_INTERRUPT_RAW_STATUS_REG); \
++}
++
++
++#define HAL_INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(source_bit_index) \
++{ \
++ (INTC_EDGE_INTERRUPT_SOURCE_CLEAR_REG) = (1 << source_bit_index); \
++}
++
++
++#define HAL_INTC_READ_INTERRUPT_MASK(int_mask) \
++{ \
++ (int_mask) = (INTC_INTERRUPT_MASK_REG); \
++}
++
++
++#define HAL_INTC_WRITE_INTERRUPT_MASK(int_mask) \
++{ \
++ (INTC_INTERRUPT_MASK_REG) = (int_mask); \
++}
++
++
++#define HAL_INTC_DISABLE_INTERRUPT_SOURCE(source_bit_index) \
++{ \
++ (INTC_INTERRUPT_MASK_REG) = (1 << source_bit_index); \
++}
++
++
++#define HAL_INTC_ENABLE_INTERRUPT_SOURCE(source_bit_index) \
++{ \
++ (INTC_INTERRUPT_MASK_CLEAR_REG) = (1 << source_bit_index); \
++}
++
++
++#define HAL_INTC_SET_EDGE_TRIGGER_MODE(source_bit_index) \
++{ \
++ (INTC_INTERRUPT_TRIGGER_MODE_REG) |= (1 << source_bit_index);\
++}
++
++
++#define HAL_INTC_SET_LEVEL_TRIGGER_MODE(source_bit_index) \
++{ \
++ (INTC_INTERRUPT_TRIGGER_MODE_REG) &= (~(1 << source_bit_index)); \
++}
++
++
++#define HAL_INTC_SET_RISING_EDGE_TRIGGER_LEVEL(source_bit_index) \
++{ \
++ (INTC_INTERRUPT_TRIGGER_LEVEL_REG) &= (~(1 << source_bit_index)); \
++}
++
++
++#define HAL_INTC_SET_FALLING_EDGE_TRIGGER_LEVEL(source_bit_index) \
++{ \
++ (INTC_INTERRUPT_TRIGGER_LEVEL_REG) |= (1 << source_bit_index); \
++}
++
++
++#define HAL_INTC_SET_ACTIVE_HIGH_TRIGGER_LEVEL(source_bit_index) \
++{ \
++ (INTC_INTERRUPT_TRIGGER_LEVEL_REG) &= (~(1 << source_bit_index));\
++}
++
++
++#define HAL_INTC_SET_ACTIVE_LOW_TRIGGER_LEVEL(source_bit_index) \
++{ \
++ (INTC_INTERRUPT_TRIGGER_LEVEL_REG) |= ((1 << source_bit_index)); \
++}
++
++
++#define HAL_INTC_ASSIGN_INTERRUPT_TO_IRQ(source_bit_index) \
++{ \
++ (INTC_FIQ_SELECT_REG) &= (~(1 << source_bit_index)); \
++}
++
++
++#define HAL_INTC_ASSIGN_INTERRUPT_TO_FIQ(source_bit_index) \
++{ \
++ (INTC_FIQ_SELECT_REG) |= (1 << source_bit_index); \
++}
++
++
++#define HAL_INTC_READ_IRQ_STATUS(int_irq_status) \
++{ \
++ (int_irq_status) = (INTC_IRQ_STATUS_REG); \
++}
++
++
++#define HAL_INTC_READ_FIQ_STATUS(int_fiq_status) \
++{ \
++ (int_fiq_status) = (INTC_FIQ_STATUS_REG); \
++}
++
++
++#define HAL_INTC_READ_SOFTWARE_INTERRUPT(software_interrupt) \
++{ \
++ (software_interrupt) = (INTC_SOFTWARE_INTERRUPT_REG); \
++}
++
++
++#define HAL_INTC_ENABLE_SOFTWARE_INTERRUPT(source_bit_index) \
++{ \
++ (INTC_SOFTWARE_INTERRUPT_REG) = (1 << source_bit_index); \
++}
++
++
++#define HAL_INTC_CLEAR_SOFTWARE_INTERRUPT(source_bit_index) \
++{ \
++ (INTC_SOFTWARE_INTERRUPT_CLEAR_REG) = (1 << source_bit_index); \
++}
++
++
++#define HAL_INTC_SELECT_INTERRUPT_SOURCE_FOR_SLEEP_WAKEUP(source_bit_index) \
++{ \
++ (INTC_POWER_MANAGEMENT_INTERRUPT_REG) = (1 << source_bit_index); \
++}
++
++#endif // end of #ifndef _STAR_INTC_H_
+diff -rupN linux-2.6.35.11/include/asm/arch/star_misc.h linux-2.6.35.11-ts7500/include/asm/arch/star_misc.h
+--- linux-2.6.35.11/include/asm/arch/star_misc.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_misc.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,402 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_MISC_H_
++#define _STAR_MISC_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define MISC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_MISC_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define MISC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_MISC_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define MISC_MEMORY_REMAP_REG MISC_MEM_MAP_VALUE(0x00)
++#define MISC_CHIP_CONFIG_REG MISC_MEM_MAP_VALUE(0x04)
++#define MISC_DEBUG_PROBE_DATA_REG MISC_MEM_MAP_VALUE(0x08)
++#define MISC_DEBUG_PROBE_SELECTION_REG MISC_MEM_MAP_VALUE(0x0C)
++#define MISC_PCI_CONTROL_BROKEN_MASK_REG MISC_MEM_MAP_VALUE(0x10)
++#define MISC_PCI_BROKEN_STATUS_REG MISC_MEM_MAP_VALUE(0x14)
++#define MISC_PCI_DEVICE_VENDOR_ID_REG MISC_MEM_MAP_VALUE(0x18)
++#define MISC_USB_HOST_PHY_CONTROL_TEST_REG MISC_MEM_MAP_VALUE(0x1C)
++#define MISC_GPIOA_PIN_ENABLE_REG MISC_MEM_MAP_VALUE(0x20)
++#define MISC_GPIOB_PIN_ENABLE_REG MISC_MEM_MAP_VALUE(0x24)
++#define MISC_GPIOA_RESISTOR_CONFIG_REG MISC_MEM_MAP_VALUE(0x28)
++#define MISC_GPIOA_DRIVE_STRENGTH_CONFIG_REG MISC_MEM_MAP_VALUE(0x2C)
++#define MISC_FAST_ETHERNET_PHY_CONFIG_REG MISC_MEM_MAP_VALUE(0x30)
++#define MISC_SOFTWARE_TEST_1_REG MISC_MEM_MAP_VALUE(0x38)
++#define MISC_SOFTWARE_TEST_2_REG MISC_MEM_MAP_VALUE(0x3C)
++
++#define MISC_E_FUSE_0_REG MISC_MEM_MAP_VALUE(0x60)
++#define MISC_E_FUSE_1_REG MISC_MEM_MAP_VALUE(0x64)
++
++
++/*
++ * define constants macros
++ */
++#define MISC_PARALLEL_FLASH_BOOT (0)
++#define MISC_SPI_SERIAL_FLASH_BOOT (1)
++
++#define MISC_LITTLE_ENDIAN (0)
++#define MISC_BIG_ENDIAN (1)
++
++#define MISC_FARADAY_ICE (0)
++#define MISC_ARM_ICE (1)
++
++#define MISC_EXT_INT29_PINS ((0x1 << 0))
++#define MISC_EXT_INT30_PINS ((0x1 << 1))
++#define MISC_EXT_INT31_PINS ((0x1 << 2))
++#define MISC_I2C_PINS ((0x1 << 13) | (0x1 << 14))
++#define MISC_I2S_PINS ((0x1 << 15) | (0x1 << 16) | (0x1 << 17))
++#define MISC_PCM_PINS ((0x1 << 18) | (0x1 << 19) | (0x1 << 20) | (0x1 << 21))
++#define MISC_LED0_PINS ((0x1 << 22))
++#define MISC_LED1_PINS ((0x1 << 23))
++#define MISC_LED2_PINS ((0x1 << 24))
++#define MISC_LED012_PINS ((0x1 << 22) | (0x1 << 23) | (0x1 << 24))
++#define MISC_WDTIMER_RESET_PINS ((0x1 << 25))
++#define MISC_SPI_PINS ((0x1 << 26) | (0x1 << 27) | (0x1 << 28) | (0x1 << 29) | (0x1 << 30) | (0x1 << 31))
++#define MISC_MDC_MDIO_PINS ((0x1 << 0) | (0x1 << 1))
++#define MISC_NIC_COL_PINS ((0x1 << 2))
++#define MISC_IDE_PINS ((0xFF << 3))
++#define MISC_SRAM_BANK1_PINS ((0x1 << 11) | (0x1 << 14))
++#define MISC_SRAM_BANK2_PINS ((0x1 << 12) | (0x1 << 15))
++#define MISC_SRAM_BANK3_PINS ((0x1 << 13) | (0x1 << 16))
++#define MISC_PCMCIA_PINS ((0x1 << 17) | (0x1 << 18) | (0x1 << 19) | (0x1 << 20))
++#define MISC_UART1_PINS ((0x1 << 21) | (0x1 << 22))
++#define MISC_PCI_PINS (((u32)0x1FF << 23))
++
++#define MISC_UART0_ACT0_Pin (0x1 << 2)
++#define MISC_UART1_ACT1_Pin (0x1 << 3)
++
++#define MISC_GPIOA_PIN_0 (0)
++#define MISC_GPIOA_PIN_1 (1)
++#define MISC_GPIOA_PIN_2 (2)
++#define MISC_GPIOA_PIN_3 (3)
++#define MISC_GPIOA_PIN_4 (4)
++#define MISC_GPIOA_PIN_5 (5)
++#define MISC_GPIOA_PIN_6 (6)
++#define MISC_GPIOA_PIN_7 (7)
++#define MISC_GPIOA_PIN_8 (8)
++#define MISC_GPIOA_PIN_9 (9)
++#define MISC_GPIOA_PIN_10 (10)
++
++#define MISC_GPIOA_75K_RESISTOR_PULL_DOWN (1)
++#define MISC_GPIOA_75K_RESISTOR_PULL_UP (2)
++#define MISC_GPIOA_75K_RESISTOR_PULL_KEEPER (3)
++
++#define MISC_GPIOA_DRIVE_STRENGTH_4MA (0)
++#define MISC_GPIOA_DRIVE_STRENGTH_8MA (1)
++
++
++/*
++ * macro declarations
++ */
++#define HAL_MISC_ENABLE_SPI_SERIAL_FLASH_BANK_ACCESS() \
++{ \
++ (MISC_CHIP_CONFIG_REG) |= (0x1 << 4); \
++}
++
++#define HAL_MISC_DISABLE_SPI_SERIAL_FLASH_BANK_ACCESS() \
++{ \
++ (MISC_CHIP_CONFIG_REG) &= ~(0x1 << 4); \
++}
++
++
++/*
++ * Macro defines for GPIOA and GPIOB Pin Enable Register
++ */
++#define HAL_MISC_ENABLE_EXT_INT29_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_EXT_INT29_PINS); \
++}
++
++#define HAL_MISC_DISABLE_EXT_INT29_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_EXT_INT29_PINS); \
++}
++
++#define HAL_MISC_ENABLE_EXT_INT30_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_EXT_INT30_PINS); \
++}
++
++#define HAL_MISC_DISABLE_EXT_INT30_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_EXT_INT30_PINS); \
++}
++
++#define HAL_MISC_ENABLE_I2C_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_I2C_PINS); \
++}
++
++#define HAL_MISC_DISABLE_I2C_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_I2C_PINS); \
++}
++
++#define HAL_MISC_ENABLE_I2S_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_I2S_PINS); \
++}
++
++#define HAL_MISC_DISABLE_I2S_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_I2S_PINS); \
++}
++
++#define HAL_MISC_ENABLE_PCM_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_PCM_PINS); \
++}
++
++#define HAL_MISC_DISABLE_PCM_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_PCM_PINS); \
++}
++
++#define HAL_MISC_ENABLE_LED0_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_LED0_PINS); \
++}
++
++#define HAL_MISC_DISABLE_LED0_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_LED0_PINS); \
++}
++
++#define HAL_MISC_ENABLE_LED1_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_LED1_PINS); \
++}
++
++#define HAL_MISC_DISABLE_LED1_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_LED1_PINS); \
++}
++
++#define HAL_MISC_ENABLE_LED2_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_LED2_PINS); \
++}
++
++#define HAL_MISC_DISABLE_LED2_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_LED2_PINS); \
++}
++
++#define HAL_MISC_ENABLE_LED012_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_LED012_PINS); \
++}
++
++#define HAL_MISC_DISABLE_LED012_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_LED012_PINS); \
++}
++
++#define HAL_MISC_ENABLE_WDTIMER_RESET_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_WDTIMER_RESET_PINS); \
++}
++
++#define HAL_MISC_DISABLE_WDTIMER_RESET_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_WDTIMER_RESET_PINS); \
++}
++
++#define HAL_MISC_ENABLE_SPI_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_SPI_PINS); \
++}
++
++#define HAL_MISC_DISABLE_SPI_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_SPI_PINS); \
++}
++
++#define HAL_MISC_ENABLE_UART0_ACT0_PIN() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_UART0_ACT0_Pin); \
++}
++
++#define HAL_MISC_DISABLE_UART0_ACT0_PIN() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_UART0_ACT0_Pin); \
++}
++
++#define HAL_MISC_ENABLE_UART1_ACT1_PIN() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) |= (MISC_UART1_ACT1_Pin); \
++}
++
++#define HAL_MISC_DISABLE_UART1_ACT1_PIN() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) &= ~(MISC_UART1_ACT1_Pin); \
++}
++
++#define HAL_MISC_ENABLE_MDC_MDIO_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_MDC_MDIO_PINS); \
++}
++
++#define HAL_MISC_DISABLE_MDC_MDIO_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_MDC_MDIO_PINS); \
++}
++
++#define HAL_MISC_ENABLE_NIC_COL_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_NIC_COL_PINS); \
++}
++
++#define HAL_MISC_DISABLE_NIC_COL_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_NIC_COL_PINS); \
++}
++
++#define HAL_MISC_ENABLE_IDE_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_IDE_PINS); \
++}
++
++#define HAL_MISC_DISABLE_IDE_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_IDE_PINS); \
++}
++
++#define HAL_MISC_ENABLE_SRAM_BANK1_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_SRAM_BANK1_PINS); \
++}
++
++#define HAL_MISC_DISABLE_SRAM_BANK1_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_SRAM_BANK1_PINS); \
++}
++
++#define HAL_MISC_ENABLE_SRAM_BANK2_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_SRAM_BANK2_PINS); \
++}
++
++#define HAL_MISC_DISABLE_SRAM_BANK2_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_SRAM_BANK2_PINS); \
++}
++
++#define HAL_MISC_ENABLE_SRAM_BANK3_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_SRAM_BANK3_PINS); \
++}
++
++#define HAL_MISC_DISABLE_SRAM_BANK3_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_SRAM_BANK3_PINS); \
++}
++
++#define HAL_MISC_ENABLE_PCMCIA_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_PCMCIA_PINS); \
++}
++
++#define HAL_MISC_DISABLE_PCMCIA_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_PCMCIA_PINS); \
++}
++
++#define HAL_MISC_ENABLE_UART1_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_UART1_PINS); \
++}
++
++#define HAL_MISC_DISABLE_UART1_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_UART1_PINS); \
++}
++
++#define HAL_MISC_ENABLE_PCI_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) |= (MISC_PCI_PINS); \
++}
++
++#define HAL_MISC_DISABLE_PCI_PINS() \
++{ \
++ (MISC_GPIOB_PIN_ENABLE_REG) &= ~(MISC_PCI_PINS); \
++}
++
++#define HAL_MISC_ENABLE_ALL_SHARED_GPIO_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) = (0x0); \
++ (MISC_GPIOB_PIN_ENABLE_REG) = (0x0); \
++}
++
++#define HAL_MISC_DISABLE_ALL_SHARED_GPIO_PINS() \
++{ \
++ (MISC_GPIOA_PIN_ENABLE_REG) = (0xFFFFFFFF); \
++ (MISC_GPIOB_PIN_ENABLE_REG) = (0xFFFFFFFF); \
++}
++
++#define HAL_MISC_CONFIGURE_GPIOA_RESISTOR(pin_index, value) \
++{ \
++ (MISC_GPIOA_RESISTOR_CONFIG_REG) &= ~(0x3 << (2 * pin_index)); \
++ (MISC_GPIOA_RESISTOR_CONFIG_REG) |= ((value & 0x3) << (2 * pin_index)); \
++}
++
++#define HAL_MISC_CONFIGURE_GPIOA_DRIVE_STRENGTH(pin_index, value) \
++{ \
++ (MISC_GPIOA_DRIVE_STRENGTH_CONFIG_REG) &= ~(0x1 << pin_index); \
++ (MISC_GPIOA_DRIVE_STRENGTH_CONFIG_REG) |= (value << pin_index); \
++}
++
++#define HAL_MISC_SELECT_FAST_ETHERNET_PHY_LED_MODE0() \
++{ \
++ (MISC_FAST_ETHERNET_PHY_CONFIG_REG) = (0x0); \
++}
++
++#define HAL_MISC_SELECT_FAST_ETHERNET_PHY_LED_MODE1() \
++{ \
++ (MISC_FAST_ETHERNET_PHY_CONFIG_REG) = (0x1); \
++}
++
++#define HAL_MISC_SELECT_FAST_ETHERNET_PHY_LED_MODE2() \
++{ \
++ (MISC_FAST_ETHERNET_PHY_CONFIG_REG) = (0x2); \
++}
++
++#define HAL_MISC_SELECT_FAST_ETHERNET_PHY_LED_MODE3() \
++{ \
++ (MISC_FAST_ETHERNET_PHY_CONFIG_REG) = (0x3); \
++}
++
++
++#endif // end of #ifndef _STAR_MISC_H_
+diff -rupN linux-2.6.35.11/include/asm/arch/star_nic.h linux-2.6.35.11-ts7500/include/asm/arch/star_nic.h
+--- linux-2.6.35.11/include/asm/arch/star_nic.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_nic.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,346 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_NIC_H_
++#define _STAR_NIC_H_
++
++
++#include <asm/arch/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define NIC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_NIC_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define NIC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_NIC_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define NIC_PHY_CONTROL_REG0 NIC_MEM_MAP_VALUE(0x000)
++#define NIC_PHY_CONTROL_REG1 NIC_MEM_MAP_VALUE(0x004)
++
++#define NIC_MAC_CONTROL_REG NIC_MEM_MAP_VALUE(0x008)
++#define NIC_FLOW_CONTROL_CONFIG_REG NIC_MEM_MAP_VALUE(0x00C)
++
++#define NIC_ARL_CONFIG_REG NIC_MEM_MAP_VALUE(0x010)
++
++#define NIC_MY_MAC_HIGH_BYTE_REG NIC_MEM_MAP_VALUE(0x014)
++#define NIC_MY_MAC_LOW_BYTE_REG NIC_MEM_MAP_VALUE(0x018)
++
++#define NIC_HASH_TABLE_CONTROL_REG NIC_MEM_MAP_VALUE(0x01C)
++
++#define NIC_MY_VLANID_CONTROL_REG NIC_MEM_MAP_VALUE(0x020)
++
++#define NIC_MY_VLANID_0_1 NIC_MEM_MAP_VALUE(0x024)
++#define NIC_MY_VLANID_2_3 NIC_MEM_MAP_VALUE(0x028)
++
++#define NIC_DMA_CONFIG_REG NIC_MEM_MAP_VALUE(0x030)
++#define NIC_TX_DMA_CONTROL_REG NIC_MEM_MAP_VALUE(0x034)
++#define NIC_RX_DMA_CONTROL_REG NIC_MEM_MAP_VALUE(0x038)
++#define NIC_TX_DESC_PTR_REG NIC_MEM_MAP_VALUE(0x03C)
++#define NIC_RX_DESC_PTR_REG NIC_MEM_MAP_VALUE(0x040)
++
++#define NIC_TX_DESC_BASE_ADDR_REG NIC_MEM_MAP_VALUE(0x044)
++#define NIC_RX_DESC_BASE_ADDR_REG NIC_MEM_MAP_VALUE(0x048)
++#define NIC_DELAYED_INT_CONFIG_REG NIC_MEM_MAP_VALUE(0x04C)
++
++#define NIC_INT_STATUS_REG NIC_MEM_MAP_VALUE(0x050)
++#define NIC_INT_MASK_REG NIC_MEM_MAP_VALUE(0x054)
++
++#define NIC_TEST_0_REG NIC_MEM_MAP_VALUE(0x058)
++#define NIC_TEST_1_REG NIC_MEM_MAP_VALUE(0x05C)
++
++#define NIC_MIB_RX_OK_PKT_CNTR NIC_MEM_MAP_VALUE(0x100)
++#define NIC_MIB_RX_OK_BYTE_CNTR NIC_MEM_MAP_VALUE(0x104)
++#define NIC_MIB_RX_RUNT_BYTE_CNTR NIC_MEM_MAP_VALUE(0x108)
++#define NIC_MIB_RX_OSIZE_DROP_PKT_CNTR NIC_MEM_MAP_VALUE(0x10C)
++
++#define NIC_MIB_RX_NO_BUF_DROP_PKT_CNTR NIC_MEM_MAP_VALUE(0x110)
++
++#define NIC_MIB_RX_CRC_ERR_PKT_CNTR NIC_MEM_MAP_VALUE(0x114)
++
++#define NIC_MIB_RX_ARL_DROP_PKT_CNTR NIC_MEM_MAP_VALUE(0x118)
++
++#define NIC_MIB_MYVLANID_MISMATCH_DROP_PKT_CNTR NIC_MEM_MAP_VALUE(0x11C)
++
++#define NIC_MIB_RX_CHKSUM_ERR_PKT_CNTR NIC_MEM_MAP_VALUE(0x120)
++
++#define NIC_MIB_RX_PAUSE_FRAME_PKT_CNTR NIC_MEM_MAP_VALUE(0x124)
++
++#define NIC_MIB_TX_OK_PKT_CNTR NIC_MEM_MAP_VALUE(0x128)
++#define NIC_MIB_TX_OK_BYTE_CNTR NIC_MEM_MAP_VALUE(0x12C)
++
++#define NIC_MIB_TX_COLLISION_CNTR NIC_MEM_MAP_VALUE(0x130)
++#define NIC_MIB_TX_PAUSE_FRAME_CNTR NIC_MEM_MAP_VALUE(0x130)
++
++#define NIC_MIB_TX_FIFO_UNDERRUN_RETX_CNTR NIC_MEM_MAP_VALUE(0x134)
++
++
++
++
++/*
++ * define constants macros
++ */
++
++#define NIC_PHY_ADDRESS 1 //the phy addr const value
++#define NIC_PHY_ID 0x0243 //the phy id
++
++#define GW_NIC_MAX_TFD_NUM (32)
++#define GW_NIC_MAX_RFD_NUM (32)
++#define MAX_BUFFERS (64)
++
++
++
++#define MMU_OFF (0)
++#define MMU_ON (1)
++#define OS_NULL (0)
++
++
++#define NET_BUFFER_PACKET_SIZE (512)
++#define NET_BUFFER_SHIFT_BIT_NUM (9) // 2*n9=512
++
++#define MAX_PACKET_LEN (1536)
++
++#define INTERNAL_LOOPBACK_MODE (1)
++#define SOFTWARE_REPEATER_MODE (2)
++
++#define TXTC_INT_BIT (0x08000000)
++#define TX_INSV_BIT (0x04000000)
++
++#define LS_BIT (0x10000000)
++#define FS_BIT (0x20000000)
++#define EOR_BIT (0x40000000)
++#define FS_LS_BIT (0x30000000)
++#define C_BIT (0x80000000)
++#define FS_LS_C_BIT (0xB0000000)
++#define FS_LS_INT_BIT (0x38000000)
++
++
++
++// HASH TABLE CONTROL REGISTER
++#define NIC_HASH_TABLE_BIST_DONE_BIT (0x1 << 17)
++#define NIC_HASH_TABLE_BIST_OK_BIT (0x1 << 16)
++#define NIC_HASH_COMMAND_START_BIT (0x1 << 14)
++#define NIC_HASH_COMMAND_BIT (0x1 << 13)
++#define NIC_HASH_BIT_DATA (0x1 << 12)
++#define NIC_HASH_BIT_ADDRESS_BIT (0x1ff)
++
++
++#define NIC_REG_CNT ((0x48 << 2) + 1)
++
++/*
++ * macro access
++ */
++
++#define GW_NIC_TX_TFD_NEXT(work_tfd_ptr) \
++ work_tfd_ptr = NIC_TX_TFD_Ring.head + (((u32)(work_tfd_ptr - NIC_TX_TFD_Ring.head) + 1) % GW_NIC_MAX_TFD_NUM)
++
++
++#define GW_NIC_TX_TFD_PREVIOUS(work_tfd_ptr) \
++ work_tfd_ptr = NIC_TX_TFD_Ring.head + ((GW_NIC_MAX_TFD_NUM + (u32)(work_tfd_ptr - NIC_TX_TFD_Ring.head) - 1) % GW_NIC_MAX_TFD_NUM)
++
++
++#define GW_NIC_RX_RFD_NEXT(work_rfd_ptr) \
++ work_rfd_ptr = NIC_RX_RFD_Ring.head + (((u32)(work_rfd_ptr - NIC_RX_RFD_Ring.head) + 1) % GW_NIC_MAX_RFD_NUM)
++
++
++#define GW_NIC_RX_RFD_PREVIOUS(work_rfd_ptr) \
++ work_rfd_ptr = NIC_RX_RFD_Ring.head + ((GW_NIC_MAX_RFD_NUM + (u32)(work_rfd_ptr - NIC_RX_RFD_Ring.head) - 1) % GW_NIC_MAX_RFD_NUM)
++
++
++/*
++ * PHY register defines
++ */
++#define PHY_MII_CONTROL_REG_ADDR 0x00
++#define PHY_MII_STATUS_REG_ADDR 0x01
++#define PHY_ID1_REG_ADDR 0x02
++#define PHY_ID2_REG_ADDR 0x03
++#define PHY_AN_ADVERTISEMENT_REG_ADDR 0x04
++#define PHY_AN_REAMOTE_CAP_REG_ADDR 0x05
++
++
++#define PHY_RESERVED1_REG_ADDR 0x10
++#define PHY_RESERVED2_REG_ADDR 0x11
++#define PHY_CH_STATUS_OUTPUT_REG_ADDR 0x12
++#define PHY_RESERVED3_REG_ADDR 0x13
++#define PHY_RESERVED4_REG_ADDR 0x14
++
++
++#define PHY_SPEC_CONTROL_REG_ADDR 0x16
++#define PHY_INTC_CONTROL_STATUS_REG_ADDR 0x17
++
++/*
++ * NIC registers access macros defines
++ */
++
++//0x004
++#define HAL_NIC_WRITE_PHY_CONTROL1(config_value) \
++ ((NIC_PHY_CONTROL_REG1) = (config_value))
++
++#define HAL_NIC_READ_PHY_CONTROL1(config_value) \
++ ((config_value) = (NIC_PHY_CONTROL_REG1))
++
++//0x008
++#define HAL_NIC_WRITE_MAC_CONFIGURATION(config_value) \
++ ((NIC_MAC_CONTROL_REG) = (config_value))
++
++#define HAL_NIC_READ_MAC_CONFIGURATION(config_value) \
++ ((config_value) = (NIC_MAC_CONTROL_REG))
++
++//0x00C
++#define HAL_NIC_WRITE_FLOW_CONTROL_CONFIG(fc_cfg) \
++ ((NIC_FLOW_CONTROL_CONFIG_REG) = (fc_cfg))
++
++#define HAL_NIC_READ_FLOW_CONTROL_CONFIG(fc_cfg) \
++ ((fc_cfg) = (NIC_FLOW_CONTROL_CONFIG_REG))
++
++//0x010
++#define HAL_NIC_WRITE_ARL_CONFIGURATION(cfg) \
++ ((NIC_ARL_CONFIG_REG) = (cfg))
++
++#define HAL_NIC_READ_ARL_CONFIGURATION(cfg) \
++ ((cfg) = (NIC_ARL_CONFIG_REG))
++
++//0x014,
++#define HAL_NIC_WRITE_MY_MAC_HIGH_BYTE(cfg) \
++ ((NIC_MY_MAC_HIGH_BYTE_REG) = (cfg & 0x0000FFFF ) )
++
++#define HAL_NIC_READ_MY_MAC_HIGH_BYTE(cfg) \
++ ((cfg) = (NIC_MY_MAC_HIGH_BYTE_REG & 0x0000FFFF ))
++
++//0x018
++#define HAL_NIC_WRITE_MY_MAC_LOW_BYTE(cfg) \
++ ((NIC_MY_MAC_LOW_BYTE_REG) = (cfg))
++
++#define HAL_NIC_READ_MY_MAC_LOW_BYTE(cfg) \
++ ((cfg) = (NIC_MY_MAC_LOW_BYTE_REG))
++
++//0x03C
++#define HAL_NIC_READ_INTERRUPT_STATUS(int_status) \
++ ((int_status) = (NIC_INT_STATUS_REG))
++
++#define HAL_NIC_CLEAR_ALL_INTERRUPT_STATUS_SOURCES()\
++ ((NIC_INT_STATUS_REG) = (0xFFFFFFFF))
++
++#define HAL_NIC_CLEAR_INTERRUPT_STATUS_SOURCES(source) \
++ ((NIC_INT_STATUS_REG) |= (source))
++
++#define HAL_NIC_CLEAR_INTERRUPT_STATUS_SOURCE_BIT(source_bit_index) \
++ ((NIC_INT_STATUS_REG) |= (1 << (source_bit_index)))
++
++//0x040
++#define HAL_NIC_DISABLE_ALL_INTERRUPT_STATUS_SOURCES() \
++ ((NIC_INT_MASK_REG) = (0xFFFFFFFF))
++
++#define HAL_NIC_ENABLE_ALL_INTERRUPT_STATUS_SOURCES() \
++ ((NIC_INT_MASK_REG) = (0x00000000))
++
++#define HAL_NIC_DISABLE_INTERRUPT_STATUS_SOURCE_BIT(source_bit_index) \
++ ((NIC_INT_MASK_REG) |= (1 << (source_bit_index)))
++
++#define HAL_NIC_ENABLE_INTERRUPT_STATUS_SOURCE_BIT(source_bit_index) \
++ ((NIC_INT_MASK_REG) &= ~(1 << (source_bit_index)))
++
++//0x44
++#define HAL_NIC_WRITE_TEST0_REG(cfg) \
++ ((NIC_TEST_0_REG) = (cfg))
++
++#define HAL_NIC_READ_TEST0_REG(cfg) \
++ ((cfg) = (NIC_TEST_0_REG))
++
++//0x48
++#define HAL_NIC_WRITE_TEST1_REG(cfg) \
++ ((NIC_TEST_1_REG) = (cfg))
++
++#define HAL_NIC_READ_TEST1_REG(cfg) \
++ ((cfg) = (NIC_TEST_1_REG))
++
++
++
++/*
++ * NIC's DMA macros defines
++ */
++#define HAL_NIC_TX_DMA_START() \
++ ((NIC_TX_DMA_CONTROL_REG) = (1))
++
++
++#define HAL_NIC_TX_DMA_STOP() \
++ ((NIC_TX_DMA_CONTROL_REG) = (0))
++
++
++#define HAL_NIC_READ_TX_DMA_STATE(state) \
++ ((state) = (NIC_TX_DMA_CONTROL_REG))
++
++
++#define HAL_NIC_RX_DMA_START() \
++ ((NIC_RX_DMA_CONTROL_REG) = (1))
++
++
++#define HAL_NIC_RX_DMA_STOP() \
++ ((NIC_RX_DMA_CONTROL_REG) = (0))
++
++
++#define HAL_NIC_WRITE_TXSD(tssd_value) \
++ ((NIC_TX_DESC_PTR_REG) = (tssd_value))
++
++
++#define HAL_NIC_READ_TXSD(tssd_value) \
++ ((tssd_value) = (NIC_TX_DESC_PTR_REG))
++
++
++#define HAL_NIC_WRITE_RXSD(fssd_value) \
++ ((NIC_RX_DESC_PTR_REG) = (fssd_value))
++
++
++#define HAL_NIC_READ_RXSD(fssd_value) \
++ ((fssd_value) = (NIC_RX_DESC_PTR_REG))
++
++
++#define HAL_NIC_WRITE_TX_BASE(ts_base_value) \
++ ((NIC_TX_DESC_BASE_ADDR_REG) = (ts_base_value))
++
++
++#define HAL_NIC_READ_TX_BASE(ts_base_value) \
++ ((ts_base_value) = (NIC_TX_DESC_BASE_ADDR_REG))
++
++
++#define HAL_NIC_WRITE_RX_BASE(fs_base_value) \
++ ((NIC_RX_DESC_BASE_ADDR_REG) = (fs_base_value))
++
++
++#define HAL_NIC_READ_RX_BASE(fs_base_value) \
++ ((fs_base_value) = (NIC_RX_DESC_BASE_ADDR_REG))
++
++
++#define HAL_NIC_WRITE_DELAYED_INTERRUPT_CONFIG(delayed_interrupt_config) \
++ ((NIC_DELAYED_INT_CONFIG_REG) = (delayed_interrupt_config))
++
++
++#define HAL_NIC_READ_DELAYED_INTERRUPT_CONFIG(delayed_interrupt_config) \
++ ((delayed_interrupt_config) = (NIC_DELAYED_INT_CONFIG_REG))
++
++#endif // end of #ifndef _STAR_NIC_H_
+diff -rupN linux-2.6.35.11/include/asm/arch/star_pci_bridge.h linux-2.6.35.11-ts7500/include/asm/arch/star_pci_bridge.h
+--- linux-2.6.35.11/include/asm/arch/star_pci_bridge.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_pci_bridge.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,132 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_PCI_DRIDGE_H_
++#define _STAR_PCI_DRIDGE_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#define PCI_IO_SPACE_BASE_ADDR (SYSPA_PCI_IO_SPACE_BASE_ADDR)
++#define PCI_IO_SPACE_SIZE 0x08000000 /* 64MB */
++#define PCI_IO_SPACE_START PCI_IO_SPACE_BASE_ADDR
++#define PCI_IO_SPACE_END (PCI_IO_SPACE_BASE_ADDR + PCI_IO_SPACE_SIZE - 1)
++#define PCI_MEMORY_SPACE_BASE_ADDR (SYSPA_PCI_MEMORY_SPACE_BASE_ADDR)
++#define PCI_MEMORY_SPACE_SIZE 0x10000000 /* 256MB */
++#define PCI_NPREFETCH_MEMORY_SPACE_START PCI_MEMORY_SPACE_BASE_ADDR
++#define PCI_NPREFETCH_MEMORY_SPACE_SIZE 0x00800000 /* 8MB */
++#define PCI_NPREFETCH_MEMORY_SPACE_END (PCI_NPREFETCH_MEMORY_SPACE_START + PCI_NPREFETCH_MEMORY_SPACE_SIZE - 1)
++#define PCI_PREFETCH_MEMORY_SPACE_START (PCI_NPREFETCH_MEMORY_SPACE_START + PCI_NPREFETCH_MEMORY_SPACE_SIZE)
++#define PCI_PREFETCH_MEMORY_SPACE_SIZE 0x00800000 /* 8MB */
++#define PCI_PREFETCH_MEMORY_SPACE_END (PCI_PREFETCH_MEMORY_SPACE_START + PCI_PREFETCH_MEMORY_SPACE_SIZE - 1)
++
++
++#if defined(__UBOOT__)
++#define PCIB_MEM_MAP_VALUE(base, reg_offset) (*((u32 volatile *)(SYSPA_PCI_##base##_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define PCIB_MEM_MAP_VALUE(base, reg_offset) (*((u32 volatile *)(SYSVA_PCI_##base##_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define PCI_BRIDGE_CONFIG_DATA PCIB_MEM_MAP_VALUE(CONFIG_DATA_BASE, 0x2C)
++#define PCI_BRIDGE_CONFIG_ADDR PCIB_MEM_MAP_VALUE(CONFIG_ADDR_BASE, 0x28)
++
++#define PCI_BRIDGE_CONFIG_DATA_REG_OFFSET 0x2C
++#define PCI_BRIDGE_CONFIG_ADDR_REG_OFFSET 0x28
++
++/*
++ * define constants macros
++ */
++#define PCIB_BUS_CLOCK_33M 1
++
++#define PCIB_BUS_CLOCK_66M 2
++
++#define PCIB_DEVICE_ID 0x8131
++
++#define PCIB_VENDOR_ID 0xEEEE
++
++#define PCIB_CLASS_CODE 0xFF0000
++
++#define PCIB_REVISION_ID 0x00
++
++#define PCIB_BAR0_MEMORY_SPACE_BASE 0x20000000
++
++#define PCIB_BAR1_IO_SPACE_BASE 0x20000000
++
++
++#define PCI_MEMORY_SPACE_BASE 0xB0000000
++
++#define PCI_IO_SPACE_BASE 0xA8000000
++
++
++#define PCI_MAX_BUS_NUM 0x01
++#define PCI_MAX_DEVICE_NUM 0x14
++#define PCI_MAX_FUNCTION_NUM 0x01
++#define PCI_MAX_REG_NUM 0x3C
++
++
++#define PCI_MAX_DEVICE_TYPE_NUM 0x13
++#define PCI_MAX_BAR_NUM 0x06
++
++
++#define PCI_CSH_VENDOR_ID_REG_ADDR 0x00
++#define PCI_CSH_DEVICE_ID_REG_ADDR 0x02
++#define PCI_CSH_COMMAND_REG_ADDR 0x04
++#define PCI_CSH_STATUS_REG_ADDR 0x06
++#define PCI_CSH_REVISION_CLASS_REG_ADDR 0x08
++#define PCI_CSH_CACHE_LINE_SIZE_REG_ADDR 0x0C
++#define PCI_CSH_LATENCY_TIMER_REG_ADDR 0x0D
++#define PCI_CSH_HEADER_TYPE_REG_ADDR 0x0E
++#define PCI_CSH_BIST_REG_ADDR 0x0F
++#define PCI_CSH_BAR_REG_ADDR 0x10
++
++
++#define PCI_IO_SPACE_SIZE_1M 0x00
++#define PCI_IO_SPACE_SIZE_2M 0x01
++#define PCI_IO_SPACE_SIZE_4M 0x02
++#define PCI_IO_SPACE_SIZE_8M 0x03
++#define PCI_IO_SPACE_SIZE_16M 0x04
++#define PCI_IO_SPACE_SIZE_32M 0x05
++#define PCI_IO_SPACE_SIZE_64M 0x06
++#define PCI_IO_SPACE_SIZE_128M 0x07
++#define PCI_IO_SPACE_SIZE_256M 0x08
++#define PCI_IO_SPACE_SIZE_512M 0x09
++#define PCI_IO_SPACE_SIZE_1G 0x0A
++#define PCI_IO_SPACE_SIZE_2G 0x0B
++
++
++#define PCI_MEMORY_SPACE_TYPE 0
++#define PCI_IO_SPACE_TYPE 1
++
++#define PCI_BROKEN_FLAG 1
++#define PCI_AHB2PCIB_FLAG 2
++
++
++#endif // end of #ifndef _STAR_PCI_DRIDGE_H_
++
+diff -rupN linux-2.6.35.11/include/asm/arch/star_pcmcia_bridge.h linux-2.6.35.11-ts7500/include/asm/arch/star_pcmcia_bridge.h
+--- linux-2.6.35.11/include/asm/arch/star_pcmcia_bridge.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_pcmcia_bridge.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,231 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_PCMCIA_DRIDGE_H_
++#define _STAR_PCMCIA_DRIDGE_H_
++
++/******************************************************************************
++ * MODULE NAME: star_pcmcia_bridge.h
++ * PROJECT CODE: Equuleus
++ * DESCRIPTION:
++ * MAINTAINER: Eric Yang
++ * DATE: 15 September 2005
++ *
++ * SOURCE CONTROL:
++ *
++ * LICENSE:
++ * This source code is copyright (c) 2005 Star Semi Inc.
++ * All rights reserved.
++ *
++ * REVISION HISTORY:
++ * 15 September 2005 - Eric Yang - Initial Version v1.0
++ *
++ *
++ * SOURCE:
++ * ISSUES:
++ * NOTES TO USERS:
++ ******************************************************************************/
++
++#include "star_sys_memory_map.h"
++
++
++#if defined(__UBOOT__)
++#define PCMCIA_BRIDGE_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_PCMCIA_CONTROL_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define PCMCIA_BRIDGE_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_PCMCIA_CONTROL_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define PCMCIA_CONFIGURATION_REG PCMCIA_BRIDGE_MEM_MAP_VALUE(0x20)
++#define PCMCIA_MEMORY_ACCESS_TIMING_PARAM_REG PCMCIA_BRIDGE_MEM_MAP_VALUE(0x24)
++#define PCMCIA_IO_ACCESS_TIMING_PARAM_REG PCMCIA_BRIDGE_MEM_MAP_VALUE(0x28)
++
++
++#define PCMCIA_ATTRIBUTE_MEMORY_SPACE_BASE_ADDR (SYSPA_PCMCIA_ATTRIBUTE_MEMORY_BASE_ADDR)
++#define PCMCIA_COMMOM_MEMORY_SPACE_BASE_ADDR (SYSPA_PCMCIA_COMMON_MEMORY_BASE_ADDR)
++#define PCMCIA_IO_SPACE_BASE_ADDR (SYSPA_PCMCIA_IO_SPACE_BASE_ADDR)
++
++
++
++/*
++ * define constants macros
++ */
++#define PCMCIA_DATA_BUS_WIDTH_8 (0)
++
++#define PCMCIA_DATA_BUS_WIDTH_16 (1)
++
++
++/*
++ * Flags for PCMCIA_STATUS
++ */
++#define FLAG_STATUS_BVD1 0x01
++#define FLAG_STATUS_STSCHG 0x01
++#define FLAG_STATUS_BVD2 0x02
++#define FLAG_STATUS_SPKR 0x02
++#define FLAG_STATUS_DETECT 0xf3 /* bit 2=0,3=0 ,0x0c bit 2=1,3=1 */
++#define FLAG_STATUS_WRPROT 0x10
++#define FLAG_STATUS_READY 0x20
++#define FLAG_STATUS_INPACK 0x40
++
++
++/*
++ * Flags for PCMCIA_CSC
++ */
++#define FLAG_CSC_BVD1 0x01
++#define FLAG_CSC_BVD2 0x02
++#define FLAG_CSC_READY 0x04
++#define FLAG_CSC_INPACK 0x08
++#define FLAG_CSC_STSCHG 0x10
++#define FLAG_CSC_CARDINT 0x20
++#define FLAG_CSC_DETECT 0x40
++#define FLAG_CSC_SWCDC 0x80
++
++
++/*
++ * Flags for PCMCIA_POWER
++ */
++#define FLAG_POWER_OFF 0x00 /* Turn off the socket */
++#define FLAG_POWER_3V 0x01 /* 1:Vcc = 3.3v 0:Vcc = 5.0v */
++#define FLAG_POWER_SWH 0x02 /* Direct 5V/3V switch enable */
++#define FLAG_POWER_CTL 0x10 /* Socket power control */
++#define FLAG_POWER_AUTO 0x20 /* Auto power switch enable */
++#define FLAG_POWER_OUTENA 0x40 /* Output enable */
++
++
++/*
++ * Flags for PCMCIA_GBLCTL
++ */
++#define FLAG_GBLCTL_PWRDOWN 0x01
++#define FLAG_GBLCTL_WBACK 0x02
++#define FLAG_GBLCTL_16BITS 0x04
++#define FLAG_GBLCTL_IOCARD 0x08
++#define FLAG_GBLCTL_SWCDINT 0x10
++#define FLAG_GBLCTL_RESET 0x20
++
++
++/*
++ * Flags for PCMCIA_INTCFG
++ */
++#define FLAG_INTCFG_BDEAD 0x01
++#define FLAG_INTCFG_BWARN 0x02
++#define FLAG_INTCFG_READY 0x04
++#define FLAG_INTCFG_INPACK 0x08
++#define FLAG_INTCFG_LEVEL 0x10
++#define FLAG_INTCFG_FEDGE 0x20
++#define FLAG_INTCFG_REDGE 0x30
++#define FLAG_INTCFG_DETECT 0x40
++#define FLAG_INTCFG_STSCHG 0x80
++
++
++/*
++ * Definitions for Card Status flags for GetStatus
++ */
++#define STATUS_BATDEAD 0x0001
++#define STATUS_BATWARN 0x0002
++#define STATUS_DETECT 0x0004
++#define STATUS_WRPROT 0x0008
++#define STATUS_READY 0x0010
++#define STATUS_INPACK 0x0020
++#define STATUS_STSCHG 0x0040 /* just for CSC */
++#define SOFTWARE_STATUS_DETECT 0x0040 /* just for CSC */
++
++
++/*
++ * Set Socket configuration flags
++ */
++#define SS_PWR_AUTO 0x0001
++#define SS_PWR_SWH 0x0002
++#define SS_PWR_SEL 0x0004
++#define SS_POWER_ON 0x0008
++#define SS_OUTPUT_ENA 0x0010
++#define SS_IOCARD 0x0020
++#define SS_RESET 0x0040
++#define SS_WBACK 0x0080
++#define SS_16BITS 0x0100
++#define SS_PWR_DOWN_MODE 0x0200
++#define SS_SWCDINT 0x0400
++
++
++/*
++ * Set Interrupt Configuration flags
++ */
++#define INTR_BATDEAD 0x0001
++#define INTR_BATWARN 0x0002
++#define INTR_READY 0x0004
++#define INTR_INPACK 0x0008
++#define INTR_CARDINT 0x0010
++#define INTR_DETECT 0x0020
++#define INTR_STSCHG 0x0040
++
++
++/*
++ * tuple code
++ */
++#define CISTPL_NULL 0x00
++#define CISTPL_DEVICE 0x01
++#define CISTPL_NO_LINK 0x14
++#define CISTPL_VERS_1 0x15
++#define CISTPL_CONFIG 0x1a
++#define CISTPL_CFTABLE_ENTRY 0x1b
++#define CISTPL_MANFID 0x20
++#define CISTPL_END 0xff
++
++
++/*
++ * Return codes
++ */
++#define CS_SUCCESS 0x00
++#define CS_UNSUPPORTED_FUNCTION 0x15
++#define CS_NO_MORE_ITEMS 0x1f
++#define CS_BAD_TUPLE 0x40
++
++
++/*
++ * Attributes for tuple calls
++ */
++#define TUPLE_RETURN_LINK 0x01
++#define TUPLE_RETURN_COMMON 0x02
++
++#define RETURN_FIRST_TUPLE 0xff
++
++
++/*
++ * macro declarations
++ */
++#define HAL_PCMCIA_ENABLE_PCMCIA_CONTROLLER() \
++{ \
++ (PCMCIA_CONFIGURATION_REG) |= (0x1 << 1); \
++}
++
++#define HAL_PCMCIA_DISABLE_PCMCIA_CONTROLLER() \
++{ \
++ (PCMCIA_CONFIGURATION_REG) &= ~(0x1 << 1); \
++}
++
++
++#endif // end of #ifndef _STAR_PCMCIA_DRIDGE_H_
+diff -rupN linux-2.6.35.11/include/asm/arch/star_pcm.h linux-2.6.35.11-ts7500/include/asm/arch/star_pcm.h
+--- linux-2.6.35.11/include/asm/arch/star_pcm.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_pcm.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,277 @@
++/******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_PCM_H_
++#define _STAR_PCM_H_
++
++/******************************************************************************
++ * MODULE NAME: star_pcm.h
++ * PROJECT CODE: Orion
++ * DESCRIPTION:
++ * MAINTAINER: MJLIU
++ * DATE: 15 September 2005
++ *
++ * SOURCE CONTROL:
++ *
++ * LICENSE:
++ * This source code is copyright (c) 2005 Star Semi Inc.
++ * All rights reserved.
++ *
++ * REVISION HISTORY:
++ * 15 September 2005 - MJLIU - Initial Version v1.0
++ *
++ *
++ * SOURCE:
++ * ISSUES:
++ * NOTES TO USERS:
++ ******************************************************************************/
++
++#include <mach/star_sys_memory_map.h>
++
++#define PCM_BASE_ADDR (SYSVA_PCM_BASE_ADDR)
++#define PCM_MEM_MAP_ADDR(reg_offset) (PCM_BASE_ADDR + reg_offset)
++#define PCM_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)PCM_MEM_MAP_ADDR(reg_offset)))
++
++
++/*
++ * define access macros
++ */
++#define PCM_CONFIGURATION_0_REG PCM_MEM_MAP_VALUE(0x80)
++#define PCM_CONFIGURATION_1_REG PCM_MEM_MAP_VALUE(0x84)
++
++#define PCM_CHANNEL_0_CONFIG_REG PCM_MEM_MAP_VALUE(0x88)
++#define PCM_CHANNEL_1_CONFIG_REG PCM_MEM_MAP_VALUE(0x8C)
++#define PCM_CHANNEL_2_CONFIG_REG PCM_MEM_MAP_VALUE(0x90)
++#define PCM_CHANNEL_3_CONFIG_REG PCM_MEM_MAP_VALUE(0x94)
++
++#define PCM_TX_DATA_31_0_REG PCM_MEM_MAP_VALUE(0x98)
++#define PCM_TX_DATA_63_32_REG PCM_MEM_MAP_VALUE(0x9C)
++
++#define PCM_RX_DATA_31_0_REG PCM_MEM_MAP_VALUE(0xA0)
++#define PCM_RX_DATA_63_32_REG PCM_MEM_MAP_VALUE(0xA4)
++
++#define PCM_INTERRUPT_STATUS_REG PCM_MEM_MAP_VALUE(0xA8)
++#define PCM_INTERRUPT_ENABLE_REG PCM_MEM_MAP_VALUE(0xAC)
++
++
++
++/*
++ * define constants macros
++ */
++#define CH0_BIT_INDEX (0x1)
++#define CH1_BIT_INDEX (0x2)
++#define CH2_BIT_INDEX (0x4)
++#define CH3_BIT_INDEX (0x8)
++
++#define PCM_RXBUF_FULL_FG (0x1)
++#define PCM_TXBUF_EMPTY_FG (0x2)
++#define PCM_RXBUF_OVERRUN_FG (0x4)
++#define PCM_TXBUF_UNDERRUN_FG (0x8)
++
++#define PCM_ENABLE_FG (0x1 << 23)
++
++#define PCM_IDL_MODE (0)
++#define PCM_GCI_MODE (1)
++
++#define PCM_DATA_BIT_8 (0)
++#define PCM_DATA_BIT_16 (1)
++
++
++/*
++ * Set Commands Variables
++ */
++#define Software_Reset (0x02)
++#define Hardware_Reset (0x04)
++#define Write_Transmit_Time_Slot (0x40)
++#define Read_Transmit_Time_Slot (0x41)
++#define Write_Receive_Time_Slot (0x42)
++#define Read_Receive_Time_Slot (0x43)
++#define Write_Tx_Rx_CLK_Slot_Tx_CLK_Edge (0x44)
++#define Read_Tx_Rx_CLK_Slot_Tx_CLK_Edge (0x45)
++#define Write_Device_Configure_Reg (0x46)
++#define Read_Device_Configure_Reg (0x47)
++#define Write_Channel_Enable_Operating_Mode_Reg (0x4A)
++#define Read_Channel_Enable_Operating_Mode_Reg (0x4B)
++#define Read_Signal_Reg (0x4D)
++#define Input_Data_Reg (0x52)
++#define Output_Data_Reg (0x53)
++#define Input_Direction_Reg (0x54)
++#define Output_Direction_Reg (0x55)
++#define Write_System_State (0x56)
++#define Read_System_State (0x57)
++#define Write_Operating_Functon (0x60)
++#define Read_Operating_Functon (0x61)
++#define Write_System_State_Config (0x68)
++#define Read_System_State_Config (0x69)
++#define Write_Interrupt_Mask_Reg (0x6C)
++#define Read_Interrupt_Mask_Reg (0x6D)
++#define Write_Operating_Condition (0x70)
++#define Write_Loop_Supervision_Parameter (0xC2)
++#define Write_DC_Feed_Parameter (0xC6)
++#define Write_Signal_A_B_Parameter (0xD2)
++#define Write_Switching_Reg_Parameter (0xE4)
++#define Write_Switching_Reg_Control (0xE6)
++
++
++/*
++ * define data structure
++ */
++typedef struct _PCM_CHANNEL_OBJECT_ PCM_CHANNEL_OBJECT_T;
++
++struct _PCM_CHANNEL_OBJECT_
++{
++ u16 channel_0_tx_data;
++ u16 channel_0_rx_data;
++ u32 channel_0_data_width; /* 0 : 8-bit, 1 : 16-bit */
++
++ u16 channel_1_tx_data;
++ u16 channel_1_rx_data;
++ u32 channel_1_data_width;
++
++ u16 channel_2_tx_data;
++ u16 channel_2_rx_data;
++ u32 channel_2_data_width;
++
++ u16 channel_3_tx_data;
++ u16 channel_3_rx_data;
++ u32 channel_3_data_width;
++
++ u32 channel_enable_config; /* bit[0] = 0 : channel 0 disabled
++ [0] = 1 : channel 0 enabled
++ bit[1] = 0 : channel 1 disabled
++ [1] = 1 : channel 1 enabled
++ bit[2] = 0 : channel 2 disabled
++ [2] = 1 : channel 2 enabled
++ bit[3] = 0 : channel 3 disabled
++ [3] = 1 : channel 3 enabled */
++};
++
++
++typedef struct _PCM_OBJECT_ PCM_OBJECT_T;
++
++struct _PCM_OBJECT_
++{
++ u32 config_0;
++ u32 config_1;
++
++ u32 channel_0_config;
++ u32 channel_1_config;
++ u32 channel_2_config;
++ u32 channel_3_config;
++
++ u32 interrupt_config;
++
++ /*
++ * For interrupt setting
++ */
++// INTC_OBJECT_T intc_obj;
++};
++
++
++
++/*
++ * function declarations
++ */
++void Hal_Pcm_Initialize(PCM_OBJECT_T *);
++
++
++/*
++ * macro declarations
++ */
++#define HAL_PCM_ENABLE_PCM() \
++{ \
++ (PCM_CONFIGURATION_0_REG) |= ((u32)0x1 << 31); \
++}
++
++#define HAL_PCM_DISABLE_PCM() \
++{ \
++ (PCM_CONFIGURATION_0_REG) &= ~((u32)0x1 << 31); \
++}
++
++#define HAL_PCM_ENABLE_DATA_SWAP() \
++{ \
++ (PCM_CONFIGURATION_0_REG) |= (0x1 << 24); \
++}
++
++#define HAL_PCM_DISABLE_DATA_SWAP() \
++{ \
++ (PCM_CONFIGURATION_0_REG) &= ~(0x1 << 24); \
++}
++
++#define HAL_PCM_WRITE_TX_DATA_0(tx_data_0) \
++{ \
++ (PCM_TX_DATA_31_0_REG) = tx_data_0; \
++}
++
++#define HAL_PCM_WRITE_TX_DATA_1(tx_data_1) \
++{ \
++ (PCM_TX_DATA_63_32_REG) = tx_data_1; \
++}
++
++#define HAL_PCM_READ_RX_DATA_0(rx_data_0) \
++{ \
++ (rx_data_0) = PCM_RX_DATA_31_0_REG; \
++}
++
++#define HAL_PCM_READ_RX_DATA_1(rx_data_1) \
++{ \
++ (rx_data_1) = PCM_RX_DATA_63_32_REG; \
++}
++
++#define HAL_PCM_READ_INTERRUPT_STATUS(status) \
++{ \
++ (status) = PCM_INTERRUPT_STATUS_REG; \
++}
++
++#define HAL_PCM_CLEAR_INTERRUPT_STATUS(status) \
++{ \
++ (PCM_INTERRUPT_STATUS_REG) = (status & 0xC0); \
++}
++
++#define HAL_PCM_DISABLE_RECEIVE_BUFFER_FULL_INTERRUPT() \
++{ \
++ (PCM_INTERRUPT_ENABLE_REG) &= ~(0x1 << 0); \
++}
++
++#define HAL_PCM_DISABLE_TRANSMIT_BUFFER_EMPTY_INTERRUPT() \
++{ \
++ (PCM_INTERRUPT_ENABLE_REG) &= ~(0x1 << 1); \
++}
++
++#define HAL_PCM_DISABLE_RECEIVE_BUFFER_OVERRUN_INTERRUPT() \
++{ \
++ (PCM_INTERRUPT_ENABLE_REG) &= ~(0x1 << 2); \
++}
++
++#define HAL_PCM_DISABLE_TRANSMIT_BUFFER_UNDERRUN_INTERRUPT() \
++{ \
++ (PCM_INTERRUPT_ENABLE_REG) &= ~(0x1 << 3); \
++}
++
++#define HAL_PCM_DISABLE_ALL_INTERRUPT_SOURCES() \
++{ \
++ (PCM_INTERRUPT_ENABLE_REG) = 0; \
++}
++
++#endif // end of #ifndef _STAR_PCM_H_
++
+diff -rupN linux-2.6.35.11/include/asm/arch/star_powermgt.h linux-2.6.35.11-ts7500/include/asm/arch/star_powermgt.h
+--- linux-2.6.35.11/include/asm/arch/star_powermgt.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_powermgt.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,616 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_POWERMGT_H_
++#define _STAR_POWERMGT_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define PWRMGT_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_POWER_MANAGEMENT_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define PWRMGT_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_POWER_MANAGEMENT_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define PWRMGT_CLOCK_GATE_CONTROL0_REG PWRMGT_MEM_MAP_VALUE(0x00)
++#define PWRMGT_CLOCK_GATE_CONTROL1_REG PWRMGT_MEM_MAP_VALUE(0x04)
++#define PWRMGT_SOFTWARE_RESET_CONTROL_REG PWRMGT_MEM_MAP_VALUE(0x08)
++#define PWRMGT_SYSTEM_CLOCK_CONTROL_REG PWRMGT_MEM_MAP_VALUE(0x0C)
++#define PWRMGT_PLL_POWER_DOWN_CONTROL_REG PWRMGT_MEM_MAP_VALUE(0x10)
++#define PWRMGT_CPU_INITIALIZATION_REG PWRMGT_MEM_MAP_VALUE(0x14)
++#define PWRMGT_PAD_DRIVE_STRENGTH_CONTROL_REG PWRMGT_MEM_MAP_VALUE(0x1C)
++#define PWRMGT_USB_DEVICE_POWERMGT_REG PWRMGT_MEM_MAP_VALUE(0x20)
++#define PWRMGT_REGULATOR_CONTROL_REG PWRMGT_MEM_MAP_VALUE(0x24)
++#define PWRMGT_RTC_XTAL_CONTROL_REG PWRMGT_MEM_MAP_VALUE(0x28)
++#define PWRMGT_PLL250_CONTROL_REG PWRMGT_MEM_MAP_VALUE(0x2C)
++
++
++/*
++ * define constants macros
++ */
++#define PWRMGT_PCMCIA_SOFTWARE_RESET_BIT_INDEX (1)
++#define PWRMGT_IDE_SOFTWARE_RESET_BIT_INDEX (2)
++#define PWRMGT_VIC_SOFTWARE_RESET_BIT_INDEX (3)
++#define PWRMGT_DMA_SOFTWARE_RESET_BIT_INDEX (4)
++#define PWRMGT_NIC_SOFTWARE_RESET_BIT_INDEX (5)
++#define PWRMGT_USB_HOST_SOFTWARE_RESET_BIT_INDEX (6)
++#define PWRMGT_PCI_BRIDGE_SOFTWARE_RESET_BIT_INDEX (7)
++#define PWRMGT_P2S_SOFTWARE_RESET_BIT_INDEX (8)
++#define PWRMGT_UART0_SOFTWARE_RESET_BIT_INDEX (9)
++#define PWRMGT_UART1_SOFTWARE_RESET_BIT_INDEX (10)
++#define PWRMGT_TIMER_SOFTWARE_RESET_BIT_INDEX (11)
++#define PWRMGT_WDTIMER_SOFTWARE_RESET_BIT_INDEX (12)
++#define PWRMGT_GPIO_SOFTWARE_RESET_BIT_INDEX (13)
++#define PWRMGT_USB_DEVICE_SOFTWARE_RESET_BIT_INDEX (14)
++#define PWRMGT_FAST_ETHERNET_PHY_SOFTWARE_RESET_BIT_INDEX (15)
++#define PWRMGT_HSDMA_SOFTWARE_RESET_BIT_INDEX (16)
++
++
++#define PWRMGT_PLL_FREQUENCY_175MHZ (0 << 0)
++#define PWRMGT_PLL_FREQUENCY_200MHZ (1 << 0)
++#define PWRMGT_PLL_FREQUENCY_225MHZ (2 << 0)
++#define PWRMGT_PLL_FREQUENCY_250MHZ (3 << 0)
++
++#define PWRMGT_CPUCLK_DIVIDER_BY_1 (0 << 2)
++#define PWRMGT_CPUCLK_DIVIDER_BY_2 (1 << 2)
++#define PWRMGT_CPUCLK_DIVIDER_BY_3 (2 << 2)
++#define PWRMGT_CPUCLK_DIVIDER_BY_4 (3 << 2)
++
++#define PWRMGT_HCLK_DIVIDER_BY_1 (0 << 4)
++#define PWRMGT_HCLK_DIVIDER_BY_2 (1 << 4)
++#define PWRMGT_HCLK_DIVIDER_BY_3 (2 << 4)
++#define PWRMGT_HCLK_DIVIDER_BY_4 (3 << 4)
++
++#define PWRMGT_HCLK_SOURCE_FCLK (0 << 6)
++#define PWRMGT_HCLK_SOURCE_125MHZ (1 << 6)
++
++#define PWRMGT_PCLK_DIVIDER_BY_1 (0 << 8)
++#define PWRMGT_PCLK_DIVIDER_BY_2 (1 << 8)
++#define PWRMGT_PCLK_DIVIDER_BY_3 (2 << 8)
++#define PWRMGT_PCLK_DIVIDER_BY_4 (3 << 8)
++
++#define PWRMGT_PCICLK_DIVIDER_BY_1 (0 << 10)
++#define PWRMGT_PCICLK_DIVIDER_BY_2 (1 << 10)
++#define PWRMGT_PCICLK_DIVIDER_BY_3 (2 << 10)
++#define PWRMGT_PCICLK_DIVIDER_BY_4 (3 << 10)
++
++
++#define PWRMGT_PLLCLK_TO_CPUCLK_RATIO_BY_1 (1)
++#define PWRMGT_PLLCLK_TO_CPUCLK_RATIO_BY_2 (2)
++#define PWRMGT_PLLCLK_TO_CPUCLK_RATIO_BY_3 (3)
++#define PWRMGT_PLLCLK_TO_CPUCLK_RATIO_BY_4 (4)
++
++#define PWRMGT_CPUCLK_TO_HCLK_RATIO_BY_1 (1)
++#define PWRMGT_CPUCLK_TO_HCLK_RATIO_BY_2 (2)
++#define PWRMGT_CPUCLK_TO_HCLK_RATIO_BY_3 (3)
++#define PWRMGT_CPUCLK_TO_HCLK_RATIO_BY_4 (4)
++
++#define PWRMGT_HCLK_TO_PCLK_RATIO_BY_1 (1)
++#define PWRMGT_HCLK_TO_PCLK_RATIO_BY_2 (2)
++#define PWRMGT_HCLK_TO_PCLK_RATIO_BY_3 (3)
++#define PWRMGT_HCLK_TO_PCLK_RATIO_BY_4 (4)
++
++/*
++ * Macro defines for Clock Gate Control
++ */
++#define HAL_PWRMGT_DISABLE_DRAMC_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~(0x1); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_NIC_CLOCK() \
++{ \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 0); \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x0F << 20); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 5); \
++}
++
++#define HAL_PWRMGT_DISABLE_NIC_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~(0x0F << 20); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_PCI_BRIDGE_33M_CLOCK() \
++{ \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 1); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 10); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (0x1 << 10); \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x1 << 28) | (0x1 << 30); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 7); \
++}
++
++#define HAL_PWRMGT_ENABLE_PCI_BRIDGE_66M_CLOCK() \
++{ \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 1); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 10); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (0x0 << 10); \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x1 << 28) | (0x1 << 30); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 7); \
++}
++
++#define HAL_PWRMGT_DISABLE_PCI_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~((0x1 << 28) | (0x1 << 30)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_USB_CLOCK() \
++{ \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0xF << 1); \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x1 << 24); \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 28); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 6) | (0x1 << 14); \
++}
++
++#define HAL_PWRMGT_DISABLE_USB_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~(0x1 << 24); \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~(0x1 << 28); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_DMA_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x1 << 16); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 4); \
++}
++
++#define HAL_PWRMGT_DISABLE_DMA_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~(0x1 << 16); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_IDE_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x1 << 8) | (0x1 << 9); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 2); \
++}
++
++#define HAL_PWRMGT_DISABLE_IDE_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~((0x1 << 8) | (0x1 << 9)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_UART0_CLOCK() \
++{ \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~((0x1 << 1) | (0x1 << 2) | (0x1 << 5)); \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 12); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 9); \
++}
++
++#define HAL_PWRMGT_DISABLE_UART0_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~(0x1 << 12); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_UART1_CLOCK() \
++{ \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~((0x1 << 1) | (0x1 << 2) | (0x1 << 5)); \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 13); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 10); \
++}
++
++#define HAL_PWRMGT_DISABLE_UART1_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~(0x1 << 13); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_PCMCIA_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x1 << 4) | (0x1 << 5); \
++}
++
++#define HAL_PWRMGT_DISABLE_PCMCIA_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~((0x1 << 4) | (0x1 << 5)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_GPIO_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 25); \
++}
++
++#define HAL_PWRMGT_DISABLE_GPIO_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~(0x1 << 25); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_WDTIMER_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 21) | (0x1 << 22); \
++}
++
++#define HAL_PWRMGT_DISABLE_WDTIMER_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~((0x1 << 21) | (0x1 << 22)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_RTC_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 23); \
++}
++
++#define HAL_PWRMGT_DISABLE_RTC_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~(0x1 << 23); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_TIMER_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 17) | (0x1 << 18) | (0x1 << 19); \
++}
++
++#define HAL_PWRMGT_DISABLE_TIMER_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~((0x1 << 17) | (0x1 << 18) | (0x1 << 19)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_I2C_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 1); \
++}
++
++#define HAL_PWRMGT_DISABLE_I2C_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~(0x1 << 1); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_I2S_CLOCK() \
++{ \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~((0x1 << 5) | (0x1 << 6)); \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 1) | (0x1 << 10); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 8); \
++}
++
++#define HAL_PWRMGT_DISABLE_I2S_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~((0x1 << 1) | (0x1 << 10)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_PCM_CLOCK() \
++{ \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 5); \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 1) | (0x1 << 6); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 8); \
++}
++
++#define HAL_PWRMGT_DISABLE_PCM_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~((0x1 << 1) | (0x1 << 6)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_SPI_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 0) | (0x1 << 1); \
++}
++
++#define HAL_PWRMGT_DISABLE_SPI_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~((0x1 << 0) | (0x1 << 1)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_VIC_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x1 << 12); \
++}
++
++#define HAL_PWRMGT_DISABLE_VIC_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~(0x1 << 12); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_SMC_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG |= (0x1 << 4) | (0x1 << 5); \
++}
++
++#define HAL_PWRMGT_DISABLE_SMC_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL0_REG &= ~((0x1 << 4) | (0x1 << 5)); \
++}
++
++
++#define HAL_PWRMGT_ENABLE_HSDMA_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG |= (0x1 << 29); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1 << 16); \
++}
++
++#define HAL_PWRMGT_DISABLE_HSDMA_CLOCK() \
++{ \
++ PWRMGT_CLOCK_GATE_CONTROL1_REG &= ~(0x1 << 29); \
++}
++
++
++
++/*
++ * Macro defines for Reset Control
++ */
++#define HAL_PWRMGT_GLOBAL_SOFTWARE_RESET() \
++{ \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG |= (0x1); \
++ PWRMGT_SOFTWARE_RESET_CONTROL_REG &= ~(0x1); \
++}
++
++
++/*
++ * Macro defines for System Clock Control
++ */
++#define HAL_PWRMGT_SET_PLL_FREQUENCY_175MHZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~0x3; \
++}
++
++
++#define HAL_PWRMGT_SET_PLL_FREQUENCY_200MHZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~0x3; \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= 0x1; \
++}
++
++
++#define HAL_PWRMGT_SET_PLL_FREQUENCY_225MHZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~0x3; \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= 0x2; \
++}
++
++
++#define HAL_PWRMGT_SET_PLL_FREQUENCY_250MHZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~0x3; \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= 0x3; \
++}
++
++
++#define HAL_PWRMGT_CONFIG_PLLCLK_TO_CPUCLK_RATIO(ratio) \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 2); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (((ratio - 1) & 0x3) << 2); \
++}
++
++
++#define HAL_PWRMGT_CONFIG_CPUCLK_TO_HCLK_RATIO(ratio) \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 4); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (((ratio - 1) & 0x3) << 4); \
++}
++
++
++#define HAL_PWRMGT_HCLK_SOURCE_FCLK() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x1 << 6); \
++}
++
++
++#define HAL_PWRMGT_HCLK_SOURCE_125MHZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (0x1 << 6); \
++}
++
++
++#define HAL_PWRMGT_GIGA_NIC_CLOCK_SOURCE_HCLK() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x1 << 7); \
++}
++
++
++#define HAL_PWRMGT_GIGA_NIC_CLOCK_SOURCE_62_5MHZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (0x1 << 7); \
++}
++
++
++#define HAL_PWRMGT_CONFIG_HCLK_TO_PCLK_RATIO(ratio) \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 8); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (((ratio - 1) & 0x3) << 8); \
++}
++
++
++#define HAL_PWRMGT_I2S_CLOCK_SOURCE_8192000HZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 12); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (0x0 << 12); \
++}
++
++
++#define HAL_PWRMGT_I2S_CLOCK_SOURCE_11289600HZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 12); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (0x1 << 12); \
++}
++
++
++#define HAL_PWRMGT_I2S_CLOCK_SOURCE_12288000HZ() \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 12); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= (0x2 << 12); \
++}
++
++
++#define HAL_PWRMGT_CONFIGURE_MDC_CLOCK_DIVIDER(divided_value) \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3 << 14); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= ((divided_value & 0x3) << 14); \
++}
++
++
++#define HAL_PWRMGT_CONFIGURE_CLOCK_OUT_PIN(pin_source_select, divided_value) \
++{ \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG &= ~(0x3F << 16); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= ((pin_source_select & 0xF) << 16); \
++ PWRMGT_SYSTEM_CLOCK_CONTROL_REG |= ((divided_value & 0x3) << 20); \
++}
++
++
++/*
++ * Macro defines for PLL Power Down Control
++ */
++#define HAL_PWRMGT_POWER_DOWN_SYSTEM_XTAL_PAD() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG |= (0x1 << 7)
++
++#define HAL_PWRMGT_POWER_ON_SYSTEM_XTAL_PAD() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 7)
++
++
++#define HAL_PWRMGT_POWER_DOWN_PLL_X5() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG |= (0x1 << 0)
++
++#define HAL_PWRMGT_POWER_ON_PLL_X5() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 0)
++
++
++#define HAL_PWRMGT_POWER_DOWN_PLL_X8() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG |= (0x1 << 1)
++
++#define HAL_PWRMGT_POWER_ON_PLL_X8() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 1)
++
++
++#define HAL_PWRMGT_POWER_DOWN_PLL_X3() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG |= (0x1 << 2)
++
++#define HAL_PWRMGT_POWER_ON_PLL_X3() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 2)
++
++
++#define HAL_PWRMGT_POWER_DOWN_USBH_PHY_PLL() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG |= (0x1 << 3)
++
++#define HAL_PWRMGT_POWER_ON_USBH_PHY_PLL() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 3)
++
++
++#define HAL_PWRMGT_POWER_DOWN_USBD_PHY_PLL() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG |= (0x1 << 4)
++
++#define HAL_PWRMGT_POWER_ON_USBD_PHY_PLL() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 4)
++
++
++#define HAL_PWRMGT_POWER_DOWN_PLL_X2250() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG |= (0x1 << 5)
++
++#define HAL_PWRMGT_POWER_ON_PLL_X2250() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 5)
++
++
++#define HAL_PWRMGT_POWER_DOWN_PLL_X7() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG |= (0x1 << 6)
++
++#define HAL_PWRMGT_POWER_ON_PLL_X7() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG &= ~(0x1 << 6)
++
++
++#define HAL_PWRMGT_POWER_DOWN_ALL_PLL() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG = 0x7F;
++
++#define HAL_PWRMGT_POWER_ON_ALL_PLL() \
++ PWRMGT_PLL_POWER_DOWN_CONTROL_REG = 0;
++
++
++/*
++ * Macro defines for Pad Drive Strength Control
++ */
++#define HAL_PWRMGT_SELECT_PAD_DRIVE_STRENGTH_PCMCIA_CARDBUS_MODE() \
++{ \
++ PWRMGT_PAD_DRIVE_STRENGTH_CONTROL_REG &= ~(0x3 << 0); \
++}
++
++#define HAL_PWRMGT_SELECT_PAD_DRIVE_STRENGTH_PCI_MODE() \
++{ \
++ PWRMGT_PAD_DRIVE_STRENGTH_CONTROL_REG &= ~(0x3 << 0); \
++ PWRMGT_PAD_DRIVE_STRENGTH_CONTROL_REG |= (0x1 << 0); \
++}
++
++#define HAL_PWRMGT_SELECT_PAD_DRIVE_STRENGTH_MII_MODE() \
++{ \
++ PWRMGT_PAD_DRIVE_STRENGTH_CONTROL_REG |= (0x1 << 2); \
++}
++
++#define HAL_PWRMGT_SELECT_PAD_DRIVE_STRENGTH_RGMII_MODE() \
++{ \
++ PWRMGT_PAD_DRIVE_STRENGTH_CONTROL_REG &= ~(0x1 << 2); \
++}
++
++#define HAL_PWRMGT_ENABLE_MII_PAD_SIGNAL_NOT_BOUNDED() \
++{ \
++ PWRMGT_PAD_DRIVE_STRENGTH_CONTROL_REG |= (0x1 << 3); \
++}
++
++#define HAL_PWRMGT_DISABLE_MII_PAD_SIGNAL_NOT_BOUNDED() \
++{ \
++ PWRMGT_PAD_DRIVE_STRENGTH_CONTROL_REG &= ~(0x1 << 3); \
++}
++
++
++/*
++ * Macro defines for USB Device Power Management
++ */
++#define HAL_PWRMGT_REMOTE_WAKEUP_USB_HOST() \
++{ \
++ PWRMGT_USB_DEVICE_POWERMGT_REG |= (0x1 << 4); \
++}
++
++#define HAL_PWRMGT_USB_DEVICE_PHY_CLOCK_SOURCE_EXTERNAL_12MHZ() \
++{ \
++ PWRMGT_USB_DEVICE_POWERMGT_REG &= ~(0x1 << 5); \
++}
++
++#define HAL_PWRMGT_USB_DEVICE_PHY_CLOCK_SOURCE_INTERNAL_12MHZ() \
++{ \
++ PWRMGT_USB_DEVICE_POWERMGT_REG |= (0x1 << 5); \
++}
++
++
++/*
++ * Macro defines for Regulator Control
++ */
++
++
++#endif // end of #ifndef _STAR_POWERMGT_H_
+diff -rupN linux-2.6.35.11/include/asm/arch/star_rtc.h linux-2.6.35.11-ts7500/include/asm/arch/star_rtc.h
+--- linux-2.6.35.11/include/asm/arch/star_rtc.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_rtc.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,87 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_RTC_H_
++#define _STAR_RTC_H_
++
++#include <mach/star_sys_memory_map.h>
++
++#define RTC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_RTC_BASE_ADDR + reg_offset)))
++
++#define RTC_SECOND_REG RTC_MEM_MAP_VALUE(0x00)
++#define RTC_MINUTE_REG RTC_MEM_MAP_VALUE(0x04)
++#define RTC_HOUR_REG RTC_MEM_MAP_VALUE(0x08)
++#define RTC_DAY_REG RTC_MEM_MAP_VALUE(0x0C)
++#define RTC_SECOND_ALARM_REG RTC_MEM_MAP_VALUE(0x10)
++#define RTC_MINUTE_ALARM_REG RTC_MEM_MAP_VALUE(0x14)
++#define RTC_HOUR_ALARM_REG RTC_MEM_MAP_VALUE(0x18)
++#define RTC_RECORD_REG RTC_MEM_MAP_VALUE(0x1C)
++#define RTC_CONTROL_REG RTC_MEM_MAP_VALUE(0x20)
++#define RTC_INTERRUPT_STATUS_REG RTC_MEM_MAP_VALUE(0x34)
++
++#define RTC_ENABLE_BIT (1 << 0)
++#define RTC_AUTO_SECOND_ALARM_ENABLE_BIT (1 << 1)
++#define RTC_AUTO_MINUTE_ALARM_ENABLE_BIT (1 << 2)
++#define RTC_AUTO_HOUR_ALARM_ENABLE_BIT (1 << 3)
++#define RTC_AUTO_DAY_ALARM_ENABLE_BIT (1 << 4)
++#define RTC_MATCH_ALARM_ENABLE_BIT (1 << 5)
++#define RTC_BATTERY_LOW_VOLTAGE_ENABLE_BIT (1 << 6)
++
++#define RTC_AUTO_SECOND_ALARM_INTR_BIT (1 << 0)
++#define RTC_AUTO_MINUTE_ALARM_INTR_BIT (1 << 1)
++#define RTC_AUTO_HOUR_ALARM_INTR_BIT (1 << 2)
++#define RTC_AUTO_DAY_ALARM_INTR_BIT (1 << 3)
++#define RTC_MATCH_ALARM_INTR_BIT (1 << 4)
++#define RTC_BATTERY_LOW_VOLTAGE_INTR_BIT (1 << 5)
++
++#define HAL_RTC_READ_SECOND(second) ((second) = (RTC_SECOND_REG) & 0x3F);
++#define HAL_RTC_READ_MINUTE(minute) ((minute) = (RTC_MINUTE_REG) & 0x3F);
++#define HAL_RTC_READ_HOUR(hour) ((hour) = (RTC_HOUR_REG) & 0x1F);
++#define HAL_RTC_READ_DAY(day) ((day) = (RTC_DAY_REG) & 0xFFFF);
++#define HAL_RTC_ENABLE() ((RTC_CONTROL_REG) |= (RTC_ENABLE_BIT));
++#define HAL_RTC_DISABLE() ((RTC_CONTROL_REG) &= ~(RTC_ENABLE_BIT));
++#define HAL_RTC_AUTO_SECOND_ALARM_ENABLE() ((RTC_CONTROL_REG) |= (RTC_AUTO_SECOND_ALARM_ENABLE_BIT));
++#define HAL_RTC_AUTO_SECOND_ALARM_DISABLE() ((RTC_CONTROL_REG) &= ~(RTC_AUTO_SECOND_ALARM_ENABLE_BIT));
++#define HAL_RTC_AUTO_MINUTE_ALARM_ENABLE() ((RTC_CONTROL_REG) |= (RTC_AUTO_MINUTE_ALARM_ENABLE_BIT));
++#define HAL_RTC_AUTO_MINUTE_ALARM_DISABLE() ((RTC_CONTROL_REG) &= ~(RTC_AUTO_MINUTE_ALARM_ENABLE_BIT));
++#define HAL_RTC_AUTO_HOUR_ALARM_ENABLE() ((RTC_CONTROL_REG) |= (RTC_AUTO_HOUR_ALARM_ENABLE_BIT));
++#define HAL_RTC_AUTO_HOUR_ALARM_DISABLE() ((RTC_CONTROL_REG) &= ~(RTC_AUTO_HOUR_ALARM_ENABLE_BIT));
++#define HAL_RTC_AUTO_DAY_ALARM_ENABLE() ((RTC_CONTROL_REG) |= (RTC_AUTO_DAY_ALARM_ENABLE_BIT));
++#define HAL_RTC_AUTO_DAY_ALARM_DISABLE() ((RTC_CONTROL_REG) &= ~(RTC_AUTO_DAY_ALARM_ENABLE_BIT));
++#define HAL_RTC_MATCH_ALARM_ENABLE() ((RTC_CONTROL_REG) |= (RTC_MATCH_ALARM_ENABLE_BIT));
++#define HAL_RTC_MATCH_ALARM_DISABLE() ((RTC_CONTROL_REG) &= ~(RTC_MATCH_ALARM_ENABLE_BIT));
++#define HAL_RTC_BATTERY_LOW_VOLTAGE_INTERRUPT_ENABLE() ((RTC_CONTROL_REG) |= (RTC_BATTERY_LOW_VOLTAGE_ENABLE_BIT));
++#define HAL_RTC_BATTERY_LOW_VOLTAGE_INTERRUPT_DISABLE() ((RTC_CONTROL_REG) &= ~(RTC_BATTERY_LOW_VOLTAGE_ENABLE_BIT));
++#define HAL_RTC_WRITE_RECORD(record) ((RTC_RECORD_REG) = (record));
++#define HAL_RTC_READ_RECORD(record) ((record) = (RTC_RECORD_REG));
++#define HAL_RTC_WRITE_MATCHED_ALARM_SECOND(second) ((RTC_SECOND_ALARM_REG) = (second & 0x3F));
++#define HAL_RTC_READ_MATCHED_ALARM_SECOND(second) ((second) = (RTC_SECOND_ALARM_REG) & 0x3F);
++#define HAL_RTC_WRITE_MATCHED_ALARM_MINUTE(minute) ((RTC_MINUTE_ALARM_REG) = (minute & 0x3F));
++#define HAL_RTC_READ_MATCHED_ALARM_MINUTE(minute) ((minute) = (RTC_MINUTE_ALARM_REG) & 0x3F);
++#define HAL_RTC_WRITE_MATCHED_ALARM_HOUR(hour) ((RTC_HOUR_ALARM_REG) = (hour & 0x1F));
++#define HAL_RTC_READ_MATCHED_ALARM_HOUR(hour) ((hour) = (RTC_HOUR_ALARM_REG) & 0x1F);
++#define HAL_RTC_READ_INTERRUPT_STATUS(status) ((status) = (RTC_INTERRUPT_STATUS_REG) & 0x3F);
++#define HAL_RTC_WRITE_INTERRUPT_STATUS(status) ((RTC_INTERRUPT_STATUS_REG) = (status) & 0x3F);
++
++#endif
++
+diff -rupN linux-2.6.35.11/include/asm/arch/star_smc.h linux-2.6.35.11-ts7500/include/asm/arch/star_smc.h
+--- linux-2.6.35.11/include/asm/arch/star_smc.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_smc.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,57 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_SMC_H_
++#define _STAR_SMC_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define SMC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_SMC_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define SMC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_SMC_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++
++/*
++ * Static Memory Controller Registers
++ */
++#define SMC_MEM_BANK0_CONFIG_REG SMC_MEM_MAP_VALUE(0x00)
++#define SMC_MEM_BANK0_TIMING_REG SMC_MEM_MAP_VALUE(0x04)
++#define SMC_MEM_BANK1_CONFIG_REG SMC_MEM_MAP_VALUE(0x08)
++#define SMC_MEM_BANK1_TIMING_REG SMC_MEM_MAP_VALUE(0x0C)
++#define SMC_MEM_BANK2_CONFIG_REG SMC_MEM_MAP_VALUE(0x10)
++#define SMC_MEM_BANK2_TIMING_REG SMC_MEM_MAP_VALUE(0x14)
++#define SMC_MEM_BANK3_CONFIG_REG SMC_MEM_MAP_VALUE(0x18)
++#define SMC_MEM_BANK3_TIMING_REG SMC_MEM_MAP_VALUE(0x1C)
++
++/*
++ * macros declarations
++ */
++
++#endif // end of #ifndef _STAR_SMC_H_
+diff -rupN linux-2.6.35.11/include/asm/arch/star_spi.h linux-2.6.35.11-ts7500/include/asm/arch/star_spi.h
+--- linux-2.6.35.11/include/asm/arch/star_spi.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_spi.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,169 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_SPI_H_
++#define _STAR_SPI_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define SPI_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_SPI_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define SPI_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_SPI_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define SPI_CONFIGURATION_REG SPI_MEM_MAP_VALUE(0x40)
++#define SPI_SERVICE_STATUS_REG SPI_MEM_MAP_VALUE(0x44)
++#define SPI_BIT_RATE_CONTROL_REG SPI_MEM_MAP_VALUE(0x48)
++#define SPI_TRANSMIT_CONTROL_REG SPI_MEM_MAP_VALUE(0x4C)
++#define SPI_TRANSMIT_BUFFER_REG SPI_MEM_MAP_VALUE(0x50)
++#define SPI_RECEIVE_CONTROL_REG SPI_MEM_MAP_VALUE(0x54)
++#define SPI_RECEIVE_BUFFER_REG SPI_MEM_MAP_VALUE(0x58)
++#define SPI_FIFO_TRANSMIT_CONFIG_REG SPI_MEM_MAP_VALUE(0x5C)
++#define SPI_FIFO_TRANSMIT_CONTROL_REG SPI_MEM_MAP_VALUE(0x60)
++#define SPI_FIFO_RECEIVE_CONFIG_REG SPI_MEM_MAP_VALUE(0x64)
++#define SPI_INTERRUPT_STATUS_REG SPI_MEM_MAP_VALUE(0x68)
++#define SPI_INTERRUPT_ENABLE_REG SPI_MEM_MAP_VALUE(0x6C)
++
++
++/*
++ * define constants macros
++ */
++#define SPI_TX_RX_FIFO_DEPTH (8)
++
++#define SPI_CH0 (0)
++#define SPI_CH1 (1)
++#define SPI_CH2 (2)
++#define SPI_CH3 (3)
++
++
++#define SPI_RXFIFO_OT_FG (0x01)
++#define SPI_TXFIFO_UT_FG (0x02)
++#define SPI_RXBUF_FULL_FG (0x04)
++#define SPI_TXBUF_EMPTY_FG (0x08)
++
++#define SPI_RXFIFO_OR_FG (0x10)
++#define SPI_TXFIFO_UR_FG (0x20)
++#define SPI_RXBUF_OR_FG (0x40)
++#define SPI_TXBUF_UR_FG (0x80)
++
++/*
++ * define Character Length Control
++ */
++#define SPI_LEN_BIT_8 (0)
++#define SPI_LEN_BIT_16 (1)
++#define SPI_LEN_BIT_24 (2)
++#define SPI_LEN_BIT_32 (3)
++
++
++/*
++ * macro declarations
++ */
++#define HAL_SPI_ENABLE_SPI() \
++{ \
++ (SPI_CONFIGURATION_REG) |= ((u_int32)0x1 << 31); \
++}
++
++#define HAL_SPI_DISABLE_SPI() \
++{ \
++ (SPI_CONFIGURATION_REG) &= ~((u_int32)0x1 << 31); \
++}
++
++#define HAL_SPI_ENABLE_DATA_SWAP() \
++{ \
++ (SPI_CONFIGURATION_REG) |= (0x1 << 24); \
++}
++
++#define HAL_SPI_DISABLE_DATA_SWAP() \
++{ \
++ (SPI_CONFIGURATION_REG) &= ~(0x1 << 24); \
++}
++
++#define HAL_SPI_TRANSMIT_DATA(tx_data) \
++{ \
++ (SPI_TRANSMIT_BUFFER_REG) = tx_data; \
++}
++
++#define HAL_SPI_RECEIVE_DATA(rx_data) \
++{ \
++ (rx_data) = SPI_RECEIVE_BUFFER_REG; \
++}
++
++#define HAL_SPI_GET_TRANSMIT_FIFO_WORDS_NUMBER(tx_fifo_words_num) \
++{ \
++ (tx_fifo_words_num) = SPI_FIFO_TRANSMIT_CONFIG_REG & 0xF; \
++}
++
++#define HAL_SPI_GET_RECEIVE_FIFO_WORDS_NUMBER(rx_fifo_words_num) \
++{ \
++ (rx_fifo_words_num) = SPI_FIFO_RECEIVE_CONFIG_REG & 0xF; \
++}
++
++#define HAL_SPI_DISABLE_ALL_INTERRUPT_SOURCES() \
++{ \
++ (SPI_INTERRUPT_ENABLE_REG) = 0; \
++}
++
++#define HAL_SPI_DISABLE_TX_FIFO_THRESHOLD_INTERRUPT() \
++{ \
++ (SPI_INTERRUPT_ENABLE_REG) &= ~(0x1 << 1); \
++}
++
++#define HAL_SPI_DISABLE_RX_FIFO_THRESHOLD_INTERRUPT() \
++{ \
++ (SPI_INTERRUPT_ENABLE_REG) &= ~(0x1 << 0); \
++}
++
++#define HAL_SPI_READ_INTERRUPT_STATUS(status) \
++{ \
++ (status) = SPI_INTERRUPT_STATUS_REG; \
++}
++
++#define HAL_SPI_CLEAR_INTERRUPT_STATUS(status) \
++{ \
++ (SPI_INTERRUPT_STATUS_REG) = (status & 0xF0); \
++}
++
++#define HAL_SPI_SET_FIFO_TRANSMIT_DELAY(delay) \
++{ \
++ (SPI_FIFO_TRANSMIT_CONTROL_REG) = (delay & 0x1F); \
++}
++
++#define STR8100_SPI_SERIAL_MODE_GENERAL 0x0
++#define STR8100_SPI_SERIAL_MODE_MICROPROCESSOR 0x1
++
++struct str8100_spi_dev_attr
++{
++ int spi_serial_mode;
++};
++
++#endif // end of #ifndef _STAR_SPI_H_
++
+diff -rupN linux-2.6.35.11/include/asm/arch/star_sys_memory_map.h linux-2.6.35.11-ts7500/include/asm/arch/star_sys_memory_map.h
+--- linux-2.6.35.11/include/asm/arch/star_sys_memory_map.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_sys_memory_map.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,109 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_SYS_MEMORY_MAP_H_
++#define _STAR_SYS_MEMORY_MAP_H_
++
++
++#if 0
++#define __UBOOT__
++#else
++#define __LINUX__
++#endif
++
++
++/*
++ * sytem memory mapping after reset
++ */
++#define SYSPA_FLASH_SRAM_BANK0_BASE_ADDR 0x10000000
++#define SYSPA_FLASH_SRAM_BANK1_BASE_ADDR 0x11000000
++#define SYSPA_FLASH_SRAM_BANK2_BASE_ADDR 0x12000000
++#define SYSPA_FLASH_SRAM_BANK3_BASE_ADDR 0x13000000
++#define SYSPA_PCMCIA_ATTRIBUTE_MEMORY_BASE_ADDR 0x14000000
++#define SYSPA_PCMCIA_COMMON_MEMORY_BASE_ADDR 0x15000000
++#define SYSPA_PCMCIA_IO_SPACE_BASE_ADDR 0x16000000
++#define SYSPA_IDE_DEVICE_BASE_ADDR 0x18000000
++#define SYSPA_SDRAM_MEMORY_BASE_ADDR 0x20000000
++#define SYSPA_GDMAC_BASE_ADDR 0x60000000
++#define SYSPA_NIC_BASE_ADDR 0x70000000
++#define SYSPA_SPI_BASE_ADDR 0x71000000
++#define SYSPA_PCM_BASE_ADDR 0x71000000
++#define SYSPA_I2C_BASE_ADDR 0x71000000
++#define SYSPA_I2S_BASE_ADDR 0x71000000
++#define SYSPA_DDRC_SDRC_BASE_ADDR 0x72000000
++#define SYSPA_SMC_BASE_ADDR 0x73000000
++#define SYSPA_PCMCIA_CONTROL_BASE_ADDR 0x73000000
++#define SYSPA_IDE_CONTROLLER_BASE_ADDR 0x74000000
++#define SYSPA_MISC_BASE_ADDR 0x76000000
++#define SYSPA_POWER_MANAGEMENT_BASE_ADDR 0x77000000
++#define SYSPA_UART0_BASE_ADDR 0x78000000
++#define SYSPA_UART1_BASE_ADDR 0x78800000
++#define SYSPA_TIMER_BASE_ADDR 0x79000000
++#define SYSPA_WATCHDOG_TIMER_BASE_ADDR 0x7A000000
++#define SYSPA_RTC_BASE_ADDR 0x7B000000
++#define SYSPA_GPIOA_BASE_ADDR 0x7C000000
++#define SYSPA_GPIOB_BASE_ADDR 0x7C800000
++#define SYSPA_PCI_BRIDGE_CONFIG_DATA_BASE_ADDR 0xA0000000
++#define SYSPA_PCI_BRIDGE_CONFIG_ADDR_BASE_ADDR 0xA4000000
++#define SYSPA_PCI_IO_SPACE_BASE_ADDR 0xA8000000
++#define SYSPA_PCI_MEMORY_SPACE_BASE_ADDR 0xB0000000
++#define SYSPA_USB11_CONFIG_BASE_ADDR 0xC0000000
++#define SYSPA_USB11_OPERATION_BASE_ADDR 0xC4000000
++#define SYSPA_USB20_CONFIG_BASE_ADDR 0xC8000000
++#define SYSPA_USB20_OPERATION_BASE_ADDR 0xCC000000
++#define SYSPA_USB20_DEVICE_BASE_ADDR 0xD0000000
++#define SYSPA_VIC_BASE_ADDR 0xFFFFF000
++
++#if defined(__LINUX__)
++#define SYSVA_FLASH_BASE_ADDR 0xFF000000
++#define SYSVA_IDE_DEVICE_BASE_ADDR 0xFFF00000
++#define SYSVA_GDMAC_BASE_ADDR 0xFFF01000
++#define SYSVA_NIC_BASE_ADDR 0xFFF02000
++#define SYSVA_SPI_BASE_ADDR 0xFFF03000
++#define SYSVA_PCM_BASE_ADDR 0xFFF04000
++#define SYSVA_I2C_BASE_ADDR 0xFFF05000
++#define SYSVA_I2S_BASE_ADDR 0xFFF06000
++#define SYSVA_DDRC_SDRC_BASE_ADDR 0xFFF07000
++#define SYSVA_SMC_BASE_ADDR 0xFFF08000
++#define SYSVA_PCMCIA_CONTROL_BASE_ADDR 0xFFF09000
++#define SYSVA_IDE_CONTROLLER_BASE_ADDR 0xFFF0A000
++#define SYSVA_MISC_BASE_ADDR 0xFFF0B000
++#define SYSVA_POWER_MANAGEMENT_BASE_ADDR 0xFFF0C000
++#define SYSVA_UART0_BASE_ADDR 0xFFF0D000
++#define SYSVA_UART1_BASE_ADDR 0xFFF0E000
++#define SYSVA_TIMER_BASE_ADDR 0xFFF0F000
++#define SYSVA_WATCHDOG_TIMER_BASE_ADDR 0xFFF10000
++#define SYSVA_RTC_BASE_ADDR 0xFFF11000
++#define SYSVA_GPIOA_BASE_ADDR 0xFFF12000
++#define SYSVA_GPIOB_BASE_ADDR 0xFFF13000
++#define SYSVA_PCI_BRIDGE_CONFIG_DATA_BASE_ADDR 0xFFF14000
++#define SYSVA_PCI_BRIDGE_CONFIG_ADDR_BASE_ADDR 0xFFF15000
++#define SYSVA_USB11_CONFIG_BASE_ADDR 0xFFF16000
++#define SYSVA_USB11_OPERATION_BASE_ADDR 0xFFF17000
++#define SYSVA_USB20_CONFIG_BASE_ADDR 0xFFF18000
++#define SYSVA_USB20_OPERATION_BASE_ADDR 0xFFF19000
++#define SYSVA_USB20_DEVICE_BASE_ADDR 0xFFF1A000
++#define SYSVA_VIC_BASE_ADDR 0xFFF1B000
++#endif //__LINUX__
++
++#endif // end of #ifndef _STAR_SYS_MEMORY_MAP_H_
+diff -rupN linux-2.6.35.11/include/asm/arch/star_timer.h linux-2.6.35.11-ts7500/include/asm/arch/star_timer.h
+--- linux-2.6.35.11/include/asm/arch/star_timer.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_timer.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,312 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_TIMER_H_
++#define _STAR_TIMER_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define TIMER_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_TIMER_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define TIMER_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_TIMER_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define TIMER1_COUNTER_REG TIMER_MEM_MAP_VALUE(0x00)
++#define TIMER1_AUTO_RELOAD_VALUE_REG TIMER_MEM_MAP_VALUE(0x04)
++#define TIMER1_MATCH_VALUE1_REG TIMER_MEM_MAP_VALUE(0x08)
++#define TIMER1_MATCH_VALUE2_REG TIMER_MEM_MAP_VALUE(0x0C)
++
++#define TIMER2_COUNTER_REG TIMER_MEM_MAP_VALUE(0x10)
++#define TIMER2_AUTO_RELOAD_VALUE_REG TIMER_MEM_MAP_VALUE(0x14)
++#define TIMER2_MATCH_VALUE1_REG TIMER_MEM_MAP_VALUE(0x18)
++#define TIMER2_MATCH_VALUE2_REG TIMER_MEM_MAP_VALUE(0x1C)
++
++#define TIMER1_TIMER2_CONTROL_REG TIMER_MEM_MAP_VALUE(0x30)
++#define TIMER1_TIMER2_INTERRUPT_STATUS_REG TIMER_MEM_MAP_VALUE(0x34)
++#define TIMER1_TIMER2_INTERRUPT_MASK_REG TIMER_MEM_MAP_VALUE(0x38)
++
++#define TIMER3_COUNTER_LOW_REG TIMER_MEM_MAP_VALUE(0x40)
++#define TIMER3_CONTROL_REG TIMER_MEM_MAP_VALUE(0x44)
++
++
++/*
++ * define constants macros
++ */
++#define TIMER1_ENABLE_BIT_INDEX 0
++#define TIMER1_CLOCK_SOURCE_BIT_INDEX 1
++#define TIMER1_OVERFLOW_ENABLE_BIT_INDEX 2
++
++#define TIMER2_ENABLE_BIT_INDEX 3
++#define TIMER2_CLOCK_SOURCE_BIT_INDEX 4
++#define TIMER2_OVERFLOW_ENABLE_BIT_INDEX 5
++
++#define TIMER1_UP_DOWN_COUNT_BIT_INDEX 9
++#define TIMER2_UP_DOWN_COUNT_BIT_INDEX 10
++
++#define TIMER1_MATCH1_INTERRUPT_BIT_INDEX 0
++#define TIMER1_MATCH2_INTERRUPT_BIT_INDEX 1
++#define TIMER1_OVERFLOW_INTERRUPT_BIT_INDEX 2
++
++#define TIMER2_MATCH1_INTERRUPT_BIT_INDEX 3
++#define TIMER2_MATCH2_INTERRUPT_BIT_INDEX 4
++#define TIMER2_OVERFLOW_INTERRUPT_BIT_INDEX 5
++
++#define TIMER3_ENABLE_BIT_INDEX 17
++#define TIMER3_RESET_BIT_INDEX 16
++
++#define TIMER_CLOCK_SOURCE_PCLK 0
++#define TIMER_CLOCK_SOURCE_EXT_CLK 1
++
++
++#define TIMER_OVERFLOW_MODE_DISABLE 0
++#define TIMER_OVERFLOW_MODE_ENABLE 1
++
++
++#define TIMER_COUNTER_MODE_UP 0
++#define TIMER_COUNTER_MODE_DOWN 1
++
++
++#define MATCH1_MASK_ENABLE (1 << 0)
++
++#define MATCH2_MASK_ENABLE (1 << 1)
++
++#define OVERFLOW_MASK_ENABLE (1 << 2)
++
++
++/*
++ * macro declarations
++ */
++#define HAL_TIMER_ENABLE_TIMER1() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) |= (1 << TIMER1_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_DISABLE_TIMER1() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) &= ~(1 << TIMER1_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_ENABLE_TIMER2() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) |= (1 << TIMER2_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_DISABLE_TIMER2() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) &= ~(1 << TIMER2_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_ENABLE_TIMER1_OVERFLOW_MODE() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) |= (1 << TIMER1_OVERFLOW_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_DISABLE_TIMER1_OVERFLOW_MODE() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) &= ~(1 << TIMER1_OVERFLOW_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_ENABLE_TIMER2_OVERFLOW_MODE() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) |= (1 << TIMER2_OVERFLOW_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_DISABLE_TIMER2_OVERFLOW_MODE() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) &= ~(1 << TIMER2_OVERFLOW_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_SET_TIMER1_DOWNCOUNT() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) |= (1 << TIMER1_UP_DOWN_COUNT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_SET_TIMER1_UPCOUNT() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) &= ~(1 << TIMER1_UP_DOWN_COUNT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_SET_TIMER2_DOWNCOUNT() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) |= (1 << TIMER2_UP_DOWN_COUNT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_SET_TIMER2_UPCOUNT() \
++{ \
++ ((TIMER1_TIMER2_CONTROL_REG) &= ~(1 << TIMER2_UP_DOWN_COUNT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_READ_INTERRUPT_STATUS(interrupt_status) \
++{ \
++ ((interrupt_status) = (TIMER1_TIMER2_INTERRUPT_STATUS_REG)); \
++}
++
++
++#define HAL_TIMER_WRITE_INTERRUPT_STATUS(interrupt_status) \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_STATUS_REG) = (interrupt_status)); \
++}
++
++
++#define HAL_TIMER_READ_INTERRUPT_MASK(interrupt_mask) \
++{ \
++ ((interrupt_mask) = (TIMER1_TIMER2_INTERRUPT_MASK_REG)); \
++}
++
++
++#define HAL_TIMER_WRITE_INTERRUPT_MASK(interrupt_mask) \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) = (interrupt_mask)); \
++}
++
++
++#define HAL_TIMER_MASK_TIMER1_TIMER2_ALL_INTERRUPTS() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) = (0x3F));\
++}
++
++
++#define HAL_TIMER_MASK_TIMER1_MATCH1_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) |= (1 << TIMER1_MATCH1_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_MASK_TIMER1_MATCH2_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) |= (1 << TIMER1_MATCH2_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_MASK_TIMER1_OVERFLOW_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) |= (1 << TIMER1_OVERFLOW_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_UNMASK_TIMER1_MATCH1_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) &= ~(1 << TIMER1_MATCH1_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_UNMASK_TIMER1_MATCH2_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) &= ~(1 << TIMER1_MATCH2_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_UNMASK_TIMER1_OVERFLOW_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) &= ~(1 << TIMER1_OVERFLOW_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_MASK_TIMER2_MATCH1_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) |= (1 << TIMER2_MATCH1_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_MASK_TIMER2_MATCH2_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) |= (1 << TIMER2_MATCH2_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_MASK_TIMER2_OVERFLOW_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) |= (1 << TIMER2_OVERFLOW_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_UNMASK_TIMER2_MATCH1_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) &= ~(1 << TIMER2_MATCH1_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_UNMASK_TIMER2_MATCH2_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) &= ~(1 << TIMER2_MATCH2_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_UNMASK_TIMER2_OVERFLOW_INTERRUPT() \
++{ \
++ ((TIMER1_TIMER2_INTERRUPT_MASK_REG) &= ~(1 << TIMER2_OVERFLOW_INTERRUPT_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_DISABLE_TIMER3() \
++{ \
++ ((TIMER3_CONTROL_REG) = 0); \
++}
++
++
++#define HAL_TIMER_ENABLE_TIMER3() \
++{ \
++ ((TIMER3_CONTROL_REG) = (1 << TIMER3_ENABLE_BIT_INDEX)); \
++}
++
++
++#define HAL_TIMER_RESET_TIMER3() \
++{ \
++ ((TIMER3_CONTROL_REG) = (1 << TIMER3_RESET_BIT_INDEX)); \
++}
++
++#ifndef __ASSEMBLY__
++static inline unsigned long long HAL_TIMER_GET_TIMER3_COUNTER(void)
++{
++ unsigned long h;
++ unsigned long l;
++
++ h = TIMER3_CONTROL_REG & 0xFFFF;
++ l = TIMER3_COUNTER_LOW_REG;
++
++ return ((((unsigned long long)h) << 32) | l);
++}
++#endif
++
++#endif // end of #ifndef _STAR_TIMER_H_
+diff -rupN linux-2.6.35.11/include/asm/arch/star_uart.h linux-2.6.35.11-ts7500/include/asm/arch/star_uart.h
+--- linux-2.6.35.11/include/asm/arch/star_uart.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_uart.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,350 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_UART_H_
++#define _STAR_UART_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#define UART_MEM_MAP_VALUE_PHY(reg_offset) (*((u32 volatile *)(SYSPA_UART0_BASE_ADDR + reg_offset)))
++#define UART_MEM_MAP_VALUE_VIR(reg_offset) (*((u32 volatile *)(SYSVA_UART0_BASE_ADDR + reg_offset)))
++
++
++#define UART1_OFFSET 0x800000 //SYS_UART1_BASE_ADDR = 0x78800000 = (UART1_OFFSET+ SYS_UART0_BASE_ADDR)
++
++#define __UART_RBR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x00)
++#define __UART_THR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x00)
++#define __UART_DLL(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x00)
++
++#define __UART_IER(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x04)
++#define __UART_DLM(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x04)
++
++#define __UART_IIR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x08)
++#define __UART_FCR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x08)
++#define __UART_PSR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x08)
++
++#define __UART_LCR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x0C)
++#define __UART_MCR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x10) //UART(n) Control Reg
++#define __UART_LSR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x14)
++#define __UART_SPR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x1C)
++
++#if defined(__UBOOT__)
++#define _UART_RBR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x00)
++#define _UART_THR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x00)
++#define _UART_DLL(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x00)
++
++#define _UART_IER(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x04)
++#define _UART_DLM(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x04)
++
++#define _UART_IIR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x08)
++#define _UART_FCR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x08)
++#define _UART_PSR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x08)
++
++#define _UART_LCR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x0C)
++#define _UART_MCR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x10) //UART(n) Control Reg
++#define _UART_LSR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x14)
++#define _UART_SPR(idx) UART_MEM_MAP_VALUE_PHY((UART1_OFFSET * idx) + 0x1C)
++#elif defined(__LINUX__)
++#define _UART_RBR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x00)
++#define _UART_THR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x00)
++#define _UART_DLL(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x00)
++
++#define _UART_IER(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x04)
++#define _UART_DLM(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x04)
++
++#define _UART_IIR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x08)
++#define _UART_FCR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x08)
++#define _UART_PSR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x08)
++
++#define _UART_LCR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x0C)
++#define _UART_MCR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x10) //UART(n) Control Reg
++#define _UART_LSR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x14)
++#define _UART_SPR(idx) UART_MEM_MAP_VALUE_VIR((UART1_OFFSET * idx) + 0x1C)
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define constants macros
++ */
++#define UART_INPUT_CLOCK (13000000)
++
++
++#define UART_FIFO_DEPTH 16
++
++
++#define RX_DATA_READY_INT (1 << 0)
++#define THR_EMPTY_INT (1 << 1)
++#define RX_LINE_STATUS_INT (1 << 2)
++#define MODEM_STATUS_INT (1 << 3)
++
++
++#define NO_INT_PENDING_MASK (0x1)
++#define RX_LINE_STATUS_INT_MASK (0x6)
++#define RX_DATA_READY_INT_MASK (0x4)
++#define RX_DATA_TIMEOUT_INT_MASK (0xC)
++#define THR_EMPTY_INT_MASK (0x2)
++#define MODEM_STATUS_CHANGE_MASK (0x0)
++
++
++/* FCR Register */
++#define FIFO_ENABLE (1 << 0)
++#define RX_FIFO_RESET (1 << 1)
++#define TX_FIFO_RESET (1 << 2)
++#define DMA_MODE (1 << 3)
++
++
++#define RX_FIFO_TRIGGER_LEVEL_1 (0 << 6)
++#define RX_FIFO_TRIGGER_LEVEL_4 (1 << 6)
++#define RX_FIFO_TRIGGER_LEVEL_8 (2 << 6)
++#define RX_FIFO_TRIGGER_LEVEL_14 (3 << 6)
++
++
++#define TX_FIFO_TRIGGER_LEVEL_1 (0 << 4)
++#define TX_FIFO_TRIGGER_LEVEL_3 (1 << 4)
++#define TX_FIFO_TRIGGER_LEVEL_9 (2 << 4)
++#define TX_FIFO_TRIGGER_LEVEL_13 (3 << 4)
++
++
++
++/* LCR Register */
++#define WORD_LENGTH_5 (0 << 0)
++#define WORD_LENGTH_6 (1 << 0)
++#define WORD_LENGTH_7 (2 << 0)
++#define WORD_LENGTH_8 (3 << 0)
++
++#define STOP_BIT_1 (0 << 2)
++#define STOP_BIT_1_5 (1 << 2)
++#define STOP_BIT_2 (1 << 2)
++
++#define PARITY_CHECK_NONE (0 << 3)
++#define PARITY_CHECK_EVEN (3 << 3)
++#define PARITY_CHECK_ODD (1 << 3)
++#define PARITY_CHECK_STICK_ONE (5 << 3)
++#define PARITY_CHECK_STICK_ZERO (7 << 3)
++
++#define SET_BREAK (1 << 6)
++
++#define DLAB_ENABLE (1 << 7)
++
++/* MCR Register */
++//#define UART_MCR_DTR 0x1 /* Data Terminal Ready */
++//#define UART_MCR_RTS 0x2 /* Request to Send */
++//#define UART_MCR_OUT1 0x4 /* output1 */
++//#define UART_MCR_OUT2 0x8 /* output2 or global interrupt enable */
++#define UART_MCR_LPBK 0x10 /* loopback mode */
++
++
++/* LSR Register */
++#define _DATA_READY (1 << 0)
++#define OVERRUN_ERROR (1 << 1)
++#define PARITY_ERROR (1 << 2)
++#define FRAMING_ERROR (1 << 3)
++#define BREAK_INTERRUPT (1 << 4)
++#define THR_EMPTY (1 << 5)
++#define TRANSMITTER_EMPTY (1 << 6)
++#define FIFO_DATA_ERROR (1 << 7)
++
++#define TEST_PARITY_ERROR (1 << 0)
++#define TEST_FRAMING_ERROR (1 << 1)
++#define TEST_BAUD_GEN (1 << 2)
++#define TEST_LOOPBACK_ENABLE (1 << 3)
++
++
++#define WORD_FIVE_BITS 5
++#define WORD_SIX_BITS 6
++#define WORD_SEVEN_BITS 7
++#define WORD_EIGHT_BITS 8
++
++#define NONE_PARITY 1
++#define EVEN_PARITY 2
++#define ODD_PARITY 3
++#define ONE_PARITY 4
++#define ZERO_PARITY 5
++
++#define ONE_STOP_BIT 1
++#define ONE_HALF_STOP_BIT 2
++#define TWO_STOP_BIT 3
++
++#define TX_RX_FIFO_DISABLE 0
++#define TX_RX_FIFO_ENABLE 1
++
++
++/*
++ * macros declarations
++ */
++
++#define HAL_UART_READ_DATA(idx,data) \
++{ \
++ ((data) = (_UART_RBR(idx)) & 0xFF); \
++}
++
++
++#define HAL_UART_WRITE_DATA(idx,data) \
++{ \
++ ((_UART_THR(idx)) = (data) & 0xFF); \
++}
++
++
++#define HAL_UART_ENABLE_INTERRUPT_TYPE(idx,interrupt_type) \
++{ \
++ ((_UART_IER(idx)) |= (interrupt_type & 0xF)); \
++}
++
++
++#define HAL_UART_DISABLE_INTERRUPT_TYPE(idx,interrupt_type) \
++{ \
++ ((_UART_IER(idx)) &= ~(interrupt_type & 0xF)); \
++}
++
++
++#define HAL_UART_READ_INTERRUPT_IDENTIFICATION(idx,uart_IIR) \
++{ \
++ ((uart_IIR) = (_UART_IIR(idx))); \
++}
++
++
++#define HAL_UART_CHECK_NO_INT_PENDING(idx,uart_IIR) \
++{ \
++ (((uart_IIR) & 0xF) == (NO_INT_PENDING_MASK)); \
++}
++
++
++#define HAL_UART_CHECK_RX_LINE_STATUS_INT(idx,uart_IIR) \
++ (((uart_IIR) & 0xF) == (RX_LINE_STATUS_INT_MASK))
++
++
++#define HAL_UART_CHECK_RX_DATA_READY_INT(idx,uart_IIR) \
++ (((uart_IIR) & 0xF) == (RX_DATA_READY_INT_MASK))
++
++
++#define HAL_UART_CHECK_RX_DATA_TIMEOUT_INT(idx,uart_IIR) \
++ (((uart_IIR) & 0xF) == (RX_DATA_TIMEOUT_INT_MASK))
++
++
++#define HAL_UART_CHECK_THR_EMPTY_INT(idx,uart_IIR) \
++ (((uart_IIR) & 0xF) == (THR_EMPTY_INT_MASK))
++
++
++#define HAL_UART_FIFO_ENABLE(idx) \
++{ \
++ ((_UART_FCR(idx)) |= (FIFO_ENABLE)); \
++}
++
++
++#define HAL_UART_FIFO_DISABLE(idx) \
++{ \
++ ((_UART_FCR(idx)) &= ~(FIFO_ENABLE)); \
++}
++
++
++#define HAL_UART_RESET_RX_FIFO(idx) \
++{ \
++ ((_UART_FCR(idx)) |= (RX_FIFO_RESET)); \
++}
++
++
++#define HAL_UART_RESET_TX_FIFO(idx) \
++{ \
++ ((_UART_FCR(idx)) |= (TX_FIFO_RESET)); \
++}
++
++
++#define HAL_UART_DLAB_ENABLE(idx) \
++{ \
++ ((_UART_LCR(idx)) |= (DLAB_ENABLE)); \
++}
++
++
++#define HAL_UART_DLAB_DISABLE(idx) \
++{ \
++ ((_UART_LCR(idx)) &= ~(DLAB_ENABLE)); \
++}
++
++
++#define HAL_UART_ENABLE_LOOPBACK_MODE(idx) \
++{ \
++ ((_UART_MCR(idx)) |= (UART_MCR_LPBK)); \
++}
++
++
++#define HAL_UART_DISABLE_LOOPBACK_MODE(idx) \
++{ \
++ ((_UART_MCR(idx)) &= ~(UART_MCR_LPBK)); \
++}
++
++
++#define HAL_UART_READ_LINE_STATUS(idx,uart_LSR) \
++{ \
++ ((uart_LSR) = (_UART_LSR(idx))); \
++}
++
++
++#define HAL_UART_WRITE_DLL(idx,dll_value) \
++{ \
++ HAL_UART_DLAB_ENABLE(idx); \
++ _UART_DLL(idx) = (u32)dll_value; \
++ HAL_UART_DLAB_DISABLE(idx); \
++}
++
++
++#define HAL_UART_WRITE_DLM(idx,dlm_value) \
++{ \
++ HAL_UART_DLAB_ENABLE(idx); \
++ _UART_DLM(idx) = (u32)dlm_value; \
++ HAL_UART_DLAB_DISABLE(idx); \
++}
++
++
++#define HAL_UART_WRITE_PSR(idx,psr_value) \
++{ \
++ HAL_UART_DLAB_ENABLE(idx); \
++ _UART_PSR(idx) = (u32)(psr_value & 0x3); \
++ HAL_UART_DLAB_DISABLE(idx); \
++}
++
++
++#define HAL_UART_READ_PSR(idx,psr_value) \
++{ \
++ HAL_UART_DLAB_ENABLE(idx); \
++ (psr_value) = (u32)((_UART_PSR(idx)) & 0x3); \
++ HAL_UART_DLAB_DISABLE(idx); \
++}
++
++
++#define HAL_UART_CHECK_RX_DATA_READY(idx) \
++ (((_UART_LSR(idx)) & _DATA_READY) == (_DATA_READY))
++
++
++#define HAL_UART_CHECK_TX_FIFO_EMPTY(idx) \
++ (((_UART_LSR(idx)) & THR_EMPTY) == (THR_EMPTY))
++
++
++#define HAL_UART_CHECK_TRANSMITTER_EMPTY(idx) \
++ (((_UART_LSR(idx)) & TRANSMITTER_EMPTY) == (TRANSMITTER_EMPTY))
++
++
++#endif // end of #ifndef _STAR_UART_H_
+diff -rupN linux-2.6.35.11/include/asm/arch/star_wdtimer.h linux-2.6.35.11-ts7500/include/asm/arch/star_wdtimer.h
+--- linux-2.6.35.11/include/asm/arch/star_wdtimer.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/arch/star_wdtimer.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,170 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_WATCHDOG_TIMER_H_
++#define _STAR_WATCHDOG_TIMER_H_
++
++
++#include <mach/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define WDTIMER_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_WATCHDOG_TIMER_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define WDTIMER_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_WATCHDOG_TIMER_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define WDTIMER_COUNTER_REG WDTIMER_MEM_MAP_VALUE(0x00)
++#define WDTIMER_AUTO_RELOAD_REG WDTIMER_MEM_MAP_VALUE(0x04)
++#define WDTIMER_COUNTER_RESTART_REG WDTIMER_MEM_MAP_VALUE(0x08)
++#define WDTIMER_CONTROL_REG WDTIMER_MEM_MAP_VALUE(0x0C)
++#define WDTIMER_STATUS_REG WDTIMER_MEM_MAP_VALUE(0x10)
++#define WDTIMER_CLEAR_REG WDTIMER_MEM_MAP_VALUE(0x14)
++#define WDTIMER_INTERRUPT_LENGTH_REG WDTIMER_MEM_MAP_VALUE(0x18)
++
++
++/*
++ * define constants macros
++ */
++#define WDTIMER_ENABLE_BIT (1 << 0)
++#define WDTIMER_SYSTEM_RESET_ENABLE_BIT (1 << 1)
++#define WDTIMER_SYSTEM_INTERRUPT_ENABLE_BIT (1 << 2)
++#define WDTIMER_EXTERNAL_SIGNAL_ENABLE_BIT (1 << 3)
++#define WDTIMER_EXTERNAL_CLOCK_ENABLE_BIT (1 << 4)
++
++
++#define WDTIMER_MAGIC_RESTART_VALUE (0x5AB9)
++
++
++/*
++ * macros declarations
++ */
++#define HAL_WDTIMER_READ_COUNTER(counter) \
++{ \
++ ((counter) = (WDTIMER_COUNTER_REG)); \
++}
++
++
++#define HAL_WDTIMER_WRITE_AUTO_RELOAD_COUNTER(counter) \
++{ \
++ ((WDTIMER_AUTO_RELOAD_REG) = (counter)); \
++}
++
++
++#define HAL_WDTIMER_READ_AUTO_RELOAD_COUNTER(counter) \
++{ \
++ ((counter) = (WDTIMER_AUTO_RELOAD_REG)); \
++}
++
++
++#define HAL_WDTIMER_ENABLE_RESTART_RELOAD() \
++{ \
++ ((WDTIMER_COUNTER_RESTART_REG) = (WDTIMER_MAGIC_RESTART_VALUE)); \
++}
++
++
++#define HAL_WDTIMER_ENABLE() \
++{ \
++ ((WDTIMER_CONTROL_REG) |= (WDTIMER_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_DISABLE() \
++{ \
++ ((WDTIMER_CONTROL_REG) &= ~(WDTIMER_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_ENABLE_SYSTEM_RESET() \
++{ \
++ ((WDTIMER_CONTROL_REG) |= (WDTIMER_SYSTEM_RESET_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_DISABLE_SYSTEM_RESET() \
++{ \
++ ((WDTIMER_CONTROL_REG) &= ~(WDTIMER_SYSTEM_RESET_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_ENABLE_SYSTEM_INTERRUPT() \
++{ \
++ ((WDTIMER_CONTROL_REG) |= (WDTIMER_SYSTEM_INTERRUPT_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_DISABLE_SYSTEM_INTERRUPT() \
++{ \
++ ((WDTIMER_CONTROL_REG) &= ~(WDTIMER_SYSTEM_INTERRUPT_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_ENABLE_EXTERNAL_SIGNAL() \
++{ \
++ ((WDTIMER_CONTROL_REG) |= (WDTIMER_EXTERNAL_SIGNAL_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_DISABLE_EXTERNAL_SIGNAL() \
++{ \
++ ((WDTIMER_CONTROL_REG) &= ~(WDTIMER_EXTERNAL_SIGNAL_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_CLOCK_SOURCE_PCLK() \
++{ \
++ ((WDTIMER_CONTROL_REG) &= ~(WDTIMER_EXTERNAL_CLOCK_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_CLOCK_SOURCE_EXTCLK() \
++{ \
++ ((WDTIMER_CONTROL_REG) |= (WDTIMER_EXTERNAL_CLOCK_ENABLE_BIT)); \
++}
++
++
++#define HAL_WDTIMER_READ_STATUS(status) \
++{ \
++ ((status) = (WDTIMER_STATUS_REG) & 0x00000001); \
++}
++
++
++#define HAL_WDTIMER_CLEAR_STATUS() \
++{ \
++ ((WDTIMER_CLEAR_REG) = (1)); \
++}
++
++
++#define HAL_WDTIMER_WRITE_INTERRUPT_LENGTH(length) \
++{ \
++ ((WDTIMER_INTERRUPT_LENGTH_REG) = (length) & 0x000000FF); \
++}
++
++
++#endif // end of #ifndef _STAR_WATCHDOG_TIMER_H_
+diff -rupN linux-2.6.35.11/include/asm/hardware.h linux-2.6.35.11-ts7500/include/asm/hardware.h
+--- linux-2.6.35.11/include/asm/hardware.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm/hardware.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,18 @@
++/*
++ * linux/include/asm-arm/hardware.h
++ *
++ * Copyright (C) 1996 Russell King
++ *
++ * 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.
++ *
++ * Common hardware definitions
++ */
++
++#ifndef __ASM_HARDWARE_H
++#define __ASM_HARDWARE_H
++
++#include <asm/arch/hardware.h>
++
++#endif
+diff -rupN linux-2.6.35.11/include/asm-arm/arch-str8100/star_nic.h linux-2.6.35.11-ts7500/include/asm-arm/arch-str8100/star_nic.h
+--- linux-2.6.35.11/include/asm-arm/arch-str8100/star_nic.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm-arm/arch-str8100/star_nic.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,346 @@
++/*******************************************************************************
++ *
++ * Copyright (c) 2008 Cavium Networks
++ *
++ * This file 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.
++ *
++ * This file is distributed in the hope that it will be useful,
++ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
++ * NONINFRINGEMENT. See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this file; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
++ * visit http://www.gnu.org/licenses/.
++ *
++ * This file may also be available under a different license from Cavium.
++ * Contact Cavium Networks for more information
++ *
++ ******************************************************************************/
++
++#ifndef _STAR_NIC_H_
++#define _STAR_NIC_H_
++
++
++#include <asm/arch/star_sys_memory_map.h>
++
++
++#if defined(__UBOOT__)
++#define NIC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSPA_NIC_BASE_ADDR + reg_offset)))
++#elif defined(__LINUX__)
++#define NIC_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(SYSVA_NIC_BASE_ADDR + reg_offset)))
++#else
++#error "NO SYSTEM DEFINED"
++#endif
++
++
++/*
++ * define access macros
++ */
++#define NIC_PHY_CONTROL_REG0 NIC_MEM_MAP_VALUE(0x000)
++#define NIC_PHY_CONTROL_REG1 NIC_MEM_MAP_VALUE(0x004)
++
++#define NIC_MAC_CONTROL_REG NIC_MEM_MAP_VALUE(0x008)
++#define NIC_FLOW_CONTROL_CONFIG_REG NIC_MEM_MAP_VALUE(0x00C)
++
++#define NIC_ARL_CONFIG_REG NIC_MEM_MAP_VALUE(0x010)
++
++#define NIC_MY_MAC_HIGH_BYTE_REG NIC_MEM_MAP_VALUE(0x014)
++#define NIC_MY_MAC_LOW_BYTE_REG NIC_MEM_MAP_VALUE(0x018)
++
++#define NIC_HASH_TABLE_CONTROL_REG NIC_MEM_MAP_VALUE(0x01C)
++
++#define NIC_MY_VLANID_CONTROL_REG NIC_MEM_MAP_VALUE(0x020)
++
++#define NIC_MY_VLANID_0_1 NIC_MEM_MAP_VALUE(0x024)
++#define NIC_MY_VLANID_2_3 NIC_MEM_MAP_VALUE(0x028)
++
++#define NIC_DMA_CONFIG_REG NIC_MEM_MAP_VALUE(0x030)
++#define NIC_TX_DMA_CONTROL_REG NIC_MEM_MAP_VALUE(0x034)
++#define NIC_RX_DMA_CONTROL_REG NIC_MEM_MAP_VALUE(0x038)
++#define NIC_TX_DESC_PTR_REG NIC_MEM_MAP_VALUE(0x03C)
++#define NIC_RX_DESC_PTR_REG NIC_MEM_MAP_VALUE(0x040)
++
++#define NIC_TX_DESC_BASE_ADDR_REG NIC_MEM_MAP_VALUE(0x044)
++#define NIC_RX_DESC_BASE_ADDR_REG NIC_MEM_MAP_VALUE(0x048)
++#define NIC_DELAYED_INT_CONFIG_REG NIC_MEM_MAP_VALUE(0x04C)
++
++#define NIC_INT_STATUS_REG NIC_MEM_MAP_VALUE(0x050)
++#define NIC_INT_MASK_REG NIC_MEM_MAP_VALUE(0x054)
++
++#define NIC_TEST_0_REG NIC_MEM_MAP_VALUE(0x058)
++#define NIC_TEST_1_REG NIC_MEM_MAP_VALUE(0x05C)
++
++#define NIC_MIB_RX_OK_PKT_CNTR NIC_MEM_MAP_VALUE(0x100)
++#define NIC_MIB_RX_OK_BYTE_CNTR NIC_MEM_MAP_VALUE(0x104)
++#define NIC_MIB_RX_RUNT_BYTE_CNTR NIC_MEM_MAP_VALUE(0x108)
++#define NIC_MIB_RX_OSIZE_DROP_PKT_CNTR NIC_MEM_MAP_VALUE(0x10C)
++
++#define NIC_MIB_RX_NO_BUF_DROP_PKT_CNTR NIC_MEM_MAP_VALUE(0x110)
++
++#define NIC_MIB_RX_CRC_ERR_PKT_CNTR NIC_MEM_MAP_VALUE(0x114)
++
++#define NIC_MIB_RX_ARL_DROP_PKT_CNTR NIC_MEM_MAP_VALUE(0x118)
++
++#define NIC_MIB_MYVLANID_MISMATCH_DROP_PKT_CNTR NIC_MEM_MAP_VALUE(0x11C)
++
++#define NIC_MIB_RX_CHKSUM_ERR_PKT_CNTR NIC_MEM_MAP_VALUE(0x120)
++
++#define NIC_MIB_RX_PAUSE_FRAME_PKT_CNTR NIC_MEM_MAP_VALUE(0x124)
++
++#define NIC_MIB_TX_OK_PKT_CNTR NIC_MEM_MAP_VALUE(0x128)
++#define NIC_MIB_TX_OK_BYTE_CNTR NIC_MEM_MAP_VALUE(0x12C)
++
++#define NIC_MIB_TX_COLLISION_CNTR NIC_MEM_MAP_VALUE(0x130)
++#define NIC_MIB_TX_PAUSE_FRAME_CNTR NIC_MEM_MAP_VALUE(0x130)
++
++#define NIC_MIB_TX_FIFO_UNDERRUN_RETX_CNTR NIC_MEM_MAP_VALUE(0x134)
++
++
++
++
++/*
++ * define constants macros
++ */
++
++#define NIC_PHY_ADDRESS 1 //the phy addr const value
++#define NIC_PHY_ID 0x0243 //the phy id
++
++#define GW_NIC_MAX_TFD_NUM (32)
++#define GW_NIC_MAX_RFD_NUM (32)
++#define MAX_BUFFERS (64)
++
++
++
++#define MMU_OFF (0)
++#define MMU_ON (1)
++#define OS_NULL (0)
++
++
++#define NET_BUFFER_PACKET_SIZE (512)
++#define NET_BUFFER_SHIFT_BIT_NUM (9) // 2*n9=512
++
++#define MAX_PACKET_LEN (1536)
++
++#define INTERNAL_LOOPBACK_MODE (1)
++#define SOFTWARE_REPEATER_MODE (2)
++
++#define TXTC_INT_BIT (0x08000000)
++#define TX_INSV_BIT (0x04000000)
++
++#define LS_BIT (0x10000000)
++#define FS_BIT (0x20000000)
++#define EOR_BIT (0x40000000)
++#define FS_LS_BIT (0x30000000)
++#define C_BIT (0x80000000)
++#define FS_LS_C_BIT (0xB0000000)
++#define FS_LS_INT_BIT (0x38000000)
++
++
++
++// HASH TABLE CONTROL REGISTER
++#define NIC_HASH_TABLE_BIST_DONE_BIT (0x1 << 17)
++#define NIC_HASH_TABLE_BIST_OK_BIT (0x1 << 16)
++#define NIC_HASH_COMMAND_START_BIT (0x1 << 14)
++#define NIC_HASH_COMMAND_BIT (0x1 << 13)
++#define NIC_HASH_BIT_DATA (0x1 << 12)
++#define NIC_HASH_BIT_ADDRESS_BIT (0x1ff)
++
++
++#define NIC_REG_CNT ((0x48 << 2) + 1)
++
++/*
++ * macro access
++ */
++
++#define GW_NIC_TX_TFD_NEXT(work_tfd_ptr) \
++ work_tfd_ptr = NIC_TX_TFD_Ring.head + (((u32)(work_tfd_ptr - NIC_TX_TFD_Ring.head) + 1) % GW_NIC_MAX_TFD_NUM)
++
++
++#define GW_NIC_TX_TFD_PREVIOUS(work_tfd_ptr) \
++ work_tfd_ptr = NIC_TX_TFD_Ring.head + ((GW_NIC_MAX_TFD_NUM + (u32)(work_tfd_ptr - NIC_TX_TFD_Ring.head) - 1) % GW_NIC_MAX_TFD_NUM)
++
++
++#define GW_NIC_RX_RFD_NEXT(work_rfd_ptr) \
++ work_rfd_ptr = NIC_RX_RFD_Ring.head + (((u32)(work_rfd_ptr - NIC_RX_RFD_Ring.head) + 1) % GW_NIC_MAX_RFD_NUM)
++
++
++#define GW_NIC_RX_RFD_PREVIOUS(work_rfd_ptr) \
++ work_rfd_ptr = NIC_RX_RFD_Ring.head + ((GW_NIC_MAX_RFD_NUM + (u32)(work_rfd_ptr - NIC_RX_RFD_Ring.head) - 1) % GW_NIC_MAX_RFD_NUM)
++
++
++/*
++ * PHY register defines
++ */
++#define PHY_MII_CONTROL_REG_ADDR 0x00
++#define PHY_MII_STATUS_REG_ADDR 0x01
++#define PHY_ID1_REG_ADDR 0x02
++#define PHY_ID2_REG_ADDR 0x03
++#define PHY_AN_ADVERTISEMENT_REG_ADDR 0x04
++#define PHY_AN_REAMOTE_CAP_REG_ADDR 0x05
++
++
++#define PHY_RESERVED1_REG_ADDR 0x10
++#define PHY_RESERVED2_REG_ADDR 0x11
++#define PHY_CH_STATUS_OUTPUT_REG_ADDR 0x12
++#define PHY_RESERVED3_REG_ADDR 0x13
++#define PHY_RESERVED4_REG_ADDR 0x14
++
++
++#define PHY_SPEC_CONTROL_REG_ADDR 0x16
++#define PHY_INTC_CONTROL_STATUS_REG_ADDR 0x17
++
++/*
++ * NIC registers access macros defines
++ */
++
++//0x004
++#define HAL_NIC_WRITE_PHY_CONTROL1(config_value) \
++ ((NIC_PHY_CONTROL_REG1) = (config_value))
++
++#define HAL_NIC_READ_PHY_CONTROL1(config_value) \
++ ((config_value) = (NIC_PHY_CONTROL_REG1))
++
++//0x008
++#define HAL_NIC_WRITE_MAC_CONFIGURATION(config_value) \
++ ((NIC_MAC_CONTROL_REG) = (config_value))
++
++#define HAL_NIC_READ_MAC_CONFIGURATION(config_value) \
++ ((config_value) = (NIC_MAC_CONTROL_REG))
++
++//0x00C
++#define HAL_NIC_WRITE_FLOW_CONTROL_CONFIG(fc_cfg) \
++ ((NIC_FLOW_CONTROL_CONFIG_REG) = (fc_cfg))
++
++#define HAL_NIC_READ_FLOW_CONTROL_CONFIG(fc_cfg) \
++ ((fc_cfg) = (NIC_FLOW_CONTROL_CONFIG_REG))
++
++//0x010
++#define HAL_NIC_WRITE_ARL_CONFIGURATION(cfg) \
++ ((NIC_ARL_CONFIG_REG) = (cfg))
++
++#define HAL_NIC_READ_ARL_CONFIGURATION(cfg) \
++ ((cfg) = (NIC_ARL_CONFIG_REG))
++
++//0x014,
++#define HAL_NIC_WRITE_MY_MAC_HIGH_BYTE(cfg) \
++ ((NIC_MY_MAC_HIGH_BYTE_REG) = (cfg & 0x0000FFFF ) )
++
++#define HAL_NIC_READ_MY_MAC_HIGH_BYTE(cfg) \
++ ((cfg) = (NIC_MY_MAC_HIGH_BYTE_REG & 0x0000FFFF ))
++
++//0x018
++#define HAL_NIC_WRITE_MY_MAC_LOW_BYTE(cfg) \
++ ((NIC_MY_MAC_LOW_BYTE_REG) = (cfg))
++
++#define HAL_NIC_READ_MY_MAC_LOW_BYTE(cfg) \
++ ((cfg) = (NIC_MY_MAC_LOW_BYTE_REG))
++
++//0x03C
++#define HAL_NIC_READ_INTERRUPT_STATUS(int_status) \
++ ((int_status) = (NIC_INT_STATUS_REG))
++
++#define HAL_NIC_CLEAR_ALL_INTERRUPT_STATUS_SOURCES()\
++ ((NIC_INT_STATUS_REG) = (0xFFFFFFFF))
++
++#define HAL_NIC_CLEAR_INTERRUPT_STATUS_SOURCES(source) \
++ ((NIC_INT_STATUS_REG) |= (source))
++
++#define HAL_NIC_CLEAR_INTERRUPT_STATUS_SOURCE_BIT(source_bit_index) \
++ ((NIC_INT_STATUS_REG) |= (1 << (source_bit_index)))
++
++//0x040
++#define HAL_NIC_DISABLE_ALL_INTERRUPT_STATUS_SOURCES() \
++ ((NIC_INT_MASK_REG) = (0xFFFFFFFF))
++
++#define HAL_NIC_ENABLE_ALL_INTERRUPT_STATUS_SOURCES() \
++ ((NIC_INT_MASK_REG) = (0x00000000))
++
++#define HAL_NIC_DISABLE_INTERRUPT_STATUS_SOURCE_BIT(source_bit_index) \
++ ((NIC_INT_MASK_REG) |= (1 << (source_bit_index)))
++
++#define HAL_NIC_ENABLE_INTERRUPT_STATUS_SOURCE_BIT(source_bit_index) \
++ ((NIC_INT_MASK_REG) &= ~(1 << (source_bit_index)))
++
++//0x44
++#define HAL_NIC_WRITE_TEST0_REG(cfg) \
++ ((NIC_TEST_0_REG) = (cfg))
++
++#define HAL_NIC_READ_TEST0_REG(cfg) \
++ ((cfg) = (NIC_TEST_0_REG))
++
++//0x48
++#define HAL_NIC_WRITE_TEST1_REG(cfg) \
++ ((NIC_TEST_1_REG) = (cfg))
++
++#define HAL_NIC_READ_TEST1_REG(cfg) \
++ ((cfg) = (NIC_TEST_1_REG))
++
++
++
++/*
++ * NIC's DMA macros defines
++ */
++#define HAL_NIC_TX_DMA_START() \
++ ((NIC_TX_DMA_CONTROL_REG) = (1))
++
++
++#define HAL_NIC_TX_DMA_STOP() \
++ ((NIC_TX_DMA_CONTROL_REG) = (0))
++
++
++#define HAL_NIC_READ_TX_DMA_STATE(state) \
++ ((state) = (NIC_TX_DMA_CONTROL_REG))
++
++
++#define HAL_NIC_RX_DMA_START() \
++ ((NIC_RX_DMA_CONTROL_REG) = (1))
++
++
++#define HAL_NIC_RX_DMA_STOP() \
++ ((NIC_RX_DMA_CONTROL_REG) = (0))
++
++
++#define HAL_NIC_WRITE_TXSD(tssd_value) \
++ ((NIC_TX_DESC_PTR_REG) = (tssd_value))
++
++
++#define HAL_NIC_READ_TXSD(tssd_value) \
++ ((tssd_value) = (NIC_TX_DESC_PTR_REG))
++
++
++#define HAL_NIC_WRITE_RXSD(fssd_value) \
++ ((NIC_RX_DESC_PTR_REG) = (fssd_value))
++
++
++#define HAL_NIC_READ_RXSD(fssd_value) \
++ ((fssd_value) = (NIC_RX_DESC_PTR_REG))
++
++
++#define HAL_NIC_WRITE_TX_BASE(ts_base_value) \
++ ((NIC_TX_DESC_BASE_ADDR_REG) = (ts_base_value))
++
++
++#define HAL_NIC_READ_TX_BASE(ts_base_value) \
++ ((ts_base_value) = (NIC_TX_DESC_BASE_ADDR_REG))
++
++
++#define HAL_NIC_WRITE_RX_BASE(fs_base_value) \
++ ((NIC_RX_DESC_BASE_ADDR_REG) = (fs_base_value))
++
++
++#define HAL_NIC_READ_RX_BASE(fs_base_value) \
++ ((fs_base_value) = (NIC_RX_DESC_BASE_ADDR_REG))
++
++
++#define HAL_NIC_WRITE_DELAYED_INTERRUPT_CONFIG(delayed_interrupt_config) \
++ ((NIC_DELAYED_INT_CONFIG_REG) = (delayed_interrupt_config))
++
++
++#define HAL_NIC_READ_DELAYED_INTERRUPT_CONFIG(delayed_interrupt_config) \
++ ((delayed_interrupt_config) = (NIC_DELAYED_INT_CONFIG_REG))
++
++#endif // end of #ifndef _STAR_NIC_H_
+diff -rupN linux-2.6.35.11/include/asm-arm/hardware.h linux-2.6.35.11-ts7500/include/asm-arm/hardware.h
+--- linux-2.6.35.11/include/asm-arm/hardware.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm-arm/hardware.h 2011-03-14 11:18:24.000000000 -0400
+@@ -0,0 +1,18 @@
++/*
++ * linux/include/asm-arm/hardware.h
++ *
++ * Copyright (C) 1996 Russell King
++ *
++ * 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.
++ *
++ * Common hardware definitions
++ */
++
++#ifndef __ASM_HARDWARE_H
++#define __ASM_HARDWARE_H
++
++#include <asm/arch/hardware.h>
++
++#endif
+diff -rupN linux-2.6.35.11/include/asm-generic/pci.h linux-2.6.35.11-ts7500/include/asm-generic/pci.h
+--- linux-2.6.35.11/include/asm-generic/pci.h 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/asm-generic/pci.h 2011-03-14 11:18:24.000000000 -0400
+@@ -43,6 +43,15 @@ pcibios_select_root(struct pci_dev *pdev
+ return root;
+ }
+
++#if defined(CONFIG_ARCH_STR9100) || defined(CONFIG_ARCH_STR8100)
++#define HAVE_ARCH_PCI_MWI
++static inline int pcibios_prep_mwi(struct pci_dev *dev)
++{
++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x08);
++ return 0;
++}
++#endif
++
+ #ifndef HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ
+ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+ {
+diff -rupN linux-2.6.35.11/include/linux/decompress/mm.h linux-2.6.35.11-ts7500/include/linux/decompress/mm.h
+--- linux-2.6.35.11/include/linux/decompress/mm.h 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/linux/decompress/mm.h 2011-03-14 11:18:24.000000000 -0400
+@@ -33,7 +33,7 @@ STATIC_RW_DATA int malloc_count;
+ static void *malloc(int size)
+ {
+ void *p;
+-
++
+ if (size < 0)
+ return NULL;
+ if (!malloc_ptr)
+@@ -58,6 +58,7 @@ static void free(void *where)
+ malloc_ptr = free_mem_ptr;
+ }
+
++
+ #define large_malloc(a) malloc(a)
+ #define large_free(a) free(a)
+
+diff -rupN linux-2.6.35.11/include/linux/i2c.h linux-2.6.35.11-ts7500/include/linux/i2c.h
+--- linux-2.6.35.11/include/linux/i2c.h 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/linux/i2c.h 2011-03-14 11:18:24.000000000 -0400
+@@ -334,6 +334,13 @@ struct i2c_algorithm {
+ unsigned short flags, char read_write,
+ u8 command, int size, union i2c_smbus_data *data);
+
++/* Eileen , for linux kernel 2.6.24 , 20080413 */
++/* Lifted from 2.6.24-cavium */
++#ifdef CONFIG_ARCH_STR8100
++ /* --- ioctl like call to set div. parameters. */
++ int (*algo_control)(struct i2c_adapter *, unsigned int, unsigned long);
++#endif
++
+ /* To determine what the adapter supports */
+ u32 (*functionality) (struct i2c_adapter *);
+ };
+diff -rupN linux-2.6.35.11/include/linux/i2c.h.orig linux-2.6.35.11-ts7500/include/linux/i2c.h.orig
+--- linux-2.6.35.11/include/linux/i2c.h.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/linux/i2c.h.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,585 @@
++/* ------------------------------------------------------------------------- */
++/* */
++/* i2c.h - definitions for the i2c-bus interface */
++/* */
++/* ------------------------------------------------------------------------- */
++/* Copyright (C) 1995-2000 Simon G. Vogl
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
++/* ------------------------------------------------------------------------- */
++
++/* With some changes from Kyösti Mälkki <kmalkki at cc.hut.fi> and
++ Frodo Looijaard <frodol at dds.nl> */
++
++#ifndef _LINUX_I2C_H
++#define _LINUX_I2C_H
++
++#include <linux/types.h>
++#ifdef __KERNEL__
++#include <linux/module.h>
++#include <linux/i2c-id.h>
++#include <linux/mod_devicetable.h>
++#include <linux/device.h> /* for struct device */
++#include <linux/sched.h> /* for completion */
++#include <linux/mutex.h>
++#include <linux/of.h> /* for struct device_node */
++
++extern struct bus_type i2c_bus_type;
++
++/* --- General options ------------------------------------------------ */
++
++struct i2c_msg;
++struct i2c_algorithm;
++struct i2c_adapter;
++struct i2c_client;
++struct i2c_driver;
++union i2c_smbus_data;
++struct i2c_board_info;
++
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
++/*
++ * The master routines are the ones normally used to transmit data to devices
++ * on a bus (or read from them). Apart from two basic transfer functions to
++ * transmit one message at a time, a more complex version can be used to
++ * transmit an arbitrary number of messages without interruption.
++ * @count must be be less than 64k since msg.len is u16.
++ */
++extern int i2c_master_send(struct i2c_client *client, const char *buf,
++ int count);
++extern int i2c_master_recv(struct i2c_client *client, char *buf, int count);
++
++/* Transfer num messages.
++ */
++extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
++ int num);
++
++/* This is the very generalized SMBus access routine. You probably do not
++ want to use this, though; one of the functions below may be much easier,
++ and probably just as fast.
++ Note that we use i2c_adapter here, because you do not need a specific
++ smbus adapter to call this function. */
++extern s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
++ unsigned short flags, char read_write, u8 command,
++ int size, union i2c_smbus_data *data);
++
++/* Now follow the 'nice' access routines. These also document the calling
++ conventions of i2c_smbus_xfer. */
++
++extern s32 i2c_smbus_read_byte(struct i2c_client *client);
++extern s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value);
++extern s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command);
++extern s32 i2c_smbus_write_byte_data(struct i2c_client *client,
++ u8 command, u8 value);
++extern s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command);
++extern s32 i2c_smbus_write_word_data(struct i2c_client *client,
++ u8 command, u16 value);
++/* Returns the number of read bytes */
++extern s32 i2c_smbus_read_block_data(struct i2c_client *client,
++ u8 command, u8 *values);
++extern s32 i2c_smbus_write_block_data(struct i2c_client *client,
++ u8 command, u8 length, const u8 *values);
++/* Returns the number of read bytes */
++extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client,
++ u8 command, u8 length, u8 *values);
++extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client,
++ u8 command, u8 length,
++ const u8 *values);
++#endif /* I2C */
++
++/**
++ * struct i2c_driver - represent an I2C device driver
++ * @class: What kind of i2c device we instantiate (for detect)
++ * @attach_adapter: Callback for bus addition (for legacy drivers)
++ * @detach_adapter: Callback for bus removal (for legacy drivers)
++ * @probe: Callback for device binding
++ * @remove: Callback for device unbinding
++ * @shutdown: Callback for device shutdown
++ * @suspend: Callback for device suspend
++ * @resume: Callback for device resume
++ * @command: Callback for bus-wide signaling (optional)
++ * @driver: Device driver model driver
++ * @id_table: List of I2C devices supported by this driver
++ * @detect: Callback for device detection
++ * @address_list: The I2C addresses to probe (for detect)
++ * @clients: List of detected clients we created (for i2c-core use only)
++ *
++ * The driver.owner field should be set to the module owner of this driver.
++ * The driver.name field should be set to the name of this driver.
++ *
++ * For automatic device detection, both @detect and @address_data must
++ * be defined. @class should also be set, otherwise only devices forced
++ * with module parameters will be created. The detect function must
++ * fill at least the name field of the i2c_board_info structure it is
++ * handed upon successful detection, and possibly also the flags field.
++ *
++ * If @detect is missing, the driver will still work fine for enumerated
++ * devices. Detected devices simply won't be supported. This is expected
++ * for the many I2C/SMBus devices which can't be detected reliably, and
++ * the ones which can always be enumerated in practice.
++ *
++ * The i2c_client structure which is handed to the @detect callback is
++ * not a real i2c_client. It is initialized just enough so that you can
++ * call i2c_smbus_read_byte_data and friends on it. Don't do anything
++ * else with it. In particular, calling dev_dbg and friends on it is
++ * not allowed.
++ */
++struct i2c_driver {
++ unsigned int class;
++
++ /* Notifies the driver that a new bus has appeared or is about to be
++ * removed. You should avoid using this if you can, it will probably
++ * be removed in a near future.
++ */
++ int (*attach_adapter)(struct i2c_adapter *);
++ int (*detach_adapter)(struct i2c_adapter *);
++
++ /* Standard driver model interfaces */
++ int (*probe)(struct i2c_client *, const struct i2c_device_id *);
++ int (*remove)(struct i2c_client *);
++
++ /* driver model interfaces that don't relate to enumeration */
++ void (*shutdown)(struct i2c_client *);
++ int (*suspend)(struct i2c_client *, pm_message_t mesg);
++ int (*resume)(struct i2c_client *);
++
++ /* Alert callback, for example for the SMBus alert protocol.
++ * The format and meaning of the data value depends on the protocol.
++ * For the SMBus alert protocol, there is a single bit of data passed
++ * as the alert response's low bit ("event flag").
++ */
++ void (*alert)(struct i2c_client *, unsigned int data);
++
++ /* a ioctl like command that can be used to perform specific functions
++ * with the device.
++ */
++ int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
++
++ struct device_driver driver;
++ const struct i2c_device_id *id_table;
++
++ /* Device detection callback for automatic device creation */
++ int (*detect)(struct i2c_client *, struct i2c_board_info *);
++ const unsigned short *address_list;
++ struct list_head clients;
++};
++#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
++
++/**
++ * struct i2c_client - represent an I2C slave device
++ * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
++ * I2C_CLIENT_PEC indicates it uses SMBus Packet Error Checking
++ * @addr: Address used on the I2C bus connected to the parent adapter.
++ * @name: Indicates the type of the device, usually a chip name that's
++ * generic enough to hide second-sourcing and compatible revisions.
++ * @adapter: manages the bus segment hosting this I2C device
++ * @driver: device's driver, hence pointer to access routines
++ * @dev: Driver model device node for the slave.
++ * @irq: indicates the IRQ generated by this device (if any)
++ * @detected: member of an i2c_driver.clients list or i2c-core's
++ * userspace_devices list
++ *
++ * An i2c_client identifies a single device (i.e. chip) connected to an
++ * i2c bus. The behaviour exposed to Linux is defined by the driver
++ * managing the device.
++ */
++struct i2c_client {
++ unsigned short flags; /* div., see below */
++ unsigned short addr; /* chip address - NOTE: 7bit */
++ /* addresses are stored in the */
++ /* _LOWER_ 7 bits */
++ char name[I2C_NAME_SIZE];
++ struct i2c_adapter *adapter; /* the adapter we sit on */
++ struct i2c_driver *driver; /* and our access routines */
++ struct device dev; /* the device structure */
++ int irq; /* irq issued by device */
++ struct list_head detected;
++};
++#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
++
++extern struct i2c_client *i2c_verify_client(struct device *dev);
++
++static inline struct i2c_client *kobj_to_i2c_client(struct kobject *kobj)
++{
++ struct device * const dev = container_of(kobj, struct device, kobj);
++ return to_i2c_client(dev);
++}
++
++static inline void *i2c_get_clientdata(const struct i2c_client *dev)
++{
++ return dev_get_drvdata(&dev->dev);
++}
++
++static inline void i2c_set_clientdata(struct i2c_client *dev, void *data)
++{
++ dev_set_drvdata(&dev->dev, data);
++}
++
++/**
++ * struct i2c_board_info - template for device creation
++ * @type: chip type, to initialize i2c_client.name
++ * @flags: to initialize i2c_client.flags
++ * @addr: stored in i2c_client.addr
++ * @platform_data: stored in i2c_client.dev.platform_data
++ * @archdata: copied into i2c_client.dev.archdata
++ * @irq: stored in i2c_client.irq
++ *
++ * I2C doesn't actually support hardware probing, although controllers and
++ * devices may be able to use I2C_SMBUS_QUICK to tell whether or not there's
++ * a device at a given address. Drivers commonly need more information than
++ * that, such as chip type, configuration, associated IRQ, and so on.
++ *
++ * i2c_board_info is used to build tables of information listing I2C devices
++ * that are present. This information is used to grow the driver model tree.
++ * For mainboards this is done statically using i2c_register_board_info();
++ * bus numbers identify adapters that aren't yet available. For add-on boards,
++ * i2c_new_device() does this dynamically with the adapter already known.
++ */
++struct i2c_board_info {
++ char type[I2C_NAME_SIZE];
++ unsigned short flags;
++ unsigned short addr;
++ void *platform_data;
++ struct dev_archdata *archdata;
++#ifdef CONFIG_OF
++ struct device_node *of_node;
++#endif
++ int irq;
++};
++
++/**
++ * I2C_BOARD_INFO - macro used to list an i2c device and its address
++ * @dev_type: identifies the device type
++ * @dev_addr: the device's address on the bus.
++ *
++ * This macro initializes essential fields of a struct i2c_board_info,
++ * declaring what has been provided on a particular board. Optional
++ * fields (such as associated irq, or device-specific platform_data)
++ * are provided using conventional syntax.
++ */
++#define I2C_BOARD_INFO(dev_type, dev_addr) \
++ .type = dev_type, .addr = (dev_addr)
++
++
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
++/* Add-on boards should register/unregister their devices; e.g. a board
++ * with integrated I2C, a config eeprom, sensors, and a codec that's
++ * used in conjunction with the primary hardware.
++ */
++extern struct i2c_client *
++i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info);
++
++/* If you don't know the exact address of an I2C device, use this variant
++ * instead, which can probe for device presence in a list of possible
++ * addresses.
++ */
++extern struct i2c_client *
++i2c_new_probed_device(struct i2c_adapter *adap,
++ struct i2c_board_info *info,
++ unsigned short const *addr_list);
++
++/* For devices that use several addresses, use i2c_new_dummy() to make
++ * client handles for the extra addresses.
++ */
++extern struct i2c_client *
++i2c_new_dummy(struct i2c_adapter *adap, u16 address);
++
++extern void i2c_unregister_device(struct i2c_client *);
++#endif /* I2C */
++
++/* Mainboard arch_initcall() code should register all its I2C devices.
++ * This is done at arch_initcall time, before declaring any i2c adapters.
++ * Modules for add-on boards must use other calls.
++ */
++#ifdef CONFIG_I2C_BOARDINFO
++extern int
++i2c_register_board_info(int busnum, struct i2c_board_info const *info,
++ unsigned n);
++#else
++static inline int
++i2c_register_board_info(int busnum, struct i2c_board_info const *info,
++ unsigned n)
++{
++ return 0;
++}
++#endif /* I2C_BOARDINFO */
++
++/*
++ * The following structs are for those who like to implement new bus drivers:
++ * i2c_algorithm is the interface to a class of hardware solutions which can
++ * be addressed using the same bus algorithms - i.e. bit-banging or the PCF8584
++ * to name two of the most common.
++ */
++struct i2c_algorithm {
++ /* If an adapter algorithm can't do I2C-level access, set master_xfer
++ to NULL. If an adapter algorithm can do SMBus access, set
++ smbus_xfer. If set to NULL, the SMBus protocol is simulated
++ using common I2C messages */
++ /* master_xfer should return the number of messages successfully
++ processed, or a negative value on error */
++ int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,
++ int num);
++ int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,
++ unsigned short flags, char read_write,
++ u8 command, int size, union i2c_smbus_data *data);
++
++ /* To determine what the adapter supports */
++ u32 (*functionality) (struct i2c_adapter *);
++};
++
++/*
++ * i2c_adapter is the structure used to identify a physical i2c bus along
++ * with the access algorithms necessary to access it.
++ */
++struct i2c_adapter {
++ struct module *owner;
++ unsigned int id;
++ unsigned int class; /* classes to allow probing for */
++ const struct i2c_algorithm *algo; /* the algorithm to access the bus */
++ void *algo_data;
++
++ /* data fields that are valid for all devices */
++ struct rt_mutex bus_lock;
++
++ int timeout; /* in jiffies */
++ int retries;
++ struct device dev; /* the adapter device */
++
++ int nr;
++ char name[48];
++ struct completion dev_released;
++
++ struct list_head userspace_clients;
++};
++#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
++
++static inline void *i2c_get_adapdata(const struct i2c_adapter *dev)
++{
++ return dev_get_drvdata(&dev->dev);
++}
++
++static inline void i2c_set_adapdata(struct i2c_adapter *dev, void *data)
++{
++ dev_set_drvdata(&dev->dev, data);
++}
++
++/**
++ * i2c_lock_adapter - Prevent access to an I2C bus segment
++ * @adapter: Target I2C bus segment
++ */
++static inline void i2c_lock_adapter(struct i2c_adapter *adapter)
++{
++ rt_mutex_lock(&adapter->bus_lock);
++}
++
++/**
++ * i2c_unlock_adapter - Reauthorize access to an I2C bus segment
++ * @adapter: Target I2C bus segment
++ */
++static inline void i2c_unlock_adapter(struct i2c_adapter *adapter)
++{
++ rt_mutex_unlock(&adapter->bus_lock);
++}
++
++/*flags for the client struct: */
++#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */
++#define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */
++ /* Must equal I2C_M_TEN below */
++#define I2C_CLIENT_WAKE 0x80 /* for board_info; true iff can wake */
++
++/* i2c adapter classes (bitmask) */
++#define I2C_CLASS_HWMON (1<<0) /* lm_sensors, ... */
++#define I2C_CLASS_TV_ANALOG (1<<1) /* bttv + friends */
++#define I2C_CLASS_TV_DIGITAL (1<<2) /* dvb cards */
++#define I2C_CLASS_DDC (1<<3) /* DDC bus on graphics adapters */
++#define I2C_CLASS_SPD (1<<7) /* SPD EEPROMs and similar */
++
++/* Internal numbers to terminate lists */
++#define I2C_CLIENT_END 0xfffeU
++
++/* The numbers to use to set I2C bus address */
++#define ANY_I2C_BUS 0xffff
++
++/* Construct an I2C_CLIENT_END-terminated array of i2c addresses */
++#define I2C_ADDRS(addr, addrs...) \
++ ((const unsigned short []){ addr, ## addrs, I2C_CLIENT_END })
++
++
++/* ----- functions exported by i2c.o */
++
++/* administration...
++ */
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
++extern int i2c_add_adapter(struct i2c_adapter *);
++extern int i2c_del_adapter(struct i2c_adapter *);
++extern int i2c_add_numbered_adapter(struct i2c_adapter *);
++
++extern int i2c_register_driver(struct module *, struct i2c_driver *);
++extern void i2c_del_driver(struct i2c_driver *);
++
++static inline int i2c_add_driver(struct i2c_driver *driver)
++{
++ return i2c_register_driver(THIS_MODULE, driver);
++}
++
++extern struct i2c_client *i2c_use_client(struct i2c_client *client);
++extern void i2c_release_client(struct i2c_client *client);
++
++/* call the i2c_client->command() of all attached clients with
++ * the given arguments */
++extern void i2c_clients_command(struct i2c_adapter *adap,
++ unsigned int cmd, void *arg);
++
++extern struct i2c_adapter *i2c_get_adapter(int id);
++extern void i2c_put_adapter(struct i2c_adapter *adap);
++
++
++/* Return the functionality mask */
++static inline u32 i2c_get_functionality(struct i2c_adapter *adap)
++{
++ return adap->algo->functionality(adap);
++}
++
++/* Return 1 if adapter supports everything we need, 0 if not. */
++static inline int i2c_check_functionality(struct i2c_adapter *adap, u32 func)
++{
++ return (func & i2c_get_functionality(adap)) == func;
++}
++
++/* Return the adapter number for a specific adapter */
++static inline int i2c_adapter_id(struct i2c_adapter *adap)
++{
++ return adap->nr;
++}
++#endif /* I2C */
++#endif /* __KERNEL__ */
++
++/**
++ * struct i2c_msg - an I2C transaction segment beginning with START
++ * @addr: Slave address, either seven or ten bits. When this is a ten
++ * bit address, I2C_M_TEN must be set in @flags and the adapter
++ * must support I2C_FUNC_10BIT_ADDR.
++ * @flags: I2C_M_RD is handled by all adapters. No other flags may be
++ * provided unless the adapter exported the relevant I2C_FUNC_*
++ * flags through i2c_check_functionality().
++ * @len: Number of data bytes in @buf being read from or written to the
++ * I2C slave address. For read transactions where I2C_M_RECV_LEN
++ * is set, the caller guarantees that this buffer can hold up to
++ * 32 bytes in addition to the initial length byte sent by the
++ * slave (plus, if used, the SMBus PEC); and this value will be
++ * incremented by the number of block data bytes received.
++ * @buf: The buffer into which data is read, or from which it's written.
++ *
++ * An i2c_msg is the low level representation of one segment of an I2C
++ * transaction. It is visible to drivers in the @i2c_transfer() procedure,
++ * to userspace from i2c-dev, and to I2C adapter drivers through the
++ * @i2c_adapter. at master_xfer() method.
++ *
++ * Except when I2C "protocol mangling" is used, all I2C adapters implement
++ * the standard rules for I2C transactions. Each transaction begins with a
++ * START. That is followed by the slave address, and a bit encoding read
++ * versus write. Then follow all the data bytes, possibly including a byte
++ * with SMBus PEC. The transfer terminates with a NAK, or when all those
++ * bytes have been transferred and ACKed. If this is the last message in a
++ * group, it is followed by a STOP. Otherwise it is followed by the next
++ * @i2c_msg transaction segment, beginning with a (repeated) START.
++ *
++ * Alternatively, when the adapter supports I2C_FUNC_PROTOCOL_MANGLING then
++ * passing certain @flags may have changed those standard protocol behaviors.
++ * Those flags are only for use with broken/nonconforming slaves, and with
++ * adapters which are known to support the specific mangling options they
++ * need (one or more of IGNORE_NAK, NO_RD_ACK, NOSTART, and REV_DIR_ADDR).
++ */
++struct i2c_msg {
++ __u16 addr; /* slave address */
++ __u16 flags;
++#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */
++#define I2C_M_RD 0x0001 /* read data, from slave to master */
++#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */
++#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
++#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
++#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
++#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
++ __u16 len; /* msg length */
++ __u8 *buf; /* pointer to msg data */
++};
++
++/* To determine what functionality is present */
++
++#define I2C_FUNC_I2C 0x00000001
++#define I2C_FUNC_10BIT_ADDR 0x00000002
++#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_NOSTART etc. */
++#define I2C_FUNC_SMBUS_PEC 0x00000008
++#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */
++#define I2C_FUNC_SMBUS_QUICK 0x00010000
++#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
++#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
++#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000
++#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000
++#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000
++#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000
++#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000
++#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000
++#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
++#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */
++#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */
++
++#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
++ I2C_FUNC_SMBUS_WRITE_BYTE)
++#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \
++ I2C_FUNC_SMBUS_WRITE_BYTE_DATA)
++#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \
++ I2C_FUNC_SMBUS_WRITE_WORD_DATA)
++#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
++ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)
++#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
++ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)
++
++#define I2C_FUNC_SMBUS_EMUL (I2C_FUNC_SMBUS_QUICK | \
++ I2C_FUNC_SMBUS_BYTE | \
++ I2C_FUNC_SMBUS_BYTE_DATA | \
++ I2C_FUNC_SMBUS_WORD_DATA | \
++ I2C_FUNC_SMBUS_PROC_CALL | \
++ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
++ I2C_FUNC_SMBUS_I2C_BLOCK | \
++ I2C_FUNC_SMBUS_PEC)
++
++/*
++ * Data for SMBus Messages
++ */
++#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */
++union i2c_smbus_data {
++ __u8 byte;
++ __u16 word;
++ __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */
++ /* and one more for user-space compatibility */
++};
++
++/* i2c_smbus_xfer read or write markers */
++#define I2C_SMBUS_READ 1
++#define I2C_SMBUS_WRITE 0
++
++/* SMBus transaction types (size parameter in the above functions)
++ Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */
++#define I2C_SMBUS_QUICK 0
++#define I2C_SMBUS_BYTE 1
++#define I2C_SMBUS_BYTE_DATA 2
++#define I2C_SMBUS_WORD_DATA 3
++#define I2C_SMBUS_PROC_CALL 4
++#define I2C_SMBUS_BLOCK_DATA 5
++#define I2C_SMBUS_I2C_BLOCK_BROKEN 6
++#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
++#define I2C_SMBUS_I2C_BLOCK_DATA 8
++
++#endif /* _LINUX_I2C_H */
+diff -rupN linux-2.6.35.11/include/linux/spi/spi.h linux-2.6.35.11-ts7500/include/linux/spi/spi.h
+--- linux-2.6.35.11/include/linux/spi/spi.h 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/linux/spi/spi.h 2011-03-14 11:18:24.000000000 -0400
+@@ -432,6 +432,11 @@ struct spi_transfer {
+ u16 delay_usecs;
+ u32 speed_hz;
+
++#ifdef CONFIG_ARCH_STR8100
++ unsigned last_in_message_list;
++#endif
++
++
+ struct list_head transfer_list;
+ };
+
+diff -rupN linux-2.6.35.11/include/linux/spi/spi.h.orig linux-2.6.35.11-ts7500/include/linux/spi/spi.h.orig
+--- linux-2.6.35.11/include/linux/spi/spi.h.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/linux/spi/spi.h.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,779 @@
++/*
++ * Copyright (C) 2005 David Brownell
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifndef __LINUX_SPI_H
++#define __LINUX_SPI_H
++
++#include <linux/device.h>
++#include <linux/mod_devicetable.h>
++#include <linux/slab.h>
++
++/*
++ * INTERFACES between SPI master-side drivers and SPI infrastructure.
++ * (There's no SPI slave support for Linux yet...)
++ */
++extern struct bus_type spi_bus_type;
++
++/**
++ * struct spi_device - Master side proxy for an SPI slave device
++ * @dev: Driver model representation of the device.
++ * @master: SPI controller used with the device.
++ * @max_speed_hz: Maximum clock rate to be used with this chip
++ * (on this board); may be changed by the device's driver.
++ * The spi_transfer.speed_hz can override this for each transfer.
++ * @chip_select: Chipselect, distinguishing chips handled by @master.
++ * @mode: The spi mode defines how data is clocked out and in.
++ * This may be changed by the device's driver.
++ * The "active low" default for chipselect mode can be overridden
++ * (by specifying SPI_CS_HIGH) as can the "MSB first" default for
++ * each word in a transfer (by specifying SPI_LSB_FIRST).
++ * @bits_per_word: Data transfers involve one or more words; word sizes
++ * like eight or 12 bits are common. In-memory wordsizes are
++ * powers of two bytes (e.g. 20 bit samples use 32 bits).
++ * This may be changed by the device's driver, or left at the
++ * default (0) indicating protocol words are eight bit bytes.
++ * The spi_transfer.bits_per_word can override this for each transfer.
++ * @irq: Negative, or the number passed to request_irq() to receive
++ * interrupts from this device.
++ * @controller_state: Controller's runtime state
++ * @controller_data: Board-specific definitions for controller, such as
++ * FIFO initialization parameters; from board_info.controller_data
++ * @modalias: Name of the driver to use with this device, or an alias
++ * for that name. This appears in the sysfs "modalias" attribute
++ * for driver coldplugging, and in uevents used for hotplugging
++ *
++ * A @spi_device is used to interchange data between an SPI slave
++ * (usually a discrete chip) and CPU memory.
++ *
++ * In @dev, the platform_data is used to hold information about this
++ * device that's meaningful to the device's protocol driver, but not
++ * to its controller. One example might be an identifier for a chip
++ * variant with slightly different functionality; another might be
++ * information about how this particular board wires the chip's pins.
++ */
++struct spi_device {
++ struct device dev;
++ struct spi_master *master;
++ u32 max_speed_hz;
++ u8 chip_select;
++ u8 mode;
++#define SPI_CPHA 0x01 /* clock phase */
++#define SPI_CPOL 0x02 /* clock polarity */
++#define SPI_MODE_0 (0|0) /* (original MicroWire) */
++#define SPI_MODE_1 (0|SPI_CPHA)
++#define SPI_MODE_2 (SPI_CPOL|0)
++#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
++#define SPI_CS_HIGH 0x04 /* chipselect active high? */
++#define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */
++#define SPI_3WIRE 0x10 /* SI/SO signals shared */
++#define SPI_LOOP 0x20 /* loopback mode */
++#define SPI_NO_CS 0x40 /* 1 dev/bus, no chipselect */
++#define SPI_READY 0x80 /* slave pulls low to pause */
++ u8 bits_per_word;
++ int irq;
++ void *controller_state;
++ void *controller_data;
++ char modalias[SPI_NAME_SIZE];
++
++ /*
++ * likely need more hooks for more protocol options affecting how
++ * the controller talks to each chip, like:
++ * - memory packing (12 bit samples into low bits, others zeroed)
++ * - priority
++ * - drop chipselect after each word
++ * - chipselect delays
++ * - ...
++ */
++};
++
++static inline struct spi_device *to_spi_device(struct device *dev)
++{
++ return dev ? container_of(dev, struct spi_device, dev) : NULL;
++}
++
++/* most drivers won't need to care about device refcounting */
++static inline struct spi_device *spi_dev_get(struct spi_device *spi)
++{
++ return (spi && get_device(&spi->dev)) ? spi : NULL;
++}
++
++static inline void spi_dev_put(struct spi_device *spi)
++{
++ if (spi)
++ put_device(&spi->dev);
++}
++
++/* ctldata is for the bus_master driver's runtime state */
++static inline void *spi_get_ctldata(struct spi_device *spi)
++{
++ return spi->controller_state;
++}
++
++static inline void spi_set_ctldata(struct spi_device *spi, void *state)
++{
++ spi->controller_state = state;
++}
++
++/* device driver data */
++
++static inline void spi_set_drvdata(struct spi_device *spi, void *data)
++{
++ dev_set_drvdata(&spi->dev, data);
++}
++
++static inline void *spi_get_drvdata(struct spi_device *spi)
++{
++ return dev_get_drvdata(&spi->dev);
++}
++
++struct spi_message;
++
++
++
++/**
++ * struct spi_driver - Host side "protocol" driver
++ * @id_table: List of SPI devices supported by this driver
++ * @probe: Binds this driver to the spi device. Drivers can verify
++ * that the device is actually present, and may need to configure
++ * characteristics (such as bits_per_word) which weren't needed for
++ * the initial configuration done during system setup.
++ * @remove: Unbinds this driver from the spi device
++ * @shutdown: Standard shutdown callback used during system state
++ * transitions such as powerdown/halt and kexec
++ * @suspend: Standard suspend callback used during system state transitions
++ * @resume: Standard resume callback used during system state transitions
++ * @driver: SPI device drivers should initialize the name and owner
++ * field of this structure.
++ *
++ * This represents the kind of device driver that uses SPI messages to
++ * interact with the hardware at the other end of a SPI link. It's called
++ * a "protocol" driver because it works through messages rather than talking
++ * directly to SPI hardware (which is what the underlying SPI controller
++ * driver does to pass those messages). These protocols are defined in the
++ * specification for the device(s) supported by the driver.
++ *
++ * As a rule, those device protocols represent the lowest level interface
++ * supported by a driver, and it will support upper level interfaces too.
++ * Examples of such upper levels include frameworks like MTD, networking,
++ * MMC, RTC, filesystem character device nodes, and hardware monitoring.
++ */
++struct spi_driver {
++ const struct spi_device_id *id_table;
++ int (*probe)(struct spi_device *spi);
++ int (*remove)(struct spi_device *spi);
++ void (*shutdown)(struct spi_device *spi);
++ int (*suspend)(struct spi_device *spi, pm_message_t mesg);
++ int (*resume)(struct spi_device *spi);
++ struct device_driver driver;
++};
++
++static inline struct spi_driver *to_spi_driver(struct device_driver *drv)
++{
++ return drv ? container_of(drv, struct spi_driver, driver) : NULL;
++}
++
++extern int spi_register_driver(struct spi_driver *sdrv);
++
++/**
++ * spi_unregister_driver - reverse effect of spi_register_driver
++ * @sdrv: the driver to unregister
++ * Context: can sleep
++ */
++static inline void spi_unregister_driver(struct spi_driver *sdrv)
++{
++ if (sdrv)
++ driver_unregister(&sdrv->driver);
++}
++
++
++/**
++ * struct spi_master - interface to SPI master controller
++ * @dev: device interface to this driver
++ * @bus_num: board-specific (and often SOC-specific) identifier for a
++ * given SPI controller.
++ * @num_chipselect: chipselects are used to distinguish individual
++ * SPI slaves, and are numbered from zero to num_chipselects.
++ * each slave has a chipselect signal, but it's common that not
++ * every chipselect is connected to a slave.
++ * @dma_alignment: SPI controller constraint on DMA buffers alignment.
++ * @mode_bits: flags understood by this controller driver
++ * @flags: other constraints relevant to this driver
++ * @setup: updates the device mode and clocking records used by a
++ * device's SPI controller; protocol code may call this. This
++ * must fail if an unrecognized or unsupported mode is requested.
++ * It's always safe to call this unless transfers are pending on
++ * the device whose settings are being modified.
++ * @transfer: adds a message to the controller's transfer queue.
++ * @cleanup: frees controller-specific state
++ *
++ * Each SPI master controller can communicate with one or more @spi_device
++ * children. These make a small bus, sharing MOSI, MISO and SCK signals
++ * but not chip select signals. Each device may be configured to use a
++ * different clock rate, since those shared signals are ignored unless
++ * the chip is selected.
++ *
++ * The driver for an SPI controller manages access to those devices through
++ * a queue of spi_message transactions, copying data between CPU memory and
++ * an SPI slave device. For each such message it queues, it calls the
++ * message's completion function when the transaction completes.
++ */
++struct spi_master {
++ struct device dev;
++
++ /* other than negative (== assign one dynamically), bus_num is fully
++ * board-specific. usually that simplifies to being SOC-specific.
++ * example: one SOC has three SPI controllers, numbered 0..2,
++ * and one board's schematics might show it using SPI-2. software
++ * would normally use bus_num=2 for that controller.
++ */
++ s16 bus_num;
++
++ /* chipselects will be integral to many controllers; some others
++ * might use board-specific GPIOs.
++ */
++ u16 num_chipselect;
++
++ /* some SPI controllers pose alignment requirements on DMAable
++ * buffers; let protocol drivers know about these requirements.
++ */
++ u16 dma_alignment;
++
++ /* spi_device.mode flags understood by this controller driver */
++ u16 mode_bits;
++
++ /* other constraints relevant to this driver */
++ u16 flags;
++#define SPI_MASTER_HALF_DUPLEX BIT(0) /* can't do full duplex */
++#define SPI_MASTER_NO_RX BIT(1) /* can't do buffer read */
++#define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */
++
++ /* Setup mode and clock, etc (spi driver may call many times).
++ *
++ * IMPORTANT: this may be called when transfers to another
++ * device are active. DO NOT UPDATE SHARED REGISTERS in ways
++ * which could break those transfers.
++ */
++ int (*setup)(struct spi_device *spi);
++
++ /* bidirectional bulk transfers
++ *
++ * + The transfer() method may not sleep; its main role is
++ * just to add the message to the queue.
++ * + For now there's no remove-from-queue operation, or
++ * any other request management
++ * + To a given spi_device, message queueing is pure fifo
++ *
++ * + The master's main job is to process its message queue,
++ * selecting a chip then transferring data
++ * + If there are multiple spi_device children, the i/o queue
++ * arbitration algorithm is unspecified (round robin, fifo,
++ * priority, reservations, preemption, etc)
++ *
++ * + Chipselect stays active during the entire message
++ * (unless modified by spi_transfer.cs_change != 0).
++ * + The message transfers use clock and SPI mode parameters
++ * previously established by setup() for this device
++ */
++ int (*transfer)(struct spi_device *spi,
++ struct spi_message *mesg);
++
++ /* called on release() to free memory provided by spi_master */
++ void (*cleanup)(struct spi_device *spi);
++};
++
++static inline void *spi_master_get_devdata(struct spi_master *master)
++{
++ return dev_get_drvdata(&master->dev);
++}
++
++static inline void spi_master_set_devdata(struct spi_master *master, void *data)
++{
++ dev_set_drvdata(&master->dev, data);
++}
++
++static inline struct spi_master *spi_master_get(struct spi_master *master)
++{
++ if (!master || !get_device(&master->dev))
++ return NULL;
++ return master;
++}
++
++static inline void spi_master_put(struct spi_master *master)
++{
++ if (master)
++ put_device(&master->dev);
++}
++
++
++/* the spi driver core manages memory for the spi_master classdev */
++extern struct spi_master *
++spi_alloc_master(struct device *host, unsigned size);
++
++extern int spi_register_master(struct spi_master *master);
++extern void spi_unregister_master(struct spi_master *master);
++
++extern struct spi_master *spi_busnum_to_master(u16 busnum);
++
++/*---------------------------------------------------------------------------*/
++
++/*
++ * I/O INTERFACE between SPI controller and protocol drivers
++ *
++ * Protocol drivers use a queue of spi_messages, each transferring data
++ * between the controller and memory buffers.
++ *
++ * The spi_messages themselves consist of a series of read+write transfer
++ * segments. Those segments always read the same number of bits as they
++ * write; but one or the other is easily ignored by passing a null buffer
++ * pointer. (This is unlike most types of I/O API, because SPI hardware
++ * is full duplex.)
++ *
++ * NOTE: Allocation of spi_transfer and spi_message memory is entirely
++ * up to the protocol driver, which guarantees the integrity of both (as
++ * well as the data buffers) for as long as the message is queued.
++ */
++
++/**
++ * struct spi_transfer - a read/write buffer pair
++ * @tx_buf: data to be written (dma-safe memory), or NULL
++ * @rx_buf: data to be read (dma-safe memory), or NULL
++ * @tx_dma: DMA address of tx_buf, if @spi_message.is_dma_mapped
++ * @rx_dma: DMA address of rx_buf, if @spi_message.is_dma_mapped
++ * @len: size of rx and tx buffers (in bytes)
++ * @speed_hz: Select a speed other than the device default for this
++ * transfer. If 0 the default (from @spi_device) is used.
++ * @bits_per_word: select a bits_per_word other than the device default
++ * for this transfer. If 0 the default (from @spi_device) is used.
++ * @cs_change: affects chipselect after this transfer completes
++ * @delay_usecs: microseconds to delay after this transfer before
++ * (optionally) changing the chipselect status, then starting
++ * the next transfer or completing this @spi_message.
++ * @transfer_list: transfers are sequenced through @spi_message.transfers
++ *
++ * SPI transfers always write the same number of bytes as they read.
++ * Protocol drivers should always provide @rx_buf and/or @tx_buf.
++ * In some cases, they may also want to provide DMA addresses for
++ * the data being transferred; that may reduce overhead, when the
++ * underlying driver uses dma.
++ *
++ * If the transmit buffer is null, zeroes will be shifted out
++ * while filling @rx_buf. If the receive buffer is null, the data
++ * shifted in will be discarded. Only "len" bytes shift out (or in).
++ * It's an error to try to shift out a partial word. (For example, by
++ * shifting out three bytes with word size of sixteen or twenty bits;
++ * the former uses two bytes per word, the latter uses four bytes.)
++ *
++ * In-memory data values are always in native CPU byte order, translated
++ * from the wire byte order (big-endian except with SPI_LSB_FIRST). So
++ * for example when bits_per_word is sixteen, buffers are 2N bytes long
++ * (@len = 2N) and hold N sixteen bit words in CPU byte order.
++ *
++ * When the word size of the SPI transfer is not a power-of-two multiple
++ * of eight bits, those in-memory words include extra bits. In-memory
++ * words are always seen by protocol drivers as right-justified, so the
++ * undefined (rx) or unused (tx) bits are always the most significant bits.
++ *
++ * All SPI transfers start with the relevant chipselect active. Normally
++ * it stays selected until after the last transfer in a message. Drivers
++ * can affect the chipselect signal using cs_change.
++ *
++ * (i) If the transfer isn't the last one in the message, this flag is
++ * used to make the chipselect briefly go inactive in the middle of the
++ * message. Toggling chipselect in this way may be needed to terminate
++ * a chip command, letting a single spi_message perform all of group of
++ * chip transactions together.
++ *
++ * (ii) When the transfer is the last one in the message, the chip may
++ * stay selected until the next transfer. On multi-device SPI busses
++ * with nothing blocking messages going to other devices, this is just
++ * a performance hint; starting a message to another device deselects
++ * this one. But in other cases, this can be used to ensure correctness.
++ * Some devices need protocol transactions to be built from a series of
++ * spi_message submissions, where the content of one message is determined
++ * by the results of previous messages and where the whole transaction
++ * ends when the chipselect goes intactive.
++ *
++ * The code that submits an spi_message (and its spi_transfers)
++ * to the lower layers is responsible for managing its memory.
++ * Zero-initialize every field you don't set up explicitly, to
++ * insulate against future API updates. After you submit a message
++ * and its transfers, ignore them until its completion callback.
++ */
++struct spi_transfer {
++ /* it's ok if tx_buf == rx_buf (right?)
++ * for MicroWire, one buffer must be null
++ * buffers must work with dma_*map_single() calls, unless
++ * spi_message.is_dma_mapped reports a pre-existing mapping
++ */
++ const void *tx_buf;
++ void *rx_buf;
++ unsigned len;
++
++ dma_addr_t tx_dma;
++ dma_addr_t rx_dma;
++
++ unsigned cs_change:1;
++ u8 bits_per_word;
++ u16 delay_usecs;
++ u32 speed_hz;
++
++ struct list_head transfer_list;
++};
++
++/**
++ * struct spi_message - one multi-segment SPI transaction
++ * @transfers: list of transfer segments in this transaction
++ * @spi: SPI device to which the transaction is queued
++ * @is_dma_mapped: if true, the caller provided both dma and cpu virtual
++ * addresses for each transfer buffer
++ * @complete: called to report transaction completions
++ * @context: the argument to complete() when it's called
++ * @actual_length: the total number of bytes that were transferred in all
++ * successful segments
++ * @status: zero for success, else negative errno
++ * @queue: for use by whichever driver currently owns the message
++ * @state: for use by whichever driver currently owns the message
++ *
++ * A @spi_message is used to execute an atomic sequence of data transfers,
++ * each represented by a struct spi_transfer. The sequence is "atomic"
++ * in the sense that no other spi_message may use that SPI bus until that
++ * sequence completes. On some systems, many such sequences can execute as
++ * as single programmed DMA transfer. On all systems, these messages are
++ * queued, and might complete after transactions to other devices. Messages
++ * sent to a given spi_device are alway executed in FIFO order.
++ *
++ * The code that submits an spi_message (and its spi_transfers)
++ * to the lower layers is responsible for managing its memory.
++ * Zero-initialize every field you don't set up explicitly, to
++ * insulate against future API updates. After you submit a message
++ * and its transfers, ignore them until its completion callback.
++ */
++struct spi_message {
++ struct list_head transfers;
++
++ struct spi_device *spi;
++
++ unsigned is_dma_mapped:1;
++
++ /* REVISIT: we might want a flag affecting the behavior of the
++ * last transfer ... allowing things like "read 16 bit length L"
++ * immediately followed by "read L bytes". Basically imposing
++ * a specific message scheduling algorithm.
++ *
++ * Some controller drivers (message-at-a-time queue processing)
++ * could provide that as their default scheduling algorithm. But
++ * others (with multi-message pipelines) could need a flag to
++ * tell them about such special cases.
++ */
++
++ /* completion is reported through a callback */
++ void (*complete)(void *context);
++ void *context;
++ unsigned actual_length;
++ int status;
++
++ /* for optional use by whatever driver currently owns the
++ * spi_message ... between calls to spi_async and then later
++ * complete(), that's the spi_master controller driver.
++ */
++ struct list_head queue;
++ void *state;
++};
++
++static inline void spi_message_init(struct spi_message *m)
++{
++ memset(m, 0, sizeof *m);
++ INIT_LIST_HEAD(&m->transfers);
++}
++
++static inline void
++spi_message_add_tail(struct spi_transfer *t, struct spi_message *m)
++{
++ list_add_tail(&t->transfer_list, &m->transfers);
++}
++
++static inline void
++spi_transfer_del(struct spi_transfer *t)
++{
++ list_del(&t->transfer_list);
++}
++
++/* It's fine to embed message and transaction structures in other data
++ * structures so long as you don't free them while they're in use.
++ */
++
++static inline struct spi_message *spi_message_alloc(unsigned ntrans, gfp_t flags)
++{
++ struct spi_message *m;
++
++ m = kzalloc(sizeof(struct spi_message)
++ + ntrans * sizeof(struct spi_transfer),
++ flags);
++ if (m) {
++ int i;
++ struct spi_transfer *t = (struct spi_transfer *)(m + 1);
++
++ INIT_LIST_HEAD(&m->transfers);
++ for (i = 0; i < ntrans; i++, t++)
++ spi_message_add_tail(t, m);
++ }
++ return m;
++}
++
++static inline void spi_message_free(struct spi_message *m)
++{
++ kfree(m);
++}
++
++extern int spi_setup(struct spi_device *spi);
++extern int spi_async(struct spi_device *spi, struct spi_message *message);
++
++/*---------------------------------------------------------------------------*/
++
++/* All these synchronous SPI transfer routines are utilities layered
++ * over the core async transfer primitive. Here, "synchronous" means
++ * they will sleep uninterruptibly until the async transfer completes.
++ */
++
++extern int spi_sync(struct spi_device *spi, struct spi_message *message);
++
++/**
++ * spi_write - SPI synchronous write
++ * @spi: device to which data will be written
++ * @buf: data buffer
++ * @len: data buffer size
++ * Context: can sleep
++ *
++ * This writes the buffer and returns zero or a negative error code.
++ * Callable only from contexts that can sleep.
++ */
++static inline int
++spi_write(struct spi_device *spi, const u8 *buf, size_t len)
++{
++ struct spi_transfer t = {
++ .tx_buf = buf,
++ .len = len,
++ };
++ struct spi_message m;
++
++ spi_message_init(&m);
++ spi_message_add_tail(&t, &m);
++ return spi_sync(spi, &m);
++}
++
++/**
++ * spi_read - SPI synchronous read
++ * @spi: device from which data will be read
++ * @buf: data buffer
++ * @len: data buffer size
++ * Context: can sleep
++ *
++ * This reads the buffer and returns zero or a negative error code.
++ * Callable only from contexts that can sleep.
++ */
++static inline int
++spi_read(struct spi_device *spi, u8 *buf, size_t len)
++{
++ struct spi_transfer t = {
++ .rx_buf = buf,
++ .len = len,
++ };
++ struct spi_message m;
++
++ spi_message_init(&m);
++ spi_message_add_tail(&t, &m);
++ return spi_sync(spi, &m);
++}
++
++/* this copies txbuf and rxbuf data; for small transfers only! */
++extern int spi_write_then_read(struct spi_device *spi,
++ const u8 *txbuf, unsigned n_tx,
++ u8 *rxbuf, unsigned n_rx);
++
++/**
++ * spi_w8r8 - SPI synchronous 8 bit write followed by 8 bit read
++ * @spi: device with which data will be exchanged
++ * @cmd: command to be written before data is read back
++ * Context: can sleep
++ *
++ * This returns the (unsigned) eight bit number returned by the
++ * device, or else a negative error code. Callable only from
++ * contexts that can sleep.
++ */
++static inline ssize_t spi_w8r8(struct spi_device *spi, u8 cmd)
++{
++ ssize_t status;
++ u8 result;
++
++ status = spi_write_then_read(spi, &cmd, 1, &result, 1);
++
++ /* return negative errno or unsigned value */
++ return (status < 0) ? status : result;
++}
++
++/**
++ * spi_w8r16 - SPI synchronous 8 bit write followed by 16 bit read
++ * @spi: device with which data will be exchanged
++ * @cmd: command to be written before data is read back
++ * Context: can sleep
++ *
++ * This returns the (unsigned) sixteen bit number returned by the
++ * device, or else a negative error code. Callable only from
++ * contexts that can sleep.
++ *
++ * The number is returned in wire-order, which is at least sometimes
++ * big-endian.
++ */
++static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd)
++{
++ ssize_t status;
++ u16 result;
++
++ status = spi_write_then_read(spi, &cmd, 1, (u8 *) &result, 2);
++
++ /* return negative errno or unsigned value */
++ return (status < 0) ? status : result;
++}
++
++/*---------------------------------------------------------------------------*/
++
++/*
++ * INTERFACE between board init code and SPI infrastructure.
++ *
++ * No SPI driver ever sees these SPI device table segments, but
++ * it's how the SPI core (or adapters that get hotplugged) grows
++ * the driver model tree.
++ *
++ * As a rule, SPI devices can't be probed. Instead, board init code
++ * provides a table listing the devices which are present, with enough
++ * information to bind and set up the device's driver. There's basic
++ * support for nonstatic configurations too; enough to handle adding
++ * parport adapters, or microcontrollers acting as USB-to-SPI bridges.
++ */
++
++/**
++ * struct spi_board_info - board-specific template for a SPI device
++ * @modalias: Initializes spi_device.modalias; identifies the driver.
++ * @platform_data: Initializes spi_device.platform_data; the particular
++ * data stored there is driver-specific.
++ * @controller_data: Initializes spi_device.controller_data; some
++ * controllers need hints about hardware setup, e.g. for DMA.
++ * @irq: Initializes spi_device.irq; depends on how the board is wired.
++ * @max_speed_hz: Initializes spi_device.max_speed_hz; based on limits
++ * from the chip datasheet and board-specific signal quality issues.
++ * @bus_num: Identifies which spi_master parents the spi_device; unused
++ * by spi_new_device(), and otherwise depends on board wiring.
++ * @chip_select: Initializes spi_device.chip_select; depends on how
++ * the board is wired.
++ * @mode: Initializes spi_device.mode; based on the chip datasheet, board
++ * wiring (some devices support both 3WIRE and standard modes), and
++ * possibly presence of an inverter in the chipselect path.
++ *
++ * When adding new SPI devices to the device tree, these structures serve
++ * as a partial device template. They hold information which can't always
++ * be determined by drivers. Information that probe() can establish (such
++ * as the default transfer wordsize) is not included here.
++ *
++ * These structures are used in two places. Their primary role is to
++ * be stored in tables of board-specific device descriptors, which are
++ * declared early in board initialization and then used (much later) to
++ * populate a controller's device tree after the that controller's driver
++ * initializes. A secondary (and atypical) role is as a parameter to
++ * spi_new_device() call, which happens after those controller drivers
++ * are active in some dynamic board configuration models.
++ */
++struct spi_board_info {
++ /* the device name and module name are coupled, like platform_bus;
++ * "modalias" is normally the driver name.
++ *
++ * platform_data goes to spi_device.dev.platform_data,
++ * controller_data goes to spi_device.controller_data,
++ * irq is copied too
++ */
++ char modalias[SPI_NAME_SIZE];
++ const void *platform_data;
++ void *controller_data;
++ int irq;
++
++ /* slower signaling on noisy or low voltage boards */
++ u32 max_speed_hz;
++
++
++ /* bus_num is board specific and matches the bus_num of some
++ * spi_master that will probably be registered later.
++ *
++ * chip_select reflects how this chip is wired to that master;
++ * it's less than num_chipselect.
++ */
++ u16 bus_num;
++ u16 chip_select;
++
++ /* mode becomes spi_device.mode, and is essential for chips
++ * where the default of SPI_CS_HIGH = 0 is wrong.
++ */
++ u8 mode;
++
++ /* ... may need additional spi_device chip config data here.
++ * avoid stuff protocol drivers can set; but include stuff
++ * needed to behave without being bound to a driver:
++ * - quirks like clock rate mattering when not selected
++ */
++};
++
++#ifdef CONFIG_SPI
++extern int
++spi_register_board_info(struct spi_board_info const *info, unsigned n);
++#else
++/* board init code may ignore whether SPI is configured or not */
++static inline int
++spi_register_board_info(struct spi_board_info const *info, unsigned n)
++ { return 0; }
++#endif
++
++
++/* If you're hotplugging an adapter with devices (parport, usb, etc)
++ * use spi_new_device() to describe each device. You can also call
++ * spi_unregister_device() to start making that device vanish, but
++ * normally that would be handled by spi_unregister_master().
++ *
++ * You can also use spi_alloc_device() and spi_add_device() to use a two
++ * stage registration sequence for each spi_device. This gives the caller
++ * some more control over the spi_device structure before it is registered,
++ * but requires that caller to initialize fields that would otherwise
++ * be defined using the board info.
++ */
++extern struct spi_device *
++spi_alloc_device(struct spi_master *master);
++
++extern int
++spi_add_device(struct spi_device *spi);
++
++extern struct spi_device *
++spi_new_device(struct spi_master *, struct spi_board_info *);
++
++static inline void
++spi_unregister_device(struct spi_device *spi)
++{
++ if (spi)
++ device_unregister(&spi->dev);
++}
++
++extern const struct spi_device_id *
++spi_get_device_id(const struct spi_device *sdev);
++
++#endif /* __LINUX_SPI_H */
+diff -rupN linux-2.6.35.11/include/linux/sysctl.h linux-2.6.35.11-ts7500/include/linux/sysctl.h
+--- linux-2.6.35.11/include/linux/sysctl.h 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/include/linux/sysctl.h 2011-03-14 11:18:24.000000000 -0400
+@@ -847,6 +847,9 @@ enum {
+ DEV_MAC_HID=5,
+ DEV_SCSI=6,
+ DEV_IPMI=7,
++#ifdef CONFIG_ARCH_STR8100
++ DEV_I2C=8,
++#endif
+ };
+
+ /* /proc/sys/dev/cdrom */
+@@ -917,6 +920,14 @@ enum {
+ DEV_IPMI_POWEROFF_POWERCYCLE=1,
+ };
+
++#ifdef CONFIG_ARCH_STR8100
++enum {
++ DEV_I2C_CLOCK=1,
++ DEV_I2C_DEBUG=2,
++ DEV_I2C_END=3
++};
++#endif
++
+ /* /proc/sys/abi */
+ enum
+ {
+diff -rupN linux-2.6.35.11/init/do_mounts_rd.c linux-2.6.35.11-ts7500/init/do_mounts_rd.c
+--- linux-2.6.35.11/init/do_mounts_rd.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/init/do_mounts_rd.c 2011-03-14 11:18:24.000000000 -0400
+@@ -168,6 +168,8 @@ int __init rd_load_image(char *from)
+ char rotator[4] = { '|' , '/' , '-' , '\\' };
+ #endif
+
++ printk("rd_load_image()\n");
++
+ out_fd = sys_open("/dev/ram", O_RDWR, 0);
+ if (out_fd < 0)
+ goto out;
+@@ -224,7 +226,11 @@ int __init rd_load_image(char *from)
+ goto done;
+ }
+
++#ifdef CONFIG_ARCH_STR8100
++ buf = kmalloc(BLOCK_SIZE<<6, GFP_KERNEL);
++#else
+ buf = kmalloc(BLOCK_SIZE, GFP_KERNEL);
++#endif
+ if (!buf) {
+ printk(KERN_ERR "RAMDISK: could not allocate buffer\n");
+ goto done;
+@@ -232,7 +238,11 @@ int __init rd_load_image(char *from)
+
+ printk(KERN_NOTICE "RAMDISK: Loading %dKiB [%ld disk%s] into ram disk... ",
+ nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : "");
++#ifdef CONFIG_ARCH_STR8100
++ for (i = 0, disk = 1; i < (nblocks>>6); i++) {
++#else
+ for (i = 0, disk = 1; i < nblocks; i++) {
++#endif
+ if (i && (i % devblocks == 0)) {
+ printk("done disk #%d.\n", disk++);
+ rotate = 0;
+@@ -248,8 +258,13 @@ int __init rd_load_image(char *from)
+ }
+ printk("Loading disk #%d... ", disk);
+ }
++#ifdef CONFIG_ARCH_STR8100
++ sys_read(in_fd, buf, BLOCK_SIZE<<6);
++ sys_write(out_fd, buf, BLOCK_SIZE<<6);
++#else
+ sys_read(in_fd, buf, BLOCK_SIZE);
+ sys_write(out_fd, buf, BLOCK_SIZE);
++#endif
+ #if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES)
+ if (!(i % 16)) {
+ printk("%c\b", rotator[rotate & 0x3]);
+diff -rupN linux-2.6.35.11/init/initramfs.c linux-2.6.35.11-ts7500/init/initramfs.c
+--- linux-2.6.35.11/init/initramfs.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/init/initramfs.c 2011-03-14 11:18:24.000000000 -0400
+@@ -464,6 +464,7 @@ static char * __init unpack_to_rootfs(ch
+ this_header = saved_offset + my_inptr;
+ buf += my_inptr;
+ len -= my_inptr;
++ break;
+ }
+ dir_utime();
+ kfree(name_buf);
+diff -rupN linux-2.6.35.11/init/main.c linux-2.6.35.11-ts7500/init/main.c
+--- linux-2.6.35.11/init/main.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/init/main.c 2011-03-14 11:18:24.000000000 -0400
+@@ -525,6 +525,7 @@ void __init __weak thread_info_cache_ini
+ */
+ static void __init mm_init(void)
+ {
++
+ /*
+ * page_cgroup requires countinous pages as memmap
+ * and it's bigger than MAX_ORDER unless SPARSEMEM.
+@@ -541,12 +542,15 @@ asmlinkage void __init start_kernel(void
+ char * command_line;
+ extern struct kernel_param __start___param[], __stop___param[];
+
++ printk("start_kernel()\n");
++
+ smp_setup_processor_id();
+
+ /*
+ * Need to run as early as possible, to initialize the
+ * lockdep hash:
+ */
++
+ lockdep_init();
+ debug_objects_early_init();
+
+@@ -703,9 +707,7 @@ asmlinkage void __init start_kernel(void
+
+ acpi_early_init(); /* before LAPIC and SMP init */
+ sfi_init_late();
+-
+ ftrace_init();
+-
+ /* Do the rest non-__init'ed, we're now alive */
+ rest_init();
+ }
+@@ -779,9 +781,14 @@ extern initcall_t __initcall_start[], __
+ static void __init do_initcalls(void)
+ {
+ initcall_t *fn;
++ int i;
+
+ for (fn = __early_initcall_end; fn < __initcall_end; fn++)
++ {
++ // printk("Calling do_one_initcall(0x%08lX)\n", *fn);
++
+ do_one_initcall(*fn);
++ }
+
+ /* Make sure there is no pending stuff from the initcall sequence */
+ flush_scheduled_work();
+@@ -837,7 +844,7 @@ static noinline int init_post(void)
+
+ current->signal->flags |= SIGNAL_UNKILLABLE;
+
+- if (ramdisk_execute_command) {
++ if (ramdisk_execute_command) {
+ run_init_process(ramdisk_execute_command);
+ printk(KERN_WARNING "Failed to execute %s\n",
+ ramdisk_execute_command);
+@@ -849,8 +856,8 @@ static noinline int init_post(void)
+ * The Bourne shell can be used instead of init if we are
+ * trying to recover a really broken machine.
+ */
+- if (execute_command) {
+- run_init_process(execute_command);
++ if (execute_command) {
++ run_init_process(execute_command);
+ printk(KERN_WARNING "Failed to execute %s. Attempting "
+ "defaults...\n", execute_command);
+ }
+diff -rupN linux-2.6.35.11/init/main.c.orig linux-2.6.35.11-ts7500/init/main.c.orig
+--- linux-2.6.35.11/init/main.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/init/main.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,931 @@
++/*
++ * linux/init/main.c
++ *
++ * Copyright (C) 1991, 1992 Linus Torvalds
++ *
++ * GK 2/5/95 - Changed to support mounting root fs via NFS
++ * Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96
++ * Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96
++ * Simplified starting of init: Michael A. Griffith <grif at acm.org>
++ */
++
++#include <linux/types.h>
++#include <linux/module.h>
++#include <linux/proc_fs.h>
++#include <linux/kernel.h>
++#include <linux/syscalls.h>
++#include <linux/stackprotector.h>
++#include <linux/string.h>
++#include <linux/ctype.h>
++#include <linux/delay.h>
++#include <linux/ioport.h>
++#include <linux/init.h>
++#include <linux/smp_lock.h>
++#include <linux/initrd.h>
++#include <linux/bootmem.h>
++#include <linux/acpi.h>
++#include <linux/tty.h>
++#include <linux/percpu.h>
++#include <linux/kmod.h>
++#include <linux/vmalloc.h>
++#include <linux/kernel_stat.h>
++#include <linux/start_kernel.h>
++#include <linux/security.h>
++#include <linux/smp.h>
++#include <linux/workqueue.h>
++#include <linux/profile.h>
++#include <linux/rcupdate.h>
++#include <linux/moduleparam.h>
++#include <linux/kallsyms.h>
++#include <linux/writeback.h>
++#include <linux/cpu.h>
++#include <linux/cpuset.h>
++#include <linux/cgroup.h>
++#include <linux/efi.h>
++#include <linux/tick.h>
++#include <linux/interrupt.h>
++#include <linux/taskstats_kern.h>
++#include <linux/delayacct.h>
++#include <linux/unistd.h>
++#include <linux/rmap.h>
++#include <linux/mempolicy.h>
++#include <linux/key.h>
++#include <linux/buffer_head.h>
++#include <linux/page_cgroup.h>
++#include <linux/debug_locks.h>
++#include <linux/debugobjects.h>
++#include <linux/lockdep.h>
++#include <linux/kmemleak.h>
++#include <linux/pid_namespace.h>
++#include <linux/device.h>
++#include <linux/kthread.h>
++#include <linux/sched.h>
++#include <linux/signal.h>
++#include <linux/idr.h>
++#include <linux/kgdb.h>
++#include <linux/ftrace.h>
++#include <linux/async.h>
++#include <linux/kmemcheck.h>
++#include <linux/kmemtrace.h>
++#include <linux/sfi.h>
++#include <linux/shmem_fs.h>
++#include <linux/slab.h>
++#include <trace/boot.h>
++
++#include <asm/io.h>
++#include <asm/bugs.h>
++#include <asm/setup.h>
++#include <asm/sections.h>
++#include <asm/cacheflush.h>
++
++#ifdef CONFIG_X86_LOCAL_APIC
++#include <asm/smp.h>
++#endif
++
++static int kernel_init(void *);
++
++extern void init_IRQ(void);
++extern void fork_init(unsigned long);
++extern void mca_init(void);
++extern void sbus_init(void);
++extern void prio_tree_init(void);
++extern void radix_tree_init(void);
++extern void free_initmem(void);
++#ifndef CONFIG_DEBUG_RODATA
++static inline void mark_rodata_ro(void) { }
++#endif
++
++#ifdef CONFIG_TC
++extern void tc_init(void);
++#endif
++
++enum system_states system_state __read_mostly;
++EXPORT_SYMBOL(system_state);
++
++/*
++ * Boot command-line arguments
++ */
++#define MAX_INIT_ARGS CONFIG_INIT_ENV_ARG_LIMIT
++#define MAX_INIT_ENVS CONFIG_INIT_ENV_ARG_LIMIT
++
++extern void time_init(void);
++/* Default late time init is NULL. archs can override this later. */
++void (*__initdata late_time_init)(void);
++extern void softirq_init(void);
++
++/* Untouched command line saved by arch-specific code. */
++char __initdata boot_command_line[COMMAND_LINE_SIZE];
++/* Untouched saved command line (eg. for /proc) */
++char *saved_command_line;
++/* Command line for parameter parsing */
++static char *static_command_line;
++
++static char *execute_command;
++static char *ramdisk_execute_command;
++
++#ifdef CONFIG_SMP
++/* Setup configured maximum number of CPUs to activate */
++unsigned int setup_max_cpus = NR_CPUS;
++EXPORT_SYMBOL(setup_max_cpus);
++
++
++/*
++ * Setup routine for controlling SMP activation
++ *
++ * Command-line option of "nosmp" or "maxcpus=0" will disable SMP
++ * activation entirely (the MPS table probe still happens, though).
++ *
++ * Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
++ * greater than 0, limits the maximum number of CPUs activated in
++ * SMP mode to <NUM>.
++ */
++
++void __weak arch_disable_smp_support(void) { }
++
++static int __init nosmp(char *str)
++{
++ setup_max_cpus = 0;
++ arch_disable_smp_support();
++
++ return 0;
++}
++
++early_param("nosmp", nosmp);
++
++/* this is hard limit */
++static int __init nrcpus(char *str)
++{
++ int nr_cpus;
++
++ get_option(&str, &nr_cpus);
++ if (nr_cpus > 0 && nr_cpus < nr_cpu_ids)
++ nr_cpu_ids = nr_cpus;
++
++ return 0;
++}
++
++early_param("nr_cpus", nrcpus);
++
++static int __init maxcpus(char *str)
++{
++ get_option(&str, &setup_max_cpus);
++ if (setup_max_cpus == 0)
++ arch_disable_smp_support();
++
++ return 0;
++}
++
++early_param("maxcpus", maxcpus);
++#else
++static const unsigned int setup_max_cpus = NR_CPUS;
++#endif
++
++/*
++ * If set, this is an indication to the drivers that reset the underlying
++ * device before going ahead with the initialization otherwise driver might
++ * rely on the BIOS and skip the reset operation.
++ *
++ * This is useful if kernel is booting in an unreliable environment.
++ * For ex. kdump situaiton where previous kernel has crashed, BIOS has been
++ * skipped and devices will be in unknown state.
++ */
++unsigned int reset_devices;
++EXPORT_SYMBOL(reset_devices);
++
++static int __init set_reset_devices(char *str)
++{
++ reset_devices = 1;
++ return 1;
++}
++
++__setup("reset_devices", set_reset_devices);
++
++static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
++char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
++static const char *panic_later, *panic_param;
++
++extern struct obs_kernel_param __setup_start[], __setup_end[];
++
++static int __init obsolete_checksetup(char *line)
++{
++ struct obs_kernel_param *p;
++ int had_early_param = 0;
++
++ p = __setup_start;
++ do {
++ int n = strlen(p->str);
++ if (!strncmp(line, p->str, n)) {
++ if (p->early) {
++ /* Already done in parse_early_param?
++ * (Needs exact match on param part).
++ * Keep iterating, as we can have early
++ * params and __setups of same names 8( */
++ if (line[n] == '\0' || line[n] == '=')
++ had_early_param = 1;
++ } else if (!p->setup_func) {
++ printk(KERN_WARNING "Parameter %s is obsolete,"
++ " ignored\n", p->str);
++ return 1;
++ } else if (p->setup_func(line + n))
++ return 1;
++ }
++ p++;
++ } while (p < __setup_end);
++
++ return had_early_param;
++}
++
++/*
++ * This should be approx 2 Bo*oMips to start (note initial shift), and will
++ * still work even if initially too large, it will just take slightly longer
++ */
++unsigned long loops_per_jiffy = (1<<12);
++
++EXPORT_SYMBOL(loops_per_jiffy);
++
++static int __init debug_kernel(char *str)
++{
++ console_loglevel = 10;
++ return 0;
++}
++
++static int __init quiet_kernel(char *str)
++{
++ console_loglevel = 4;
++ return 0;
++}
++
++early_param("debug", debug_kernel);
++early_param("quiet", quiet_kernel);
++
++static int __init loglevel(char *str)
++{
++ get_option(&str, &console_loglevel);
++ return 0;
++}
++
++early_param("loglevel", loglevel);
++
++/*
++ * Unknown boot options get handed to init, unless they look like
++ * unused parameters (modprobe will find them in /proc/cmdline).
++ */
++static int __init unknown_bootoption(char *param, char *val)
++{
++ /* Change NUL term back to "=", to make "param" the whole string. */
++ if (val) {
++ /* param=val or param="val"? */
++ if (val == param+strlen(param)+1)
++ val[-1] = '=';
++ else if (val == param+strlen(param)+2) {
++ val[-2] = '=';
++ memmove(val-1, val, strlen(val)+1);
++ val--;
++ } else
++ BUG();
++ }
++
++ /* Handle obsolete-style parameters */
++ if (obsolete_checksetup(param))
++ return 0;
++
++ /* Unused module parameter. */
++ if (strchr(param, '.') && (!val || strchr(param, '.') < val))
++ return 0;
++
++ if (panic_later)
++ return 0;
++
++ if (val) {
++ /* Environment option */
++ unsigned int i;
++ for (i = 0; envp_init[i]; i++) {
++ if (i == MAX_INIT_ENVS) {
++ panic_later = "Too many boot env vars at `%s'";
++ panic_param = param;
++ }
++ if (!strncmp(param, envp_init[i], val - param))
++ break;
++ }
++ envp_init[i] = param;
++ } else {
++ /* Command line option */
++ unsigned int i;
++ for (i = 0; argv_init[i]; i++) {
++ if (i == MAX_INIT_ARGS) {
++ panic_later = "Too many boot init vars at `%s'";
++ panic_param = param;
++ }
++ }
++ argv_init[i] = param;
++ }
++ return 0;
++}
++
++#ifdef CONFIG_DEBUG_PAGEALLOC
++int __read_mostly debug_pagealloc_enabled = 0;
++#endif
++
++static int __init init_setup(char *str)
++{
++ unsigned int i;
++
++ execute_command = str;
++ /*
++ * In case LILO is going to boot us with default command line,
++ * it prepends "auto" before the whole cmdline which makes
++ * the shell think it should execute a script with such name.
++ * So we ignore all arguments entered _before_ init=... [MJ]
++ */
++ for (i = 1; i < MAX_INIT_ARGS; i++)
++ argv_init[i] = NULL;
++ return 1;
++}
++__setup("init=", init_setup);
++
++static int __init rdinit_setup(char *str)
++{
++ unsigned int i;
++
++ ramdisk_execute_command = str;
++ /* See "auto" comment in init_setup */
++ for (i = 1; i < MAX_INIT_ARGS; i++)
++ argv_init[i] = NULL;
++ return 1;
++}
++__setup("rdinit=", rdinit_setup);
++
++#ifndef CONFIG_SMP
++
++#ifdef CONFIG_X86_LOCAL_APIC
++static void __init smp_init(void)
++{
++ APIC_init_uniprocessor();
++}
++#else
++#define smp_init() do { } while (0)
++#endif
++
++static inline void setup_nr_cpu_ids(void) { }
++static inline void smp_prepare_cpus(unsigned int maxcpus) { }
++
++#else
++
++/* Setup number of possible processor ids */
++int nr_cpu_ids __read_mostly = NR_CPUS;
++EXPORT_SYMBOL(nr_cpu_ids);
++
++/* An arch may set nr_cpu_ids earlier if needed, so this would be redundant */
++static void __init setup_nr_cpu_ids(void)
++{
++ nr_cpu_ids = find_last_bit(cpumask_bits(cpu_possible_mask),NR_CPUS) + 1;
++}
++
++/* Called by boot processor to activate the rest. */
++static void __init smp_init(void)
++{
++ unsigned int cpu;
++
++ /* FIXME: This should be done in userspace --RR */
++ for_each_present_cpu(cpu) {
++ if (num_online_cpus() >= setup_max_cpus)
++ break;
++ if (!cpu_online(cpu))
++ cpu_up(cpu);
++ }
++
++ /* Any cleanup work */
++ printk(KERN_INFO "Brought up %ld CPUs\n", (long)num_online_cpus());
++ smp_cpus_done(setup_max_cpus);
++}
++
++#endif
++
++/*
++ * We need to store the untouched command line for future reference.
++ * We also need to store the touched command line since the parameter
++ * parsing is performed in place, and we should allow a component to
++ * store reference of name/value for future reference.
++ */
++static void __init setup_command_line(char *command_line)
++{
++ saved_command_line = alloc_bootmem(strlen (boot_command_line)+1);
++ static_command_line = alloc_bootmem(strlen (command_line)+1);
++ strcpy (saved_command_line, boot_command_line);
++ strcpy (static_command_line, command_line);
++}
++
++/*
++ * We need to finalize in a non-__init function or else race conditions
++ * between the root thread and the init thread may cause start_kernel to
++ * be reaped by free_initmem before the root thread has proceeded to
++ * cpu_idle.
++ *
++ * gcc-3.4 accidentally inlines this function, so use noinline.
++ */
++
++static __initdata DECLARE_COMPLETION(kthreadd_done);
++
++static noinline void __init_refok rest_init(void)
++ __releases(kernel_lock)
++{
++ int pid;
++
++ rcu_scheduler_starting();
++ /*
++ * We need to spawn init first so that it obtains pid 1, however
++ * the init task will end up wanting to create kthreads, which, if
++ * we schedule it before we create kthreadd, will OOPS.
++ */
++ kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
++ numa_default_policy();
++ pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
++ rcu_read_lock();
++ kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
++ rcu_read_unlock();
++ complete(&kthreadd_done);
++ unlock_kernel();
++
++ /*
++ * The boot idle thread must execute schedule()
++ * at least once to get things moving:
++ */
++ init_idle_bootup_task(current);
++ preempt_enable_no_resched();
++ schedule();
++ preempt_disable();
++
++ /* Call into cpu_idle with preempt disabled */
++ cpu_idle();
++}
++
++/* Check for early params. */
++static int __init do_early_param(char *param, char *val)
++{
++ struct obs_kernel_param *p;
++
++ for (p = __setup_start; p < __setup_end; p++) {
++ if ((p->early && strcmp(param, p->str) == 0) ||
++ (strcmp(param, "console") == 0 &&
++ strcmp(p->str, "earlycon") == 0)
++ ) {
++ if (p->setup_func(val) != 0)
++ printk(KERN_WARNING
++ "Malformed early option '%s'\n", param);
++ }
++ }
++ /* We accept everything at this stage. */
++ return 0;
++}
++
++void __init parse_early_options(char *cmdline)
++{
++ parse_args("early options", cmdline, NULL, 0, do_early_param);
++}
++
++/* Arch code calls this early on, or if not, just before other parsing. */
++void __init parse_early_param(void)
++{
++ static __initdata int done = 0;
++ static __initdata char tmp_cmdline[COMMAND_LINE_SIZE];
++
++ if (done)
++ return;
++
++ /* All fall through to do_early_param. */
++ strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
++ parse_early_options(tmp_cmdline);
++ done = 1;
++}
++
++/*
++ * Activate the first processor.
++ */
++
++static void __init boot_cpu_init(void)
++{
++ int cpu = smp_processor_id();
++ /* Mark the boot cpu "present", "online" etc for SMP and UP case */
++ set_cpu_online(cpu, true);
++ set_cpu_active(cpu, true);
++ set_cpu_present(cpu, true);
++ set_cpu_possible(cpu, true);
++}
++
++void __init __weak smp_setup_processor_id(void)
++{
++}
++
++void __init __weak thread_info_cache_init(void)
++{
++}
++
++/*
++ * Set up kernel memory allocators
++ */
++static void __init mm_init(void)
++{
++ /*
++ * page_cgroup requires countinous pages as memmap
++ * and it's bigger than MAX_ORDER unless SPARSEMEM.
++ */
++ page_cgroup_init_flatmem();
++ mem_init();
++ kmem_cache_init();
++ pgtable_cache_init();
++ vmalloc_init();
++}
++
++asmlinkage void __init start_kernel(void)
++{
++ char * command_line;
++ extern struct kernel_param __start___param[], __stop___param[];
++
++ smp_setup_processor_id();
++
++ /*
++ * Need to run as early as possible, to initialize the
++ * lockdep hash:
++ */
++ lockdep_init();
++ debug_objects_early_init();
++
++ /*
++ * Set up the the initial canary ASAP:
++ */
++ boot_init_stack_canary();
++
++ cgroup_init_early();
++
++ local_irq_disable();
++ early_boot_irqs_off();
++ early_init_irq_lock_class();
++
++/*
++ * Interrupts are still disabled. Do necessary setups, then
++ * enable them
++ */
++ lock_kernel();
++ tick_init();
++ boot_cpu_init();
++ page_address_init();
++ printk(KERN_NOTICE "%s", linux_banner);
++ setup_arch(&command_line);
++ mm_init_owner(&init_mm, &init_task);
++ setup_command_line(command_line);
++ setup_nr_cpu_ids();
++ setup_per_cpu_areas();
++ smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
++
++ build_all_zonelists(NULL);
++ page_alloc_init();
++
++ printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);
++ parse_early_param();
++ parse_args("Booting kernel", static_command_line, __start___param,
++ __stop___param - __start___param,
++ &unknown_bootoption);
++ /*
++ * These use large bootmem allocations and must precede
++ * kmem_cache_init()
++ */
++ pidhash_init();
++ vfs_caches_init_early();
++ sort_main_extable();
++ trap_init();
++ mm_init();
++ /*
++ * Set up the scheduler prior starting any interrupts (such as the
++ * timer interrupt). Full topology setup happens at smp_init()
++ * time - but meanwhile we still have a functioning scheduler.
++ */
++ sched_init();
++ /*
++ * Disable preemption - early bootup scheduling is extremely
++ * fragile until we cpu_idle() for the first time.
++ */
++ preempt_disable();
++ if (!irqs_disabled()) {
++ printk(KERN_WARNING "start_kernel(): bug: interrupts were "
++ "enabled *very* early, fixing it\n");
++ local_irq_disable();
++ }
++ rcu_init();
++ radix_tree_init();
++ /* init some links before init_ISA_irqs() */
++ early_irq_init();
++ init_IRQ();
++ prio_tree_init();
++ init_timers();
++ hrtimers_init();
++ softirq_init();
++ timekeeping_init();
++ time_init();
++ profile_init();
++ if (!irqs_disabled())
++ printk(KERN_CRIT "start_kernel(): bug: interrupts were "
++ "enabled early\n");
++ early_boot_irqs_on();
++ local_irq_enable();
++
++ /* Interrupts are enabled now so all GFP allocations are safe. */
++ gfp_allowed_mask = __GFP_BITS_MASK;
++
++ kmem_cache_init_late();
++
++ /*
++ * HACK ALERT! This is early. We're enabling the console before
++ * we've done PCI setups etc, and console_init() must be aware of
++ * this. But we do want output early, in case something goes wrong.
++ */
++ console_init();
++ if (panic_later)
++ panic(panic_later, panic_param);
++
++ lockdep_info();
++
++ /*
++ * Need to run this when irqs are enabled, because it wants
++ * to self-test [hard/soft]-irqs on/off lock inversion bugs
++ * too:
++ */
++ locking_selftest();
++
++#ifdef CONFIG_BLK_DEV_INITRD
++ if (initrd_start && !initrd_below_start_ok &&
++ page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
++ printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
++ "disabling it.\n",
++ page_to_pfn(virt_to_page((void *)initrd_start)),
++ min_low_pfn);
++ initrd_start = 0;
++ }
++#endif
++ page_cgroup_init();
++ enable_debug_pagealloc();
++ kmemtrace_init();
++ kmemleak_init();
++ debug_objects_mem_init();
++ idr_init_cache();
++ setup_per_cpu_pageset();
++ numa_policy_init();
++ if (late_time_init)
++ late_time_init();
++ sched_clock_init();
++ calibrate_delay();
++ pidmap_init();
++ anon_vma_init();
++#ifdef CONFIG_X86
++ if (efi_enabled)
++ efi_enter_virtual_mode();
++#endif
++ thread_info_cache_init();
++ cred_init();
++ fork_init(totalram_pages);
++ proc_caches_init();
++ buffer_init();
++ key_init();
++ security_init();
++ dbg_late_init();
++ vfs_caches_init(totalram_pages);
++ signals_init();
++ /* rootfs populating might need page-writeback */
++ page_writeback_init();
++#ifdef CONFIG_PROC_FS
++ proc_root_init();
++#endif
++ cgroup_init();
++ cpuset_init();
++ taskstats_init_early();
++ delayacct_init();
++
++ check_bugs();
++
++ acpi_early_init(); /* before LAPIC and SMP init */
++ sfi_init_late();
++
++ ftrace_init();
++
++ /* Do the rest non-__init'ed, we're now alive */
++ rest_init();
++}
++
++/* Call all constructor functions linked into the kernel. */
++static void __init do_ctors(void)
++{
++#ifdef CONFIG_CONSTRUCTORS
++ ctor_fn_t *fn = (ctor_fn_t *) __ctors_start;
++
++ for (; fn < (ctor_fn_t *) __ctors_end; fn++)
++ (*fn)();
++#endif
++}
++
++int initcall_debug;
++core_param(initcall_debug, initcall_debug, bool, 0644);
++
++static char msgbuf[64];
++static struct boot_trace_call call;
++static struct boot_trace_ret ret;
++
++int do_one_initcall(initcall_t fn)
++{
++ int count = preempt_count();
++ ktime_t calltime, delta, rettime;
++
++ if (initcall_debug) {
++ call.caller = task_pid_nr(current);
++ printk("calling %pF @ %i\n", fn, call.caller);
++ calltime = ktime_get();
++ trace_boot_call(&call, fn);
++ enable_boot_trace();
++ }
++
++ ret.result = fn();
++
++ if (initcall_debug) {
++ disable_boot_trace();
++ rettime = ktime_get();
++ delta = ktime_sub(rettime, calltime);
++ ret.duration = (unsigned long long) ktime_to_ns(delta) >> 10;
++ trace_boot_ret(&ret, fn);
++ printk("initcall %pF returned %d after %Ld usecs\n", fn,
++ ret.result, ret.duration);
++ }
++
++ msgbuf[0] = 0;
++
++ if (ret.result && ret.result != -ENODEV && initcall_debug)
++ sprintf(msgbuf, "error code %d ", ret.result);
++
++ if (preempt_count() != count) {
++ strlcat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
++ preempt_count() = count;
++ }
++ if (irqs_disabled()) {
++ strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
++ local_irq_enable();
++ }
++ if (msgbuf[0]) {
++ printk("initcall %pF returned with %s\n", fn, msgbuf);
++ }
++
++ return ret.result;
++}
++
++
++extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];
++
++static void __init do_initcalls(void)
++{
++ initcall_t *fn;
++
++ for (fn = __early_initcall_end; fn < __initcall_end; fn++)
++ do_one_initcall(*fn);
++
++ /* Make sure there is no pending stuff from the initcall sequence */
++ flush_scheduled_work();
++}
++
++/*
++ * Ok, the machine is now initialized. None of the devices
++ * have been touched yet, but the CPU subsystem is up and
++ * running, and memory and process management works.
++ *
++ * Now we can finally start doing some real work..
++ */
++static void __init do_basic_setup(void)
++{
++ init_workqueues();
++ cpuset_init_smp();
++ usermodehelper_init();
++ init_tmpfs();
++ driver_init();
++ init_irq_proc();
++ do_ctors();
++ do_initcalls();
++}
++
++static void __init do_pre_smp_initcalls(void)
++{
++ initcall_t *fn;
++
++ for (fn = __initcall_start; fn < __early_initcall_end; fn++)
++ do_one_initcall(*fn);
++}
++
++static void run_init_process(char *init_filename)
++{
++ argv_init[0] = init_filename;
++ kernel_execve(init_filename, argv_init, envp_init);
++}
++
++/* This is a non __init function. Force it to be noinline otherwise gcc
++ * makes it inline to init() and it becomes part of init.text section
++ */
++static noinline int init_post(void)
++ __releases(kernel_lock)
++{
++ /* need to finish all async __init code before freeing the memory */
++ async_synchronize_full();
++ free_initmem();
++ unlock_kernel();
++ mark_rodata_ro();
++ system_state = SYSTEM_RUNNING;
++ numa_default_policy();
++
++
++ current->signal->flags |= SIGNAL_UNKILLABLE;
++
++ if (ramdisk_execute_command) {
++ run_init_process(ramdisk_execute_command);
++ printk(KERN_WARNING "Failed to execute %s\n",
++ ramdisk_execute_command);
++ }
++
++ /*
++ * We try each of these until one succeeds.
++ *
++ * The Bourne shell can be used instead of init if we are
++ * trying to recover a really broken machine.
++ */
++ if (execute_command) {
++ run_init_process(execute_command);
++ printk(KERN_WARNING "Failed to execute %s. Attempting "
++ "defaults...\n", execute_command);
++ }
++ run_init_process("/sbin/init");
++ run_init_process("/etc/init");
++ run_init_process("/bin/init");
++ run_init_process("/bin/sh");
++
++ panic("No init found. Try passing init= option to kernel. "
++ "See Linux Documentation/init.txt for guidance.");
++}
++
++static int __init kernel_init(void * unused)
++{
++ /*
++ * Wait until kthreadd is all set-up.
++ */
++ wait_for_completion(&kthreadd_done);
++ lock_kernel();
++
++ /*
++ * init can allocate pages on any node
++ */
++ set_mems_allowed(node_states[N_HIGH_MEMORY]);
++ /*
++ * init can run on any cpu.
++ */
++ set_cpus_allowed_ptr(current, cpu_all_mask);
++ /*
++ * Tell the world that we're going to be the grim
++ * reaper of innocent orphaned children.
++ *
++ * We don't want people to have to make incorrect
++ * assumptions about where in the task array this
++ * can be found.
++ */
++ init_pid_ns.child_reaper = current;
++
++ cad_pid = task_pid(current);
++
++ smp_prepare_cpus(setup_max_cpus);
++
++ do_pre_smp_initcalls();
++ start_boot_trace();
++
++ smp_init();
++ sched_init_smp();
++
++ do_basic_setup();
++
++ /* Open the /dev/console on the rootfs, this should never fail */
++ if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
++ printk(KERN_WARNING "Warning: unable to open an initial console.\n");
++
++ (void) sys_dup(0);
++ (void) sys_dup(0);
++ /*
++ * check if there is an early userspace init. If yes, let it do all
++ * the work
++ */
++
++ if (!ramdisk_execute_command)
++ ramdisk_execute_command = "/init";
++
++ if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
++ ramdisk_execute_command = NULL;
++ prepare_namespace();
++ }
++
++ /*
++ * Ok, we have completed the initial bootup, and
++ * we're essentially up and running. Get rid of the
++ * initmem segments and start the user-mode stuff..
++ */
++
++ init_post();
++ return 0;
++}
+diff -rupN linux-2.6.35.11/kernel/hrtimer.c linux-2.6.35.11-ts7500/kernel/hrtimer.c
+--- linux-2.6.35.11/kernel/hrtimer.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/kernel/hrtimer.c 2011-03-14 11:18:24.000000000 -0400
+@@ -328,14 +328,13 @@ ktime_t ktime_add_safe(const ktime_t lhs
+ */
+ if (res.tv64 < 0 || res.tv64 < lhs.tv64 || res.tv64 < rhs.tv64)
+ res = ktime_set(KTIME_SEC_MAX, 0);
+-
++
+ return res;
+ }
+
+ EXPORT_SYMBOL_GPL(ktime_add_safe);
+
+ #ifdef CONFIG_DEBUG_OBJECTS_TIMERS
+-
+ static struct debug_obj_descr hrtimer_debug_descr;
+
+ /*
+@@ -466,7 +465,6 @@ static inline void debug_deactivate(stru
+
+ /* High resolution timer related functions */
+ #ifdef CONFIG_HIGH_RES_TIMERS
+-
+ /*
+ * High resolution timer enabled ?
+ */
+@@ -715,6 +713,8 @@ static int hrtimer_switch_to_hres(void)
+ struct hrtimer_cpu_base *base = &per_cpu(hrtimer_bases, cpu);
+ unsigned long flags;
+
++ printk("hrtimer_switch_to_hres()\n");
++
+ if (base->hres_active)
+ return 1;
+
+@@ -851,7 +851,7 @@ static int enqueue_hrtimer(struct hrtime
+ int leftmost = 1;
+
+ debug_activate(timer);
+-
++
+ /*
+ * Find the right place in the rbtree:
+ */
+@@ -885,7 +885,7 @@ static int enqueue_hrtimer(struct hrtime
+ * state of a possibly running callback.
+ */
+ timer->state |= HRTIMER_STATE_ENQUEUED;
+-
++
+ return leftmost;
+ }
+
+@@ -969,9 +969,10 @@ int __hrtimer_start_range_ns(struct hrti
+ struct hrtimer_clock_base *base, *new_base;
+ unsigned long flags;
+ int ret, leftmost;
+-
++
+ base = lock_hrtimer_base(timer, &flags);
+
++
+ /* Remove an active timer from the queue: */
+ ret = remove_hrtimer(timer, base);
+
+@@ -1008,7 +1009,7 @@ int __hrtimer_start_range_ns(struct hrti
+ hrtimer_enqueue_reprogram(timer, new_base, wakeup);
+
+ unlock_hrtimer_base(timer, &flags);
+-
++
+ return ret;
+ }
+
+@@ -1184,7 +1185,7 @@ static void __hrtimer_init(struct hrtime
+ */
+ void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
+ enum hrtimer_mode mode)
+-{
++{
+ debug_init(timer, clock_id, mode);
+ __hrtimer_init(timer, clock_id, mode);
+ }
+@@ -1216,6 +1217,8 @@ static void __run_hrtimer(struct hrtimer
+ enum hrtimer_restart (*fn)(struct hrtimer *);
+ int restart;
+
++ //printk("__run_hrtimer %lld\n", timer->_expires.tv64);
++
+ WARN_ON(!irqs_disabled());
+
+ debug_deactivate(timer);
+@@ -1452,26 +1455,41 @@ void hrtimer_run_queues(void)
+ struct hrtimer_clock_base *base;
+ int index, gettime = 1;
+
++
+ if (hrtimer_hres_active())
+ return;
+
++
+ for (index = 0; index < HRTIMER_MAX_CLOCK_BASES; index++) {
+ base = &cpu_base->clock_base[index];
+
++ //printk("0\n");
++
+ if (!base->first)
+ continue;
+
++ //printk("1\n");
++
+ if (gettime) {
++ // printk("2\n");
+ hrtimer_get_softirq_time(cpu_base);
++ //printk("3\n");
+ gettime = 0;
+ }
+
++ //printk("4\n");
++
+ raw_spin_lock(&cpu_base->lock);
+
++ //printk("5\n");
++
+ while ((node = base->first)) {
+ struct hrtimer *timer;
+-
++
+ timer = rb_entry(node, struct hrtimer, node);
++
++ //printk("timer %lld\n", timer->_expires.tv64);
++
+ if (base->softirq_time.tv64 <=
+ hrtimer_get_expires_tv64(timer))
+ break;
+@@ -1507,22 +1525,28 @@ EXPORT_SYMBOL_GPL(hrtimer_init_sleeper);
+
+ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
+ {
+- hrtimer_init_sleeper(t, current);
+-
++ //printk("do_nanosleep()\n");
++
++ hrtimer_init_sleeper(t, current);
++
++ //printk("1\n");
++
+ do {
+ set_current_state(TASK_INTERRUPTIBLE);
+ hrtimer_start_expires(&t->timer, mode);
+ if (!hrtimer_active(&t->timer))
+ t->task = NULL;
+-
++
+ if (likely(t->task))
+ schedule();
+-
++
+ hrtimer_cancel(&t->timer);
+ mode = HRTIMER_MODE_ABS;
+-
++
+ } while (t->task && !signal_pending(current));
+
++ //printk("done\n");
++
+ __set_current_state(TASK_RUNNING);
+
+ return t->task == NULL;
+diff -rupN linux-2.6.35.11/kernel/hrtimer.c.orig linux-2.6.35.11-ts7500/kernel/hrtimer.c.orig
+--- linux-2.6.35.11/kernel/hrtimer.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/kernel/hrtimer.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,1874 @@
++/*
++ * linux/kernel/hrtimer.c
++ *
++ * Copyright(C) 2005-2006, Thomas Gleixner <tglx at linutronix.de>
++ * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
++ * Copyright(C) 2006-2007 Timesys Corp., Thomas Gleixner
++ *
++ * High-resolution kernel timers
++ *
++ * In contrast to the low-resolution timeout API implemented in
++ * kernel/timer.c, hrtimers provide finer resolution and accuracy
++ * depending on system configuration and capabilities.
++ *
++ * These timers are currently used for:
++ * - itimers
++ * - POSIX timers
++ * - nanosleep
++ * - precise in-kernel timing
++ *
++ * Started by: Thomas Gleixner and Ingo Molnar
++ *
++ * Credits:
++ * based on kernel/timer.c
++ *
++ * Help, testing, suggestions, bugfixes, improvements were
++ * provided by:
++ *
++ * George Anzinger, Andrew Morton, Steven Rostedt, Roman Zippel
++ * et. al.
++ *
++ * For licencing details see kernel-base/COPYING
++ */
++
++#include <linux/cpu.h>
++#include <linux/module.h>
++#include <linux/percpu.h>
++#include <linux/hrtimer.h>
++#include <linux/notifier.h>
++#include <linux/syscalls.h>
++#include <linux/kallsyms.h>
++#include <linux/interrupt.h>
++#include <linux/tick.h>
++#include <linux/seq_file.h>
++#include <linux/err.h>
++#include <linux/debugobjects.h>
++#include <linux/sched.h>
++#include <linux/timer.h>
++
++#include <asm/uaccess.h>
++
++#include <trace/events/timer.h>
++
++/*
++ * The timer bases:
++ *
++ * Note: If we want to add new timer bases, we have to skip the two
++ * clock ids captured by the cpu-timers. We do this by holding empty
++ * entries rather than doing math adjustment of the clock ids.
++ * This ensures that we capture erroneous accesses to these clock ids
++ * rather than moving them into the range of valid clock id's.
++ */
++DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
++{
++
++ .clock_base =
++ {
++ {
++ .index = CLOCK_REALTIME,
++ .get_time = &ktime_get_real,
++ .resolution = KTIME_LOW_RES,
++ },
++ {
++ .index = CLOCK_MONOTONIC,
++ .get_time = &ktime_get,
++ .resolution = KTIME_LOW_RES,
++ },
++ }
++};
++
++/*
++ * Get the coarse grained time at the softirq based on xtime and
++ * wall_to_monotonic.
++ */
++static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base)
++{
++ ktime_t xtim, tomono;
++ struct timespec xts, tom;
++ unsigned long seq;
++
++ do {
++ seq = read_seqbegin(&xtime_lock);
++ xts = __current_kernel_time();
++ tom = wall_to_monotonic;
++ } while (read_seqretry(&xtime_lock, seq));
++
++ xtim = timespec_to_ktime(xts);
++ tomono = timespec_to_ktime(tom);
++ base->clock_base[CLOCK_REALTIME].softirq_time = xtim;
++ base->clock_base[CLOCK_MONOTONIC].softirq_time =
++ ktime_add(xtim, tomono);
++}
++
++/*
++ * Functions and macros which are different for UP/SMP systems are kept in a
++ * single place
++ */
++#ifdef CONFIG_SMP
++
++/*
++ * We are using hashed locking: holding per_cpu(hrtimer_bases)[n].lock
++ * means that all timers which are tied to this base via timer->base are
++ * locked, and the base itself is locked too.
++ *
++ * So __run_timers/migrate_timers can safely modify all timers which could
++ * be found on the lists/queues.
++ *
++ * When the timer's base is locked, and the timer removed from list, it is
++ * possible to set timer->base = NULL and drop the lock: the timer remains
++ * locked.
++ */
++static
++struct hrtimer_clock_base *lock_hrtimer_base(const struct hrtimer *timer,
++ unsigned long *flags)
++{
++ struct hrtimer_clock_base *base;
++
++ for (;;) {
++ base = timer->base;
++ if (likely(base != NULL)) {
++ raw_spin_lock_irqsave(&base->cpu_base->lock, *flags);
++ if (likely(base == timer->base))
++ return base;
++ /* The timer has migrated to another CPU: */
++ raw_spin_unlock_irqrestore(&base->cpu_base->lock, *flags);
++ }
++ cpu_relax();
++ }
++}
++
++
++/*
++ * Get the preferred target CPU for NOHZ
++ */
++static int hrtimer_get_target(int this_cpu, int pinned)
++{
++#ifdef CONFIG_NO_HZ
++ if (!pinned && get_sysctl_timer_migration() && idle_cpu(this_cpu)) {
++ int preferred_cpu = get_nohz_load_balancer();
++
++ if (preferred_cpu >= 0)
++ return preferred_cpu;
++ }
++#endif
++ return this_cpu;
++}
++
++/*
++ * With HIGHRES=y we do not migrate the timer when it is expiring
++ * before the next event on the target cpu because we cannot reprogram
++ * the target cpu hardware and we would cause it to fire late.
++ *
++ * Called with cpu_base->lock of target cpu held.
++ */
++static int
++hrtimer_check_target(struct hrtimer *timer, struct hrtimer_clock_base *new_base)
++{
++#ifdef CONFIG_HIGH_RES_TIMERS
++ ktime_t expires;
++
++ if (!new_base->cpu_base->hres_active)
++ return 0;
++
++ expires = ktime_sub(hrtimer_get_expires(timer), new_base->offset);
++ return expires.tv64 <= new_base->cpu_base->expires_next.tv64;
++#else
++ return 0;
++#endif
++}
++
++/*
++ * Switch the timer base to the current CPU when possible.
++ */
++static inline struct hrtimer_clock_base *
++switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base,
++ int pinned)
++{
++ struct hrtimer_clock_base *new_base;
++ struct hrtimer_cpu_base *new_cpu_base;
++ int this_cpu = smp_processor_id();
++ int cpu = hrtimer_get_target(this_cpu, pinned);
++
++again:
++ new_cpu_base = &per_cpu(hrtimer_bases, cpu);
++ new_base = &new_cpu_base->clock_base[base->index];
++
++ if (base != new_base) {
++ /*
++ * We are trying to move timer to new_base.
++ * However we can't change timer's base while it is running,
++ * so we keep it on the same CPU. No hassle vs. reprogramming
++ * the event source in the high resolution case. The softirq
++ * code will take care of this when the timer function has
++ * completed. There is no conflict as we hold the lock until
++ * the timer is enqueued.
++ */
++ if (unlikely(hrtimer_callback_running(timer)))
++ return base;
++
++ /* See the comment in lock_timer_base() */
++ timer->base = NULL;
++ raw_spin_unlock(&base->cpu_base->lock);
++ raw_spin_lock(&new_base->cpu_base->lock);
++
++ if (cpu != this_cpu && hrtimer_check_target(timer, new_base)) {
++ cpu = this_cpu;
++ raw_spin_unlock(&new_base->cpu_base->lock);
++ raw_spin_lock(&base->cpu_base->lock);
++ timer->base = base;
++ goto again;
++ }
++ timer->base = new_base;
++ }
++ return new_base;
++}
++
++#else /* CONFIG_SMP */
++
++static inline struct hrtimer_clock_base *
++lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
++{
++ struct hrtimer_clock_base *base = timer->base;
++
++ raw_spin_lock_irqsave(&base->cpu_base->lock, *flags);
++
++ return base;
++}
++
++# define switch_hrtimer_base(t, b, p) (b)
++
++#endif /* !CONFIG_SMP */
++
++/*
++ * Functions for the union type storage format of ktime_t which are
++ * too large for inlining:
++ */
++#if BITS_PER_LONG < 64
++# ifndef CONFIG_KTIME_SCALAR
++/**
++ * ktime_add_ns - Add a scalar nanoseconds value to a ktime_t variable
++ * @kt: addend
++ * @nsec: the scalar nsec value to add
++ *
++ * Returns the sum of kt and nsec in ktime_t format
++ */
++ktime_t ktime_add_ns(const ktime_t kt, u64 nsec)
++{
++ ktime_t tmp;
++
++ if (likely(nsec < NSEC_PER_SEC)) {
++ tmp.tv64 = nsec;
++ } else {
++ unsigned long rem = do_div(nsec, NSEC_PER_SEC);
++
++ tmp = ktime_set((long)nsec, rem);
++ }
++
++ return ktime_add(kt, tmp);
++}
++
++EXPORT_SYMBOL_GPL(ktime_add_ns);
++
++/**
++ * ktime_sub_ns - Subtract a scalar nanoseconds value from a ktime_t variable
++ * @kt: minuend
++ * @nsec: the scalar nsec value to subtract
++ *
++ * Returns the subtraction of @nsec from @kt in ktime_t format
++ */
++ktime_t ktime_sub_ns(const ktime_t kt, u64 nsec)
++{
++ ktime_t tmp;
++
++ if (likely(nsec < NSEC_PER_SEC)) {
++ tmp.tv64 = nsec;
++ } else {
++ unsigned long rem = do_div(nsec, NSEC_PER_SEC);
++
++ tmp = ktime_set((long)nsec, rem);
++ }
++
++ return ktime_sub(kt, tmp);
++}
++
++EXPORT_SYMBOL_GPL(ktime_sub_ns);
++# endif /* !CONFIG_KTIME_SCALAR */
++
++/*
++ * Divide a ktime value by a nanosecond value
++ */
++u64 ktime_divns(const ktime_t kt, s64 div)
++{
++ u64 dclc;
++ int sft = 0;
++
++ dclc = ktime_to_ns(kt);
++ /* Make sure the divisor is less than 2^32: */
++ while (div >> 32) {
++ sft++;
++ div >>= 1;
++ }
++ dclc >>= sft;
++ do_div(dclc, (unsigned long) div);
++
++ return dclc;
++}
++#endif /* BITS_PER_LONG >= 64 */
++
++/*
++ * Add two ktime values and do a safety check for overflow:
++ */
++ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs)
++{
++ ktime_t res = ktime_add(lhs, rhs);
++
++ /*
++ * We use KTIME_SEC_MAX here, the maximum timeout which we can
++ * return to user space in a timespec:
++ */
++ if (res.tv64 < 0 || res.tv64 < lhs.tv64 || res.tv64 < rhs.tv64)
++ res = ktime_set(KTIME_SEC_MAX, 0);
++
++ return res;
++}
++
++EXPORT_SYMBOL_GPL(ktime_add_safe);
++
++#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
++
++static struct debug_obj_descr hrtimer_debug_descr;
++
++/*
++ * fixup_init is called when:
++ * - an active object is initialized
++ */
++static int hrtimer_fixup_init(void *addr, enum debug_obj_state state)
++{
++ struct hrtimer *timer = addr;
++
++ switch (state) {
++ case ODEBUG_STATE_ACTIVE:
++ hrtimer_cancel(timer);
++ debug_object_init(timer, &hrtimer_debug_descr);
++ return 1;
++ default:
++ return 0;
++ }
++}
++
++/*
++ * fixup_activate is called when:
++ * - an active object is activated
++ * - an unknown object is activated (might be a statically initialized object)
++ */
++static int hrtimer_fixup_activate(void *addr, enum debug_obj_state state)
++{
++ switch (state) {
++
++ case ODEBUG_STATE_NOTAVAILABLE:
++ WARN_ON_ONCE(1);
++ return 0;
++
++ case ODEBUG_STATE_ACTIVE:
++ WARN_ON(1);
++
++ default:
++ return 0;
++ }
++}
++
++/*
++ * fixup_free is called when:
++ * - an active object is freed
++ */
++static int hrtimer_fixup_free(void *addr, enum debug_obj_state state)
++{
++ struct hrtimer *timer = addr;
++
++ switch (state) {
++ case ODEBUG_STATE_ACTIVE:
++ hrtimer_cancel(timer);
++ debug_object_free(timer, &hrtimer_debug_descr);
++ return 1;
++ default:
++ return 0;
++ }
++}
++
++static struct debug_obj_descr hrtimer_debug_descr = {
++ .name = "hrtimer",
++ .fixup_init = hrtimer_fixup_init,
++ .fixup_activate = hrtimer_fixup_activate,
++ .fixup_free = hrtimer_fixup_free,
++};
++
++static inline void debug_hrtimer_init(struct hrtimer *timer)
++{
++ debug_object_init(timer, &hrtimer_debug_descr);
++}
++
++static inline void debug_hrtimer_activate(struct hrtimer *timer)
++{
++ debug_object_activate(timer, &hrtimer_debug_descr);
++}
++
++static inline void debug_hrtimer_deactivate(struct hrtimer *timer)
++{
++ debug_object_deactivate(timer, &hrtimer_debug_descr);
++}
++
++static inline void debug_hrtimer_free(struct hrtimer *timer)
++{
++ debug_object_free(timer, &hrtimer_debug_descr);
++}
++
++static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
++ enum hrtimer_mode mode);
++
++void hrtimer_init_on_stack(struct hrtimer *timer, clockid_t clock_id,
++ enum hrtimer_mode mode)
++{
++ debug_object_init_on_stack(timer, &hrtimer_debug_descr);
++ __hrtimer_init(timer, clock_id, mode);
++}
++EXPORT_SYMBOL_GPL(hrtimer_init_on_stack);
++
++void destroy_hrtimer_on_stack(struct hrtimer *timer)
++{
++ debug_object_free(timer, &hrtimer_debug_descr);
++}
++
++#else
++static inline void debug_hrtimer_init(struct hrtimer *timer) { }
++static inline void debug_hrtimer_activate(struct hrtimer *timer) { }
++static inline void debug_hrtimer_deactivate(struct hrtimer *timer) { }
++#endif
++
++static inline void
++debug_init(struct hrtimer *timer, clockid_t clockid,
++ enum hrtimer_mode mode)
++{
++ debug_hrtimer_init(timer);
++ trace_hrtimer_init(timer, clockid, mode);
++}
++
++static inline void debug_activate(struct hrtimer *timer)
++{
++ debug_hrtimer_activate(timer);
++ trace_hrtimer_start(timer);
++}
++
++static inline void debug_deactivate(struct hrtimer *timer)
++{
++ debug_hrtimer_deactivate(timer);
++ trace_hrtimer_cancel(timer);
++}
++
++/* High resolution timer related functions */
++#ifdef CONFIG_HIGH_RES_TIMERS
++
++/*
++ * High resolution timer enabled ?
++ */
++static int hrtimer_hres_enabled __read_mostly = 1;
++
++/*
++ * Enable / Disable high resolution mode
++ */
++static int __init setup_hrtimer_hres(char *str)
++{
++ if (!strcmp(str, "off"))
++ hrtimer_hres_enabled = 0;
++ else if (!strcmp(str, "on"))
++ hrtimer_hres_enabled = 1;
++ else
++ return 0;
++ return 1;
++}
++
++__setup("highres=", setup_hrtimer_hres);
++
++/*
++ * hrtimer_high_res_enabled - query, if the highres mode is enabled
++ */
++static inline int hrtimer_is_hres_enabled(void)
++{
++ return hrtimer_hres_enabled;
++}
++
++/*
++ * Is the high resolution mode active ?
++ */
++static inline int hrtimer_hres_active(void)
++{
++ return __get_cpu_var(hrtimer_bases).hres_active;
++}
++
++/*
++ * Reprogram the event source with checking both queues for the
++ * next event
++ * Called with interrupts disabled and base->lock held
++ */
++static void
++hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal)
++{
++ int i;
++ struct hrtimer_clock_base *base = cpu_base->clock_base;
++ ktime_t expires, expires_next;
++
++ expires_next.tv64 = KTIME_MAX;
++
++ for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) {
++ struct hrtimer *timer;
++
++ if (!base->first)
++ continue;
++ timer = rb_entry(base->first, struct hrtimer, node);
++ expires = ktime_sub(hrtimer_get_expires(timer), base->offset);
++ /*
++ * clock_was_set() has changed base->offset so the
++ * result might be negative. Fix it up to prevent a
++ * false positive in clockevents_program_event()
++ */
++ if (expires.tv64 < 0)
++ expires.tv64 = 0;
++ if (expires.tv64 < expires_next.tv64)
++ expires_next = expires;
++ }
++
++ if (skip_equal && expires_next.tv64 == cpu_base->expires_next.tv64)
++ return;
++
++ cpu_base->expires_next.tv64 = expires_next.tv64;
++
++ if (cpu_base->expires_next.tv64 != KTIME_MAX)
++ tick_program_event(cpu_base->expires_next, 1);
++}
++
++/*
++ * Shared reprogramming for clock_realtime and clock_monotonic
++ *
++ * When a timer is enqueued and expires earlier than the already enqueued
++ * timers, we have to check, whether it expires earlier than the timer for
++ * which the clock event device was armed.
++ *
++ * Called with interrupts disabled and base->cpu_base.lock held
++ */
++static int hrtimer_reprogram(struct hrtimer *timer,
++ struct hrtimer_clock_base *base)
++{
++ struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
++ ktime_t expires = ktime_sub(hrtimer_get_expires(timer), base->offset);
++ int res;
++
++ WARN_ON_ONCE(hrtimer_get_expires_tv64(timer) < 0);
++
++ /*
++ * When the callback is running, we do not reprogram the clock event
++ * device. The timer callback is either running on a different CPU or
++ * the callback is executed in the hrtimer_interrupt context. The
++ * reprogramming is handled either by the softirq, which called the
++ * callback or at the end of the hrtimer_interrupt.
++ */
++ if (hrtimer_callback_running(timer))
++ return 0;
++
++ /*
++ * CLOCK_REALTIME timer might be requested with an absolute
++ * expiry time which is less than base->offset. Nothing wrong
++ * about that, just avoid to call into the tick code, which
++ * has now objections against negative expiry values.
++ */
++ if (expires.tv64 < 0)
++ return -ETIME;
++
++ if (expires.tv64 >= cpu_base->expires_next.tv64)
++ return 0;
++
++ /*
++ * If a hang was detected in the last timer interrupt then we
++ * do not schedule a timer which is earlier than the expiry
++ * which we enforced in the hang detection. We want the system
++ * to make progress.
++ */
++ if (cpu_base->hang_detected)
++ return 0;
++
++ /*
++ * Clockevents returns -ETIME, when the event was in the past.
++ */
++ res = tick_program_event(expires, 0);
++ if (!IS_ERR_VALUE(res))
++ cpu_base->expires_next = expires;
++ return res;
++}
++
++
++/*
++ * Retrigger next event is called after clock was set
++ *
++ * Called with interrupts disabled via on_each_cpu()
++ */
++static void retrigger_next_event(void *arg)
++{
++ struct hrtimer_cpu_base *base;
++ struct timespec realtime_offset;
++ unsigned long seq;
++
++ if (!hrtimer_hres_active())
++ return;
++
++ do {
++ seq = read_seqbegin(&xtime_lock);
++ set_normalized_timespec(&realtime_offset,
++ -wall_to_monotonic.tv_sec,
++ -wall_to_monotonic.tv_nsec);
++ } while (read_seqretry(&xtime_lock, seq));
++
++ base = &__get_cpu_var(hrtimer_bases);
++
++ /* Adjust CLOCK_REALTIME offset */
++ raw_spin_lock(&base->lock);
++ base->clock_base[CLOCK_REALTIME].offset =
++ timespec_to_ktime(realtime_offset);
++
++ hrtimer_force_reprogram(base, 0);
++ raw_spin_unlock(&base->lock);
++}
++
++/*
++ * Clock realtime was set
++ *
++ * Change the offset of the realtime clock vs. the monotonic
++ * clock.
++ *
++ * We might have to reprogram the high resolution timer interrupt. On
++ * SMP we call the architecture specific code to retrigger _all_ high
++ * resolution timer interrupts. On UP we just disable interrupts and
++ * call the high resolution interrupt code.
++ */
++void clock_was_set(void)
++{
++ /* Retrigger the CPU local events everywhere */
++ on_each_cpu(retrigger_next_event, NULL, 1);
++}
++
++/*
++ * During resume we might have to reprogram the high resolution timer
++ * interrupt (on the local CPU):
++ */
++void hres_timers_resume(void)
++{
++ WARN_ONCE(!irqs_disabled(),
++ KERN_INFO "hres_timers_resume() called with IRQs enabled!");
++
++ retrigger_next_event(NULL);
++}
++
++/*
++ * Initialize the high resolution related parts of cpu_base
++ */
++static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base)
++{
++ base->expires_next.tv64 = KTIME_MAX;
++ base->hres_active = 0;
++}
++
++/*
++ * Initialize the high resolution related parts of a hrtimer
++ */
++static inline void hrtimer_init_timer_hres(struct hrtimer *timer)
++{
++}
++
++
++/*
++ * When High resolution timers are active, try to reprogram. Note, that in case
++ * the state has HRTIMER_STATE_CALLBACK set, no reprogramming and no expiry
++ * check happens. The timer gets enqueued into the rbtree. The reprogramming
++ * and expiry check is done in the hrtimer_interrupt or in the softirq.
++ */
++static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
++ struct hrtimer_clock_base *base,
++ int wakeup)
++{
++ if (base->cpu_base->hres_active && hrtimer_reprogram(timer, base)) {
++ if (wakeup) {
++ raw_spin_unlock(&base->cpu_base->lock);
++ raise_softirq_irqoff(HRTIMER_SOFTIRQ);
++ raw_spin_lock(&base->cpu_base->lock);
++ } else
++ __raise_softirq_irqoff(HRTIMER_SOFTIRQ);
++
++ return 1;
++ }
++
++ return 0;
++}
++
++/*
++ * Switch to high resolution mode
++ */
++static int hrtimer_switch_to_hres(void)
++{
++ int cpu = smp_processor_id();
++ struct hrtimer_cpu_base *base = &per_cpu(hrtimer_bases, cpu);
++ unsigned long flags;
++
++ if (base->hres_active)
++ return 1;
++
++ local_irq_save(flags);
++
++ if (tick_init_highres()) {
++ local_irq_restore(flags);
++ printk(KERN_WARNING "Could not switch to high resolution "
++ "mode on CPU %d\n", cpu);
++ return 0;
++ }
++ base->hres_active = 1;
++ base->clock_base[CLOCK_REALTIME].resolution = KTIME_HIGH_RES;
++ base->clock_base[CLOCK_MONOTONIC].resolution = KTIME_HIGH_RES;
++
++ tick_setup_sched_timer();
++
++ /* "Retrigger" the interrupt to get things going */
++ retrigger_next_event(NULL);
++ local_irq_restore(flags);
++ return 1;
++}
++
++#else
++
++static inline int hrtimer_hres_active(void) { return 0; }
++static inline int hrtimer_is_hres_enabled(void) { return 0; }
++static inline int hrtimer_switch_to_hres(void) { return 0; }
++static inline void
++hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { }
++static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
++ struct hrtimer_clock_base *base,
++ int wakeup)
++{
++ return 0;
++}
++static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) { }
++static inline void hrtimer_init_timer_hres(struct hrtimer *timer) { }
++
++#endif /* CONFIG_HIGH_RES_TIMERS */
++
++static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer)
++{
++#ifdef CONFIG_TIMER_STATS
++ if (timer->start_site)
++ return;
++ timer->start_site = __builtin_return_address(0);
++ memcpy(timer->start_comm, current->comm, TASK_COMM_LEN);
++ timer->start_pid = current->pid;
++#endif
++}
++
++static inline void timer_stats_hrtimer_clear_start_info(struct hrtimer *timer)
++{
++#ifdef CONFIG_TIMER_STATS
++ timer->start_site = NULL;
++#endif
++}
++
++static inline void timer_stats_account_hrtimer(struct hrtimer *timer)
++{
++#ifdef CONFIG_TIMER_STATS
++ if (likely(!timer_stats_active))
++ return;
++ timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
++ timer->function, timer->start_comm, 0);
++#endif
++}
++
++/*
++ * Counterpart to lock_hrtimer_base above:
++ */
++static inline
++void unlock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
++{
++ raw_spin_unlock_irqrestore(&timer->base->cpu_base->lock, *flags);
++}
++
++/**
++ * hrtimer_forward - forward the timer expiry
++ * @timer: hrtimer to forward
++ * @now: forward past this time
++ * @interval: the interval to forward
++ *
++ * Forward the timer expiry so it will expire in the future.
++ * Returns the number of overruns.
++ */
++u64 hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval)
++{
++ u64 orun = 1;
++ ktime_t delta;
++
++ delta = ktime_sub(now, hrtimer_get_expires(timer));
++
++ if (delta.tv64 < 0)
++ return 0;
++
++ if (interval.tv64 < timer->base->resolution.tv64)
++ interval.tv64 = timer->base->resolution.tv64;
++
++ if (unlikely(delta.tv64 >= interval.tv64)) {
++ s64 incr = ktime_to_ns(interval);
++
++ orun = ktime_divns(delta, incr);
++ hrtimer_add_expires_ns(timer, incr * orun);
++ if (hrtimer_get_expires_tv64(timer) > now.tv64)
++ return orun;
++ /*
++ * This (and the ktime_add() below) is the
++ * correction for exact:
++ */
++ orun++;
++ }
++ hrtimer_add_expires(timer, interval);
++
++ return orun;
++}
++EXPORT_SYMBOL_GPL(hrtimer_forward);
++
++/*
++ * enqueue_hrtimer - internal function to (re)start a timer
++ *
++ * The timer is inserted in expiry order. Insertion into the
++ * red black tree is O(log(n)). Must hold the base lock.
++ *
++ * Returns 1 when the new timer is the leftmost timer in the tree.
++ */
++static int enqueue_hrtimer(struct hrtimer *timer,
++ struct hrtimer_clock_base *base)
++{
++ struct rb_node **link = &base->active.rb_node;
++ struct rb_node *parent = NULL;
++ struct hrtimer *entry;
++ int leftmost = 1;
++
++ debug_activate(timer);
++
++ /*
++ * Find the right place in the rbtree:
++ */
++ while (*link) {
++ parent = *link;
++ entry = rb_entry(parent, struct hrtimer, node);
++ /*
++ * We dont care about collisions. Nodes with
++ * the same expiry time stay together.
++ */
++ if (hrtimer_get_expires_tv64(timer) <
++ hrtimer_get_expires_tv64(entry)) {
++ link = &(*link)->rb_left;
++ } else {
++ link = &(*link)->rb_right;
++ leftmost = 0;
++ }
++ }
++
++ /*
++ * Insert the timer to the rbtree and check whether it
++ * replaces the first pending timer
++ */
++ if (leftmost)
++ base->first = &timer->node;
++
++ rb_link_node(&timer->node, parent, link);
++ rb_insert_color(&timer->node, &base->active);
++ /*
++ * HRTIMER_STATE_ENQUEUED is or'ed to the current state to preserve the
++ * state of a possibly running callback.
++ */
++ timer->state |= HRTIMER_STATE_ENQUEUED;
++
++ return leftmost;
++}
++
++/*
++ * __remove_hrtimer - internal function to remove a timer
++ *
++ * Caller must hold the base lock.
++ *
++ * High resolution timer mode reprograms the clock event device when the
++ * timer is the one which expires next. The caller can disable this by setting
++ * reprogram to zero. This is useful, when the context does a reprogramming
++ * anyway (e.g. timer interrupt)
++ */
++static void __remove_hrtimer(struct hrtimer *timer,
++ struct hrtimer_clock_base *base,
++ unsigned long newstate, int reprogram)
++{
++ if (!(timer->state & HRTIMER_STATE_ENQUEUED))
++ goto out;
++
++ /*
++ * Remove the timer from the rbtree and replace the first
++ * entry pointer if necessary.
++ */
++ if (base->first == &timer->node) {
++ base->first = rb_next(&timer->node);
++#ifdef CONFIG_HIGH_RES_TIMERS
++ /* Reprogram the clock event device. if enabled */
++ if (reprogram && hrtimer_hres_active()) {
++ ktime_t expires;
++
++ expires = ktime_sub(hrtimer_get_expires(timer),
++ base->offset);
++ if (base->cpu_base->expires_next.tv64 == expires.tv64)
++ hrtimer_force_reprogram(base->cpu_base, 1);
++ }
++#endif
++ }
++ rb_erase(&timer->node, &base->active);
++out:
++ timer->state = newstate;
++}
++
++/*
++ * remove hrtimer, called with base lock held
++ */
++static inline int
++remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
++{
++ if (hrtimer_is_queued(timer)) {
++ unsigned long state;
++ int reprogram;
++
++ /*
++ * Remove the timer and force reprogramming when high
++ * resolution mode is active and the timer is on the current
++ * CPU. If we remove a timer on another CPU, reprogramming is
++ * skipped. The interrupt event on this CPU is fired and
++ * reprogramming happens in the interrupt handler. This is a
++ * rare case and less expensive than a smp call.
++ */
++ debug_deactivate(timer);
++ timer_stats_hrtimer_clear_start_info(timer);
++ reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases);
++ /*
++ * We must preserve the CALLBACK state flag here,
++ * otherwise we could move the timer base in
++ * switch_hrtimer_base.
++ */
++ state = timer->state & HRTIMER_STATE_CALLBACK;
++ __remove_hrtimer(timer, base, state, reprogram);
++ return 1;
++ }
++ return 0;
++}
++
++int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
++ unsigned long delta_ns, const enum hrtimer_mode mode,
++ int wakeup)
++{
++ struct hrtimer_clock_base *base, *new_base;
++ unsigned long flags;
++ int ret, leftmost;
++
++ base = lock_hrtimer_base(timer, &flags);
++
++ /* Remove an active timer from the queue: */
++ ret = remove_hrtimer(timer, base);
++
++ /* Switch the timer base, if necessary: */
++ new_base = switch_hrtimer_base(timer, base, mode & HRTIMER_MODE_PINNED);
++
++ if (mode & HRTIMER_MODE_REL) {
++ tim = ktime_add_safe(tim, new_base->get_time());
++ /*
++ * CONFIG_TIME_LOW_RES is a temporary way for architectures
++ * to signal that they simply return xtime in
++ * do_gettimeoffset(). In this case we want to round up by
++ * resolution when starting a relative timer, to avoid short
++ * timeouts. This will go away with the GTOD framework.
++ */
++#ifdef CONFIG_TIME_LOW_RES
++ tim = ktime_add_safe(tim, base->resolution);
++#endif
++ }
++
++ hrtimer_set_expires_range_ns(timer, tim, delta_ns);
++
++ timer_stats_hrtimer_set_start_info(timer);
++
++ leftmost = enqueue_hrtimer(timer, new_base);
++
++ /*
++ * Only allow reprogramming if the new base is on this CPU.
++ * (it might still be on another CPU if the timer was pending)
++ *
++ * XXX send_remote_softirq() ?
++ */
++ if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases))
++ hrtimer_enqueue_reprogram(timer, new_base, wakeup);
++
++ unlock_hrtimer_base(timer, &flags);
++
++ return ret;
++}
++
++/**
++ * hrtimer_start_range_ns - (re)start an hrtimer on the current CPU
++ * @timer: the timer to be added
++ * @tim: expiry time
++ * @delta_ns: "slack" range for the timer
++ * @mode: expiry mode: absolute (HRTIMER_ABS) or relative (HRTIMER_REL)
++ *
++ * Returns:
++ * 0 on success
++ * 1 when the timer was active
++ */
++int hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
++ unsigned long delta_ns, const enum hrtimer_mode mode)
++{
++ return __hrtimer_start_range_ns(timer, tim, delta_ns, mode, 1);
++}
++EXPORT_SYMBOL_GPL(hrtimer_start_range_ns);
++
++/**
++ * hrtimer_start - (re)start an hrtimer on the current CPU
++ * @timer: the timer to be added
++ * @tim: expiry time
++ * @mode: expiry mode: absolute (HRTIMER_ABS) or relative (HRTIMER_REL)
++ *
++ * Returns:
++ * 0 on success
++ * 1 when the timer was active
++ */
++int
++hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
++{
++ return __hrtimer_start_range_ns(timer, tim, 0, mode, 1);
++}
++EXPORT_SYMBOL_GPL(hrtimer_start);
++
++
++/**
++ * hrtimer_try_to_cancel - try to deactivate a timer
++ * @timer: hrtimer to stop
++ *
++ * Returns:
++ * 0 when the timer was not active
++ * 1 when the timer was active
++ * -1 when the timer is currently excuting the callback function and
++ * cannot be stopped
++ */
++int hrtimer_try_to_cancel(struct hrtimer *timer)
++{
++ struct hrtimer_clock_base *base;
++ unsigned long flags;
++ int ret = -1;
++
++ base = lock_hrtimer_base(timer, &flags);
++
++ if (!hrtimer_callback_running(timer))
++ ret = remove_hrtimer(timer, base);
++
++ unlock_hrtimer_base(timer, &flags);
++
++ return ret;
++
++}
++EXPORT_SYMBOL_GPL(hrtimer_try_to_cancel);
++
++/**
++ * hrtimer_cancel - cancel a timer and wait for the handler to finish.
++ * @timer: the timer to be cancelled
++ *
++ * Returns:
++ * 0 when the timer was not active
++ * 1 when the timer was active
++ */
++int hrtimer_cancel(struct hrtimer *timer)
++{
++ for (;;) {
++ int ret = hrtimer_try_to_cancel(timer);
++
++ if (ret >= 0)
++ return ret;
++ cpu_relax();
++ }
++}
++EXPORT_SYMBOL_GPL(hrtimer_cancel);
++
++/**
++ * hrtimer_get_remaining - get remaining time for the timer
++ * @timer: the timer to read
++ */
++ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
++{
++ struct hrtimer_clock_base *base;
++ unsigned long flags;
++ ktime_t rem;
++
++ base = lock_hrtimer_base(timer, &flags);
++ rem = hrtimer_expires_remaining(timer);
++ unlock_hrtimer_base(timer, &flags);
++
++ return rem;
++}
++EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
++
++#ifdef CONFIG_NO_HZ
++/**
++ * hrtimer_get_next_event - get the time until next expiry event
++ *
++ * Returns the delta to the next expiry event or KTIME_MAX if no timer
++ * is pending.
++ */
++ktime_t hrtimer_get_next_event(void)
++{
++ struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
++ struct hrtimer_clock_base *base = cpu_base->clock_base;
++ ktime_t delta, mindelta = { .tv64 = KTIME_MAX };
++ unsigned long flags;
++ int i;
++
++ raw_spin_lock_irqsave(&cpu_base->lock, flags);
++
++ if (!hrtimer_hres_active()) {
++ for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) {
++ struct hrtimer *timer;
++
++ if (!base->first)
++ continue;
++
++ timer = rb_entry(base->first, struct hrtimer, node);
++ delta.tv64 = hrtimer_get_expires_tv64(timer);
++ delta = ktime_sub(delta, base->get_time());
++ if (delta.tv64 < mindelta.tv64)
++ mindelta.tv64 = delta.tv64;
++ }
++ }
++
++ raw_spin_unlock_irqrestore(&cpu_base->lock, flags);
++
++ if (mindelta.tv64 < 0)
++ mindelta.tv64 = 0;
++ return mindelta;
++}
++#endif
++
++static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
++ enum hrtimer_mode mode)
++{
++ struct hrtimer_cpu_base *cpu_base;
++
++ memset(timer, 0, sizeof(struct hrtimer));
++
++ cpu_base = &__raw_get_cpu_var(hrtimer_bases);
++
++ if (clock_id == CLOCK_REALTIME && mode != HRTIMER_MODE_ABS)
++ clock_id = CLOCK_MONOTONIC;
++
++ timer->base = &cpu_base->clock_base[clock_id];
++ hrtimer_init_timer_hres(timer);
++
++#ifdef CONFIG_TIMER_STATS
++ timer->start_site = NULL;
++ timer->start_pid = -1;
++ memset(timer->start_comm, 0, TASK_COMM_LEN);
++#endif
++}
++
++/**
++ * hrtimer_init - initialize a timer to the given clock
++ * @timer: the timer to be initialized
++ * @clock_id: the clock to be used
++ * @mode: timer mode abs/rel
++ */
++void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
++ enum hrtimer_mode mode)
++{
++ debug_init(timer, clock_id, mode);
++ __hrtimer_init(timer, clock_id, mode);
++}
++EXPORT_SYMBOL_GPL(hrtimer_init);
++
++/**
++ * hrtimer_get_res - get the timer resolution for a clock
++ * @which_clock: which clock to query
++ * @tp: pointer to timespec variable to store the resolution
++ *
++ * Store the resolution of the clock selected by @which_clock in the
++ * variable pointed to by @tp.
++ */
++int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
++{
++ struct hrtimer_cpu_base *cpu_base;
++
++ cpu_base = &__raw_get_cpu_var(hrtimer_bases);
++ *tp = ktime_to_timespec(cpu_base->clock_base[which_clock].resolution);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(hrtimer_get_res);
++
++static void __run_hrtimer(struct hrtimer *timer, ktime_t *now)
++{
++ struct hrtimer_clock_base *base = timer->base;
++ struct hrtimer_cpu_base *cpu_base = base->cpu_base;
++ enum hrtimer_restart (*fn)(struct hrtimer *);
++ int restart;
++
++ WARN_ON(!irqs_disabled());
++
++ debug_deactivate(timer);
++ __remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0);
++ timer_stats_account_hrtimer(timer);
++ fn = timer->function;
++
++ /*
++ * Because we run timers from hardirq context, there is no chance
++ * they get migrated to another cpu, therefore its safe to unlock
++ * the timer base.
++ */
++ raw_spin_unlock(&cpu_base->lock);
++ trace_hrtimer_expire_entry(timer, now);
++ restart = fn(timer);
++ trace_hrtimer_expire_exit(timer);
++ raw_spin_lock(&cpu_base->lock);
++
++ /*
++ * Note: We clear the CALLBACK bit after enqueue_hrtimer and
++ * we do not reprogramm the event hardware. Happens either in
++ * hrtimer_start_range_ns() or in hrtimer_interrupt()
++ */
++ if (restart != HRTIMER_NORESTART) {
++ BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
++ enqueue_hrtimer(timer, base);
++ }
++
++ WARN_ON_ONCE(!(timer->state & HRTIMER_STATE_CALLBACK));
++
++ timer->state &= ~HRTIMER_STATE_CALLBACK;
++}
++
++#ifdef CONFIG_HIGH_RES_TIMERS
++
++/*
++ * High resolution timer interrupt
++ * Called with interrupts disabled
++ */
++void hrtimer_interrupt(struct clock_event_device *dev)
++{
++ struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
++ struct hrtimer_clock_base *base;
++ ktime_t expires_next, now, entry_time, delta;
++ int i, retries = 0;
++
++ BUG_ON(!cpu_base->hres_active);
++ cpu_base->nr_events++;
++ dev->next_event.tv64 = KTIME_MAX;
++
++ entry_time = now = ktime_get();
++retry:
++ expires_next.tv64 = KTIME_MAX;
++
++ raw_spin_lock(&cpu_base->lock);
++ /*
++ * We set expires_next to KTIME_MAX here with cpu_base->lock
++ * held to prevent that a timer is enqueued in our queue via
++ * the migration code. This does not affect enqueueing of
++ * timers which run their callback and need to be requeued on
++ * this CPU.
++ */
++ cpu_base->expires_next.tv64 = KTIME_MAX;
++
++ base = cpu_base->clock_base;
++
++ for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
++ ktime_t basenow;
++ struct rb_node *node;
++
++ basenow = ktime_add(now, base->offset);
++
++ while ((node = base->first)) {
++ struct hrtimer *timer;
++
++ timer = rb_entry(node, struct hrtimer, node);
++
++ /*
++ * The immediate goal for using the softexpires is
++ * minimizing wakeups, not running timers at the
++ * earliest interrupt after their soft expiration.
++ * This allows us to avoid using a Priority Search
++ * Tree, which can answer a stabbing querry for
++ * overlapping intervals and instead use the simple
++ * BST we already have.
++ * We don't add extra wakeups by delaying timers that
++ * are right-of a not yet expired timer, because that
++ * timer will have to trigger a wakeup anyway.
++ */
++
++ if (basenow.tv64 < hrtimer_get_softexpires_tv64(timer)) {
++ ktime_t expires;
++
++ expires = ktime_sub(hrtimer_get_expires(timer),
++ base->offset);
++ if (expires.tv64 < expires_next.tv64)
++ expires_next = expires;
++ break;
++ }
++
++ __run_hrtimer(timer, &basenow);
++ }
++ base++;
++ }
++
++ /*
++ * Store the new expiry value so the migration code can verify
++ * against it.
++ */
++ cpu_base->expires_next = expires_next;
++ raw_spin_unlock(&cpu_base->lock);
++
++ /* Reprogramming necessary ? */
++ if (expires_next.tv64 == KTIME_MAX ||
++ !tick_program_event(expires_next, 0)) {
++ cpu_base->hang_detected = 0;
++ return;
++ }
++
++ /*
++ * The next timer was already expired due to:
++ * - tracing
++ * - long lasting callbacks
++ * - being scheduled away when running in a VM
++ *
++ * We need to prevent that we loop forever in the hrtimer
++ * interrupt routine. We give it 3 attempts to avoid
++ * overreacting on some spurious event.
++ */
++ now = ktime_get();
++ cpu_base->nr_retries++;
++ if (++retries < 3)
++ goto retry;
++ /*
++ * Give the system a chance to do something else than looping
++ * here. We stored the entry time, so we know exactly how long
++ * we spent here. We schedule the next event this amount of
++ * time away.
++ */
++ cpu_base->nr_hangs++;
++ cpu_base->hang_detected = 1;
++ delta = ktime_sub(now, entry_time);
++ if (delta.tv64 > cpu_base->max_hang_time.tv64)
++ cpu_base->max_hang_time = delta;
++ /*
++ * Limit it to a sensible value as we enforce a longer
++ * delay. Give the CPU at least 100ms to catch up.
++ */
++ if (delta.tv64 > 100 * NSEC_PER_MSEC)
++ expires_next = ktime_add_ns(now, 100 * NSEC_PER_MSEC);
++ else
++ expires_next = ktime_add(now, delta);
++ tick_program_event(expires_next, 1);
++ printk_once(KERN_WARNING "hrtimer: interrupt took %llu ns\n",
++ ktime_to_ns(delta));
++}
++
++/*
++ * local version of hrtimer_peek_ahead_timers() called with interrupts
++ * disabled.
++ */
++static void __hrtimer_peek_ahead_timers(void)
++{
++ struct tick_device *td;
++
++ if (!hrtimer_hres_active())
++ return;
++
++ td = &__get_cpu_var(tick_cpu_device);
++ if (td && td->evtdev)
++ hrtimer_interrupt(td->evtdev);
++}
++
++/**
++ * hrtimer_peek_ahead_timers -- run soft-expired timers now
++ *
++ * hrtimer_peek_ahead_timers will peek at the timer queue of
++ * the current cpu and check if there are any timers for which
++ * the soft expires time has passed. If any such timers exist,
++ * they are run immediately and then removed from the timer queue.
++ *
++ */
++void hrtimer_peek_ahead_timers(void)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ __hrtimer_peek_ahead_timers();
++ local_irq_restore(flags);
++}
++
++static void run_hrtimer_softirq(struct softirq_action *h)
++{
++ hrtimer_peek_ahead_timers();
++}
++
++#else /* CONFIG_HIGH_RES_TIMERS */
++
++static inline void __hrtimer_peek_ahead_timers(void) { }
++
++#endif /* !CONFIG_HIGH_RES_TIMERS */
++
++/*
++ * Called from timer softirq every jiffy, expire hrtimers:
++ *
++ * For HRT its the fall back code to run the softirq in the timer
++ * softirq context in case the hrtimer initialization failed or has
++ * not been done yet.
++ */
++void hrtimer_run_pending(void)
++{
++ if (hrtimer_hres_active())
++ return;
++
++ /*
++ * This _is_ ugly: We have to check in the softirq context,
++ * whether we can switch to highres and / or nohz mode. The
++ * clocksource switch happens in the timer interrupt with
++ * xtime_lock held. Notification from there only sets the
++ * check bit in the tick_oneshot code, otherwise we might
++ * deadlock vs. xtime_lock.
++ */
++ if (tick_check_oneshot_change(!hrtimer_is_hres_enabled()))
++ hrtimer_switch_to_hres();
++}
++
++/*
++ * Called from hardirq context every jiffy
++ */
++void hrtimer_run_queues(void)
++{
++ struct rb_node *node;
++ struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
++ struct hrtimer_clock_base *base;
++ int index, gettime = 1;
++
++ if (hrtimer_hres_active())
++ return;
++
++ for (index = 0; index < HRTIMER_MAX_CLOCK_BASES; index++) {
++ base = &cpu_base->clock_base[index];
++
++ if (!base->first)
++ continue;
++
++ if (gettime) {
++ hrtimer_get_softirq_time(cpu_base);
++ gettime = 0;
++ }
++
++ raw_spin_lock(&cpu_base->lock);
++
++ while ((node = base->first)) {
++ struct hrtimer *timer;
++
++ timer = rb_entry(node, struct hrtimer, node);
++ if (base->softirq_time.tv64 <=
++ hrtimer_get_expires_tv64(timer))
++ break;
++
++ __run_hrtimer(timer, &base->softirq_time);
++ }
++ raw_spin_unlock(&cpu_base->lock);
++ }
++}
++
++/*
++ * Sleep related functions:
++ */
++static enum hrtimer_restart hrtimer_wakeup(struct hrtimer *timer)
++{
++ struct hrtimer_sleeper *t =
++ container_of(timer, struct hrtimer_sleeper, timer);
++ struct task_struct *task = t->task;
++
++ t->task = NULL;
++ if (task)
++ wake_up_process(task);
++
++ return HRTIMER_NORESTART;
++}
++
++void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task)
++{
++ sl->timer.function = hrtimer_wakeup;
++ sl->task = task;
++}
++EXPORT_SYMBOL_GPL(hrtimer_init_sleeper);
++
++static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode)
++{
++ hrtimer_init_sleeper(t, current);
++
++ do {
++ set_current_state(TASK_INTERRUPTIBLE);
++ hrtimer_start_expires(&t->timer, mode);
++ if (!hrtimer_active(&t->timer))
++ t->task = NULL;
++
++ if (likely(t->task))
++ schedule();
++
++ hrtimer_cancel(&t->timer);
++ mode = HRTIMER_MODE_ABS;
++
++ } while (t->task && !signal_pending(current));
++
++ __set_current_state(TASK_RUNNING);
++
++ return t->task == NULL;
++}
++
++static int update_rmtp(struct hrtimer *timer, struct timespec __user *rmtp)
++{
++ struct timespec rmt;
++ ktime_t rem;
++
++ rem = hrtimer_expires_remaining(timer);
++ if (rem.tv64 <= 0)
++ return 0;
++ rmt = ktime_to_timespec(rem);
++
++ if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
++ return -EFAULT;
++
++ return 1;
++}
++
++long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
++{
++ struct hrtimer_sleeper t;
++ struct timespec __user *rmtp;
++ int ret = 0;
++
++ hrtimer_init_on_stack(&t.timer, restart->nanosleep.index,
++ HRTIMER_MODE_ABS);
++ hrtimer_set_expires_tv64(&t.timer, restart->nanosleep.expires);
++
++ if (do_nanosleep(&t, HRTIMER_MODE_ABS))
++ goto out;
++
++ rmtp = restart->nanosleep.rmtp;
++ if (rmtp) {
++ ret = update_rmtp(&t.timer, rmtp);
++ if (ret <= 0)
++ goto out;
++ }
++
++ /* The other values in restart are already filled in */
++ ret = -ERESTART_RESTARTBLOCK;
++out:
++ destroy_hrtimer_on_stack(&t.timer);
++ return ret;
++}
++
++long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
++ const enum hrtimer_mode mode, const clockid_t clockid)
++{
++ struct restart_block *restart;
++ struct hrtimer_sleeper t;
++ int ret = 0;
++ unsigned long slack;
++
++ slack = current->timer_slack_ns;
++ if (rt_task(current))
++ slack = 0;
++
++ hrtimer_init_on_stack(&t.timer, clockid, mode);
++ hrtimer_set_expires_range_ns(&t.timer, timespec_to_ktime(*rqtp), slack);
++ if (do_nanosleep(&t, mode))
++ goto out;
++
++ /* Absolute timers do not update the rmtp value and restart: */
++ if (mode == HRTIMER_MODE_ABS) {
++ ret = -ERESTARTNOHAND;
++ goto out;
++ }
++
++ if (rmtp) {
++ ret = update_rmtp(&t.timer, rmtp);
++ if (ret <= 0)
++ goto out;
++ }
++
++ restart = ¤t_thread_info()->restart_block;
++ restart->fn = hrtimer_nanosleep_restart;
++ restart->nanosleep.index = t.timer.base->index;
++ restart->nanosleep.rmtp = rmtp;
++ restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer);
++
++ ret = -ERESTART_RESTARTBLOCK;
++out:
++ destroy_hrtimer_on_stack(&t.timer);
++ return ret;
++}
++
++SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,
++ struct timespec __user *, rmtp)
++{
++ struct timespec tu;
++
++ if (copy_from_user(&tu, rqtp, sizeof(tu)))
++ return -EFAULT;
++
++ if (!timespec_valid(&tu))
++ return -EINVAL;
++
++ return hrtimer_nanosleep(&tu, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
++}
++
++/*
++ * Functions related to boot-time initialization:
++ */
++static void __cpuinit init_hrtimers_cpu(int cpu)
++{
++ struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);
++ int i;
++
++ raw_spin_lock_init(&cpu_base->lock);
++
++ for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
++ cpu_base->clock_base[i].cpu_base = cpu_base;
++
++ hrtimer_init_hres(cpu_base);
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++
++static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
++ struct hrtimer_clock_base *new_base)
++{
++ struct hrtimer *timer;
++ struct rb_node *node;
++
++ while ((node = rb_first(&old_base->active))) {
++ timer = rb_entry(node, struct hrtimer, node);
++ BUG_ON(hrtimer_callback_running(timer));
++ debug_deactivate(timer);
++
++ /*
++ * Mark it as STATE_MIGRATE not INACTIVE otherwise the
++ * timer could be seen as !active and just vanish away
++ * under us on another CPU
++ */
++ __remove_hrtimer(timer, old_base, HRTIMER_STATE_MIGRATE, 0);
++ timer->base = new_base;
++ /*
++ * Enqueue the timers on the new cpu. This does not
++ * reprogram the event device in case the timer
++ * expires before the earliest on this CPU, but we run
++ * hrtimer_interrupt after we migrated everything to
++ * sort out already expired timers and reprogram the
++ * event device.
++ */
++ enqueue_hrtimer(timer, new_base);
++
++ /* Clear the migration state bit */
++ timer->state &= ~HRTIMER_STATE_MIGRATE;
++ }
++}
++
++static void migrate_hrtimers(int scpu)
++{
++ struct hrtimer_cpu_base *old_base, *new_base;
++ int i;
++
++ BUG_ON(cpu_online(scpu));
++ tick_cancel_sched_timer(scpu);
++
++ local_irq_disable();
++ old_base = &per_cpu(hrtimer_bases, scpu);
++ new_base = &__get_cpu_var(hrtimer_bases);
++ /*
++ * The caller is globally serialized and nobody else
++ * takes two locks at once, deadlock is not possible.
++ */
++ raw_spin_lock(&new_base->lock);
++ raw_spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
++
++ for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
++ migrate_hrtimer_list(&old_base->clock_base[i],
++ &new_base->clock_base[i]);
++ }
++
++ raw_spin_unlock(&old_base->lock);
++ raw_spin_unlock(&new_base->lock);
++
++ /* Check, if we got expired work to do */
++ __hrtimer_peek_ahead_timers();
++ local_irq_enable();
++}
++
++#endif /* CONFIG_HOTPLUG_CPU */
++
++static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self,
++ unsigned long action, void *hcpu)
++{
++ int scpu = (long)hcpu;
++
++ switch (action) {
++
++ case CPU_UP_PREPARE:
++ case CPU_UP_PREPARE_FROZEN:
++ init_hrtimers_cpu(scpu);
++ break;
++
++#ifdef CONFIG_HOTPLUG_CPU
++ case CPU_DYING:
++ case CPU_DYING_FROZEN:
++ clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DYING, &scpu);
++ break;
++ case CPU_DEAD:
++ case CPU_DEAD_FROZEN:
++ {
++ clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DEAD, &scpu);
++ migrate_hrtimers(scpu);
++ break;
++ }
++#endif
++
++ default:
++ break;
++ }
++
++ return NOTIFY_OK;
++}
++
++static struct notifier_block __cpuinitdata hrtimers_nb = {
++ .notifier_call = hrtimer_cpu_notify,
++};
++
++void __init hrtimers_init(void)
++{
++ hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE,
++ (void *)(long)smp_processor_id());
++ register_cpu_notifier(&hrtimers_nb);
++#ifdef CONFIG_HIGH_RES_TIMERS
++ open_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq);
++#endif
++}
++
++/**
++ * schedule_hrtimeout_range_clock - sleep until timeout
++ * @expires: timeout value (ktime_t)
++ * @delta: slack in expires timeout (ktime_t)
++ * @mode: timer mode, HRTIMER_MODE_ABS or HRTIMER_MODE_REL
++ * @clock: timer clock, CLOCK_MONOTONIC or CLOCK_REALTIME
++ */
++int __sched
++schedule_hrtimeout_range_clock(ktime_t *expires, unsigned long delta,
++ const enum hrtimer_mode mode, int clock)
++{
++ struct hrtimer_sleeper t;
++
++ /*
++ * Optimize when a zero timeout value is given. It does not
++ * matter whether this is an absolute or a relative time.
++ */
++ if (expires && !expires->tv64) {
++ __set_current_state(TASK_RUNNING);
++ return 0;
++ }
++
++ /*
++ * A NULL parameter means "inifinte"
++ */
++ if (!expires) {
++ schedule();
++ __set_current_state(TASK_RUNNING);
++ return -EINTR;
++ }
++
++ hrtimer_init_on_stack(&t.timer, clock, mode);
++ hrtimer_set_expires_range_ns(&t.timer, *expires, delta);
++
++ hrtimer_init_sleeper(&t, current);
++
++ hrtimer_start_expires(&t.timer, mode);
++ if (!hrtimer_active(&t.timer))
++ t.task = NULL;
++
++ if (likely(t.task))
++ schedule();
++
++ hrtimer_cancel(&t.timer);
++ destroy_hrtimer_on_stack(&t.timer);
++
++ __set_current_state(TASK_RUNNING);
++
++ return !t.task ? 0 : -EINTR;
++}
++
++/**
++ * schedule_hrtimeout_range - sleep until timeout
++ * @expires: timeout value (ktime_t)
++ * @delta: slack in expires timeout (ktime_t)
++ * @mode: timer mode, HRTIMER_MODE_ABS or HRTIMER_MODE_REL
++ *
++ * Make the current task sleep until the given expiry time has
++ * elapsed. The routine will return immediately unless
++ * the current task state has been set (see set_current_state()).
++ *
++ * The @delta argument gives the kernel the freedom to schedule the
++ * actual wakeup to a time that is both power and performance friendly.
++ * The kernel give the normal best effort behavior for "@expires+ at delta",
++ * but may decide to fire the timer earlier, but no earlier than @expires.
++ *
++ * You can set the task state as follows -
++ *
++ * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
++ * pass before the routine returns.
++ *
++ * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
++ * delivered to the current task.
++ *
++ * The current task state is guaranteed to be TASK_RUNNING when this
++ * routine returns.
++ *
++ * Returns 0 when the timer has expired otherwise -EINTR
++ */
++int __sched schedule_hrtimeout_range(ktime_t *expires, unsigned long delta,
++ const enum hrtimer_mode mode)
++{
++ return schedule_hrtimeout_range_clock(expires, delta, mode,
++ CLOCK_MONOTONIC);
++}
++EXPORT_SYMBOL_GPL(schedule_hrtimeout_range);
++
++/**
++ * schedule_hrtimeout - sleep until timeout
++ * @expires: timeout value (ktime_t)
++ * @mode: timer mode, HRTIMER_MODE_ABS or HRTIMER_MODE_REL
++ *
++ * Make the current task sleep until the given expiry time has
++ * elapsed. The routine will return immediately unless
++ * the current task state has been set (see set_current_state()).
++ *
++ * You can set the task state as follows -
++ *
++ * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
++ * pass before the routine returns.
++ *
++ * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
++ * delivered to the current task.
++ *
++ * The current task state is guaranteed to be TASK_RUNNING when this
++ * routine returns.
++ *
++ * Returns 0 when the timer has expired otherwise -EINTR
++ */
++int __sched schedule_hrtimeout(ktime_t *expires,
++ const enum hrtimer_mode mode)
++{
++ return schedule_hrtimeout_range(expires, 0, mode);
++}
++EXPORT_SYMBOL_GPL(schedule_hrtimeout);
+diff -rupN linux-2.6.35.11/kernel/itimer.c linux-2.6.35.11-ts7500/kernel/itimer.c
+--- linux-2.6.35.11/kernel/itimer.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/kernel/itimer.c 2011-03-14 11:18:24.000000000 -0400
+@@ -220,6 +220,7 @@ again:
+ if (expires.tv64 != 0) {
+ tsk->signal->it_real_incr =
+ timeval_to_ktime(value->it_interval);
++
+ hrtimer_start(timer, expires, HRTIMER_MODE_REL);
+ } else
+ tsk->signal->it_real_incr.tv64 = 0;
+@@ -255,6 +256,7 @@ unsigned int alarm_setitimer(unsigned in
+ {
+ struct itimerval it_new, it_old;
+
++
+ #if BITS_PER_LONG < 64
+ if (seconds > INT_MAX)
+ seconds = INT_MAX;
+diff -rupN linux-2.6.35.11/kernel/sysctl_binary.c linux-2.6.35.11-ts7500/kernel/sysctl_binary.c
+--- linux-2.6.35.11/kernel/sysctl_binary.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/kernel/sysctl_binary.c 2011-03-14 11:18:24.000000000 -0400
+@@ -828,6 +828,13 @@ static const struct bin_table bin_ipmi_t
+ {}
+ };
+
++#ifdef CONFIG_ARCH_STR8100
++static struct trans_ctl_table trans_i2c_table[] = {
++ {DEV_I2C_CLOCK, "str8100_clock"},
++ {DEV_I2C_DEBUG, "str8100_debug"}
++};
++#endif
++
+ static const struct bin_table bin_mac_hid_files[] = {
+ /* DEV_MAC_HID_KEYBOARD_SENDS_LINUX_KEYCODES unused */
+ /* DEV_MAC_HID_KEYBOARD_LOCK_KEYCODES unused */
+@@ -857,6 +864,9 @@ static const struct bin_table bin_dev_ta
+ { CTL_DIR, DEV_MAC_HID, "mac_hid", bin_mac_hid_files },
+ { CTL_DIR, DEV_SCSI, "scsi", bin_scsi_table },
+ { CTL_DIR, DEV_IPMI, "ipmi", bin_ipmi_table },
++#ifdef CONFIG_ARCH_STR8100
++ { DEV_I2C, "i2c", trans_i2c_table },
++#endif
+ {}
+ };
+
+diff -rupN linux-2.6.35.11/kernel/time/tick-oneshot.c linux-2.6.35.11-ts7500/kernel/time/tick-oneshot.c
+--- linux-2.6.35.11/kernel/time/tick-oneshot.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/kernel/time/tick-oneshot.c 2011-03-14 11:18:24.000000000 -0400
+@@ -132,6 +132,8 @@ int tick_switch_to_oneshot(void (*handle
+ struct tick_device *td = &__get_cpu_var(tick_cpu_device);
+ struct clock_event_device *dev = td->evtdev;
+
++ printk("tick_switch_to_oneshot()\n");
++
+ if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT) ||
+ !tick_device_is_functional(dev)) {
+
+diff -rupN linux-2.6.35.11/kernel/timer.c linux-2.6.35.11-ts7500/kernel/timer.c
+--- linux-2.6.35.11/kernel/timer.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/kernel/timer.c 2011-03-14 11:18:24.000000000 -0400
+@@ -590,7 +590,7 @@ static void __init_timer(struct timer_li
+ void init_timer_key(struct timer_list *timer,
+ const char *name,
+ struct lock_class_key *key)
+-{
++{
+ debug_init(timer);
+ __init_timer(timer, name, key);
+ }
+@@ -795,7 +795,7 @@ unsigned long apply_slack(struct timer_l
+ * active timer returns 1.)
+ */
+ int mod_timer(struct timer_list *timer, unsigned long expires)
+-{
++{
+ /*
+ * This is a common optimization triggered by the
+ * networking code - if the timer is re-modified
+@@ -847,7 +847,10 @@ EXPORT_SYMBOL(mod_timer_pinned);
+ * timer tick.
+ */
+ void add_timer(struct timer_list *timer)
+-{
++{
++
++ //printk("add_timer 0x%08lX %lu\n", timer->function, timer->expires - jiffies);
++
+ BUG_ON(timer_pending(timer));
+ mod_timer(timer, timer->expires);
+ }
+@@ -864,7 +867,7 @@ void add_timer_on(struct timer_list *tim
+ {
+ struct tvec_base *base = per_cpu(tvec_bases, cpu);
+ unsigned long flags;
+-
++
+ timer_stats_timer_set_start_info(timer);
+ BUG_ON(timer_pending(timer) || !timer->function);
+ spin_lock_irqsave(&base->lock, flags);
+@@ -1069,7 +1072,7 @@ static void call_timer_fn(struct timer_l
+ static inline void __run_timers(struct tvec_base *base)
+ {
+ struct timer_list *timer;
+-
++
+ spin_lock_irq(&base->lock);
+ while (time_after_eq(jiffies, base->timer_jiffies)) {
+ struct list_head work_list;
+@@ -1423,7 +1426,7 @@ signed long __sched schedule_timeout(sig
+ {
+ struct timer_list timer;
+ unsigned long expire;
+-
++
+ switch (timeout)
+ {
+ case MAX_SCHEDULE_TIMEOUT:
+@@ -1720,7 +1723,8 @@ void __init init_timers(void)
+ {
+ int err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
+ (void *)(long)smp_processor_id());
+-
++
++
+ init_timer_stats();
+
+ BUG_ON(err != NOTIFY_OK);
+@@ -1734,8 +1738,10 @@ void __init init_timers(void)
+ */
+ void msleep(unsigned int msecs)
+ {
+- unsigned long timeout = msecs_to_jiffies(msecs) + 1;
+-
++ unsigned long timeout = msecs_to_jiffies(msecs) + 1;
++
++ //printk("msleep %d\n", msecs);
++
+ while (timeout)
+ timeout = schedule_timeout_uninterruptible(timeout);
+ }
+@@ -1749,7 +1755,9 @@ EXPORT_SYMBOL(msleep);
+ unsigned long msleep_interruptible(unsigned int msecs)
+ {
+ unsigned long timeout = msecs_to_jiffies(msecs) + 1;
+-
++
++ //printk("msleep_interruptible %d\n", msecs);
++
+ while (timeout && !signal_pending(current))
+ timeout = schedule_timeout_interruptible(timeout);
+ return jiffies_to_msecs(timeout);
+diff -rupN linux-2.6.35.11/kernel/timer.c.orig linux-2.6.35.11-ts7500/kernel/timer.c.orig
+--- linux-2.6.35.11/kernel/timer.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/kernel/timer.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,1758 @@
++/*
++ * linux/kernel/timer.c
++ *
++ * Kernel internal timers, basic process system calls
++ *
++ * Copyright (C) 1991, 1992 Linus Torvalds
++ *
++ * 1997-01-28 Modified by Finn Arne Gangstad to make timers scale better.
++ *
++ * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
++ * "A Kernel Model for Precision Timekeeping" by Dave Mills
++ * 1998-12-24 Fixed a xtime SMP race (we need the xtime_lock rw spinlock to
++ * serialize accesses to xtime/lost_ticks).
++ * Copyright (C) 1998 Andrea Arcangeli
++ * 1999-03-10 Improved NTP compatibility by Ulrich Windl
++ * 2002-05-31 Move sys_sysinfo here and make its locking sane, Robert Love
++ * 2000-10-05 Implemented scalable SMP per-CPU timer handling.
++ * Copyright (C) 2000, 2001, 2002 Ingo Molnar
++ * Designed by David S. Miller, Alexey Kuznetsov and Ingo Molnar
++ */
++
++#include <linux/kernel_stat.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/percpu.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/swap.h>
++#include <linux/pid_namespace.h>
++#include <linux/notifier.h>
++#include <linux/thread_info.h>
++#include <linux/time.h>
++#include <linux/jiffies.h>
++#include <linux/posix-timers.h>
++#include <linux/cpu.h>
++#include <linux/syscalls.h>
++#include <linux/delay.h>
++#include <linux/tick.h>
++#include <linux/kallsyms.h>
++#include <linux/perf_event.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++
++#include <asm/uaccess.h>
++#include <asm/unistd.h>
++#include <asm/div64.h>
++#include <asm/timex.h>
++#include <asm/io.h>
++
++#define CREATE_TRACE_POINTS
++#include <trace/events/timer.h>
++
++u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;
++
++EXPORT_SYMBOL(jiffies_64);
++
++/*
++ * per-CPU timer vector definitions:
++ */
++#define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6)
++#define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8)
++#define TVN_SIZE (1 << TVN_BITS)
++#define TVR_SIZE (1 << TVR_BITS)
++#define TVN_MASK (TVN_SIZE - 1)
++#define TVR_MASK (TVR_SIZE - 1)
++
++struct tvec {
++ struct list_head vec[TVN_SIZE];
++};
++
++struct tvec_root {
++ struct list_head vec[TVR_SIZE];
++};
++
++struct tvec_base {
++ spinlock_t lock;
++ struct timer_list *running_timer;
++ unsigned long timer_jiffies;
++ unsigned long next_timer;
++ struct tvec_root tv1;
++ struct tvec tv2;
++ struct tvec tv3;
++ struct tvec tv4;
++ struct tvec tv5;
++} ____cacheline_aligned;
++
++struct tvec_base boot_tvec_bases;
++EXPORT_SYMBOL(boot_tvec_bases);
++static DEFINE_PER_CPU(struct tvec_base *, tvec_bases) = &boot_tvec_bases;
++
++/*
++ * Note that all tvec_bases are 2 byte aligned and lower bit of
++ * base in timer_list is guaranteed to be zero. Use the LSB for
++ * the new flag to indicate whether the timer is deferrable
++ */
++#define TBASE_DEFERRABLE_FLAG (0x1)
++
++/* Functions below help us manage 'deferrable' flag */
++static inline unsigned int tbase_get_deferrable(struct tvec_base *base)
++{
++ return ((unsigned int)(unsigned long)base & TBASE_DEFERRABLE_FLAG);
++}
++
++static inline struct tvec_base *tbase_get_base(struct tvec_base *base)
++{
++ return ((struct tvec_base *)((unsigned long)base & ~TBASE_DEFERRABLE_FLAG));
++}
++
++static inline void timer_set_deferrable(struct timer_list *timer)
++{
++ timer->base = ((struct tvec_base *)((unsigned long)(timer->base) |
++ TBASE_DEFERRABLE_FLAG));
++}
++
++static inline void
++timer_set_base(struct timer_list *timer, struct tvec_base *new_base)
++{
++ timer->base = (struct tvec_base *)((unsigned long)(new_base) |
++ tbase_get_deferrable(timer->base));
++}
++
++static unsigned long round_jiffies_common(unsigned long j, int cpu,
++ bool force_up)
++{
++ int rem;
++ unsigned long original = j;
++
++ /*
++ * We don't want all cpus firing their timers at once hitting the
++ * same lock or cachelines, so we skew each extra cpu with an extra
++ * 3 jiffies. This 3 jiffies came originally from the mm/ code which
++ * already did this.
++ * The skew is done by adding 3*cpunr, then round, then subtract this
++ * extra offset again.
++ */
++ j += cpu * 3;
++
++ rem = j % HZ;
++
++ /*
++ * If the target jiffie is just after a whole second (which can happen
++ * due to delays of the timer irq, long irq off times etc etc) then
++ * we should round down to the whole second, not up. Use 1/4th second
++ * as cutoff for this rounding as an extreme upper bound for this.
++ * But never round down if @force_up is set.
++ */
++ if (rem < HZ/4 && !force_up) /* round down */
++ j = j - rem;
++ else /* round up */
++ j = j - rem + HZ;
++
++ /* now that we have rounded, subtract the extra skew again */
++ j -= cpu * 3;
++
++ if (j <= jiffies) /* rounding ate our timeout entirely; */
++ return original;
++ return j;
++}
++
++/**
++ * __round_jiffies - function to round jiffies to a full second
++ * @j: the time in (absolute) jiffies that should be rounded
++ * @cpu: the processor number on which the timeout will happen
++ *
++ * __round_jiffies() rounds an absolute time in the future (in jiffies)
++ * up or down to (approximately) full seconds. This is useful for timers
++ * for which the exact time they fire does not matter too much, as long as
++ * they fire approximately every X seconds.
++ *
++ * By rounding these timers to whole seconds, all such timers will fire
++ * at the same time, rather than at various times spread out. The goal
++ * of this is to have the CPU wake up less, which saves power.
++ *
++ * The exact rounding is skewed for each processor to avoid all
++ * processors firing at the exact same time, which could lead
++ * to lock contention or spurious cache line bouncing.
++ *
++ * The return value is the rounded version of the @j parameter.
++ */
++unsigned long __round_jiffies(unsigned long j, int cpu)
++{
++ return round_jiffies_common(j, cpu, false);
++}
++EXPORT_SYMBOL_GPL(__round_jiffies);
++
++/**
++ * __round_jiffies_relative - function to round jiffies to a full second
++ * @j: the time in (relative) jiffies that should be rounded
++ * @cpu: the processor number on which the timeout will happen
++ *
++ * __round_jiffies_relative() rounds a time delta in the future (in jiffies)
++ * up or down to (approximately) full seconds. This is useful for timers
++ * for which the exact time they fire does not matter too much, as long as
++ * they fire approximately every X seconds.
++ *
++ * By rounding these timers to whole seconds, all such timers will fire
++ * at the same time, rather than at various times spread out. The goal
++ * of this is to have the CPU wake up less, which saves power.
++ *
++ * The exact rounding is skewed for each processor to avoid all
++ * processors firing at the exact same time, which could lead
++ * to lock contention or spurious cache line bouncing.
++ *
++ * The return value is the rounded version of the @j parameter.
++ */
++unsigned long __round_jiffies_relative(unsigned long j, int cpu)
++{
++ unsigned long j0 = jiffies;
++
++ /* Use j0 because jiffies might change while we run */
++ return round_jiffies_common(j + j0, cpu, false) - j0;
++}
++EXPORT_SYMBOL_GPL(__round_jiffies_relative);
++
++/**
++ * round_jiffies - function to round jiffies to a full second
++ * @j: the time in (absolute) jiffies that should be rounded
++ *
++ * round_jiffies() rounds an absolute time in the future (in jiffies)
++ * up or down to (approximately) full seconds. This is useful for timers
++ * for which the exact time they fire does not matter too much, as long as
++ * they fire approximately every X seconds.
++ *
++ * By rounding these timers to whole seconds, all such timers will fire
++ * at the same time, rather than at various times spread out. The goal
++ * of this is to have the CPU wake up less, which saves power.
++ *
++ * The return value is the rounded version of the @j parameter.
++ */
++unsigned long round_jiffies(unsigned long j)
++{
++ return round_jiffies_common(j, raw_smp_processor_id(), false);
++}
++EXPORT_SYMBOL_GPL(round_jiffies);
++
++/**
++ * round_jiffies_relative - function to round jiffies to a full second
++ * @j: the time in (relative) jiffies that should be rounded
++ *
++ * round_jiffies_relative() rounds a time delta in the future (in jiffies)
++ * up or down to (approximately) full seconds. This is useful for timers
++ * for which the exact time they fire does not matter too much, as long as
++ * they fire approximately every X seconds.
++ *
++ * By rounding these timers to whole seconds, all such timers will fire
++ * at the same time, rather than at various times spread out. The goal
++ * of this is to have the CPU wake up less, which saves power.
++ *
++ * The return value is the rounded version of the @j parameter.
++ */
++unsigned long round_jiffies_relative(unsigned long j)
++{
++ return __round_jiffies_relative(j, raw_smp_processor_id());
++}
++EXPORT_SYMBOL_GPL(round_jiffies_relative);
++
++/**
++ * __round_jiffies_up - function to round jiffies up to a full second
++ * @j: the time in (absolute) jiffies that should be rounded
++ * @cpu: the processor number on which the timeout will happen
++ *
++ * This is the same as __round_jiffies() except that it will never
++ * round down. This is useful for timeouts for which the exact time
++ * of firing does not matter too much, as long as they don't fire too
++ * early.
++ */
++unsigned long __round_jiffies_up(unsigned long j, int cpu)
++{
++ return round_jiffies_common(j, cpu, true);
++}
++EXPORT_SYMBOL_GPL(__round_jiffies_up);
++
++/**
++ * __round_jiffies_up_relative - function to round jiffies up to a full second
++ * @j: the time in (relative) jiffies that should be rounded
++ * @cpu: the processor number on which the timeout will happen
++ *
++ * This is the same as __round_jiffies_relative() except that it will never
++ * round down. This is useful for timeouts for which the exact time
++ * of firing does not matter too much, as long as they don't fire too
++ * early.
++ */
++unsigned long __round_jiffies_up_relative(unsigned long j, int cpu)
++{
++ unsigned long j0 = jiffies;
++
++ /* Use j0 because jiffies might change while we run */
++ return round_jiffies_common(j + j0, cpu, true) - j0;
++}
++EXPORT_SYMBOL_GPL(__round_jiffies_up_relative);
++
++/**
++ * round_jiffies_up - function to round jiffies up to a full second
++ * @j: the time in (absolute) jiffies that should be rounded
++ *
++ * This is the same as round_jiffies() except that it will never
++ * round down. This is useful for timeouts for which the exact time
++ * of firing does not matter too much, as long as they don't fire too
++ * early.
++ */
++unsigned long round_jiffies_up(unsigned long j)
++{
++ return round_jiffies_common(j, raw_smp_processor_id(), true);
++}
++EXPORT_SYMBOL_GPL(round_jiffies_up);
++
++/**
++ * round_jiffies_up_relative - function to round jiffies up to a full second
++ * @j: the time in (relative) jiffies that should be rounded
++ *
++ * This is the same as round_jiffies_relative() except that it will never
++ * round down. This is useful for timeouts for which the exact time
++ * of firing does not matter too much, as long as they don't fire too
++ * early.
++ */
++unsigned long round_jiffies_up_relative(unsigned long j)
++{
++ return __round_jiffies_up_relative(j, raw_smp_processor_id());
++}
++EXPORT_SYMBOL_GPL(round_jiffies_up_relative);
++
++/**
++ * set_timer_slack - set the allowed slack for a timer
++ * @slack_hz: the amount of time (in jiffies) allowed for rounding
++ *
++ * Set the amount of time, in jiffies, that a certain timer has
++ * in terms of slack. By setting this value, the timer subsystem
++ * will schedule the actual timer somewhere between
++ * the time mod_timer() asks for, and that time plus the slack.
++ *
++ * By setting the slack to -1, a percentage of the delay is used
++ * instead.
++ */
++void set_timer_slack(struct timer_list *timer, int slack_hz)
++{
++ timer->slack = slack_hz;
++}
++EXPORT_SYMBOL_GPL(set_timer_slack);
++
++
++static inline void set_running_timer(struct tvec_base *base,
++ struct timer_list *timer)
++{
++#ifdef CONFIG_SMP
++ base->running_timer = timer;
++#endif
++}
++
++static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
++{
++ unsigned long expires = timer->expires;
++ unsigned long idx = expires - base->timer_jiffies;
++ struct list_head *vec;
++
++ if (idx < TVR_SIZE) {
++ int i = expires & TVR_MASK;
++ vec = base->tv1.vec + i;
++ } else if (idx < 1 << (TVR_BITS + TVN_BITS)) {
++ int i = (expires >> TVR_BITS) & TVN_MASK;
++ vec = base->tv2.vec + i;
++ } else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) {
++ int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;
++ vec = base->tv3.vec + i;
++ } else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) {
++ int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
++ vec = base->tv4.vec + i;
++ } else if ((signed long) idx < 0) {
++ /*
++ * Can happen if you add a timer with expires == jiffies,
++ * or you set a timer to go off in the past
++ */
++ vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);
++ } else {
++ int i;
++ /* If the timeout is larger than 0xffffffff on 64-bit
++ * architectures then we use the maximum timeout:
++ */
++ if (idx > 0xffffffffUL) {
++ idx = 0xffffffffUL;
++ expires = idx + base->timer_jiffies;
++ }
++ i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
++ vec = base->tv5.vec + i;
++ }
++ /*
++ * Timers are FIFO:
++ */
++ list_add_tail(&timer->entry, vec);
++}
++
++#ifdef CONFIG_TIMER_STATS
++void __timer_stats_timer_set_start_info(struct timer_list *timer, void *addr)
++{
++ if (timer->start_site)
++ return;
++
++ timer->start_site = addr;
++ memcpy(timer->start_comm, current->comm, TASK_COMM_LEN);
++ timer->start_pid = current->pid;
++}
++
++static void timer_stats_account_timer(struct timer_list *timer)
++{
++ unsigned int flag = 0;
++
++ if (likely(!timer->start_site))
++ return;
++ if (unlikely(tbase_get_deferrable(timer->base)))
++ flag |= TIMER_STATS_FLAG_DEFERRABLE;
++
++ timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
++ timer->function, timer->start_comm, flag);
++}
++
++#else
++static void timer_stats_account_timer(struct timer_list *timer) {}
++#endif
++
++#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
++
++static struct debug_obj_descr timer_debug_descr;
++
++/*
++ * fixup_init is called when:
++ * - an active object is initialized
++ */
++static int timer_fixup_init(void *addr, enum debug_obj_state state)
++{
++ struct timer_list *timer = addr;
++
++ switch (state) {
++ case ODEBUG_STATE_ACTIVE:
++ del_timer_sync(timer);
++ debug_object_init(timer, &timer_debug_descr);
++ return 1;
++ default:
++ return 0;
++ }
++}
++
++/*
++ * fixup_activate is called when:
++ * - an active object is activated
++ * - an unknown object is activated (might be a statically initialized object)
++ */
++static int timer_fixup_activate(void *addr, enum debug_obj_state state)
++{
++ struct timer_list *timer = addr;
++
++ switch (state) {
++
++ case ODEBUG_STATE_NOTAVAILABLE:
++ /*
++ * This is not really a fixup. The timer was
++ * statically initialized. We just make sure that it
++ * is tracked in the object tracker.
++ */
++ if (timer->entry.next == NULL &&
++ timer->entry.prev == TIMER_ENTRY_STATIC) {
++ debug_object_init(timer, &timer_debug_descr);
++ debug_object_activate(timer, &timer_debug_descr);
++ return 0;
++ } else {
++ WARN_ON_ONCE(1);
++ }
++ return 0;
++
++ case ODEBUG_STATE_ACTIVE:
++ WARN_ON(1);
++
++ default:
++ return 0;
++ }
++}
++
++/*
++ * fixup_free is called when:
++ * - an active object is freed
++ */
++static int timer_fixup_free(void *addr, enum debug_obj_state state)
++{
++ struct timer_list *timer = addr;
++
++ switch (state) {
++ case ODEBUG_STATE_ACTIVE:
++ del_timer_sync(timer);
++ debug_object_free(timer, &timer_debug_descr);
++ return 1;
++ default:
++ return 0;
++ }
++}
++
++static struct debug_obj_descr timer_debug_descr = {
++ .name = "timer_list",
++ .fixup_init = timer_fixup_init,
++ .fixup_activate = timer_fixup_activate,
++ .fixup_free = timer_fixup_free,
++};
++
++static inline void debug_timer_init(struct timer_list *timer)
++{
++ debug_object_init(timer, &timer_debug_descr);
++}
++
++static inline void debug_timer_activate(struct timer_list *timer)
++{
++ debug_object_activate(timer, &timer_debug_descr);
++}
++
++static inline void debug_timer_deactivate(struct timer_list *timer)
++{
++ debug_object_deactivate(timer, &timer_debug_descr);
++}
++
++static inline void debug_timer_free(struct timer_list *timer)
++{
++ debug_object_free(timer, &timer_debug_descr);
++}
++
++static void __init_timer(struct timer_list *timer,
++ const char *name,
++ struct lock_class_key *key);
++
++void init_timer_on_stack_key(struct timer_list *timer,
++ const char *name,
++ struct lock_class_key *key)
++{
++ debug_object_init_on_stack(timer, &timer_debug_descr);
++ __init_timer(timer, name, key);
++}
++EXPORT_SYMBOL_GPL(init_timer_on_stack_key);
++
++void destroy_timer_on_stack(struct timer_list *timer)
++{
++ debug_object_free(timer, &timer_debug_descr);
++}
++EXPORT_SYMBOL_GPL(destroy_timer_on_stack);
++
++#else
++static inline void debug_timer_init(struct timer_list *timer) { }
++static inline void debug_timer_activate(struct timer_list *timer) { }
++static inline void debug_timer_deactivate(struct timer_list *timer) { }
++#endif
++
++static inline void debug_init(struct timer_list *timer)
++{
++ debug_timer_init(timer);
++ trace_timer_init(timer);
++}
++
++static inline void
++debug_activate(struct timer_list *timer, unsigned long expires)
++{
++ debug_timer_activate(timer);
++ trace_timer_start(timer, expires);
++}
++
++static inline void debug_deactivate(struct timer_list *timer)
++{
++ debug_timer_deactivate(timer);
++ trace_timer_cancel(timer);
++}
++
++static void __init_timer(struct timer_list *timer,
++ const char *name,
++ struct lock_class_key *key)
++{
++ timer->entry.next = NULL;
++ timer->base = __raw_get_cpu_var(tvec_bases);
++ timer->slack = -1;
++#ifdef CONFIG_TIMER_STATS
++ timer->start_site = NULL;
++ timer->start_pid = -1;
++ memset(timer->start_comm, 0, TASK_COMM_LEN);
++#endif
++ lockdep_init_map(&timer->lockdep_map, name, key, 0);
++}
++
++/**
++ * init_timer_key - initialize a timer
++ * @timer: the timer to be initialized
++ * @name: name of the timer
++ * @key: lockdep class key of the fake lock used for tracking timer
++ * sync lock dependencies
++ *
++ * init_timer_key() must be done to a timer prior calling *any* of the
++ * other timer functions.
++ */
++void init_timer_key(struct timer_list *timer,
++ const char *name,
++ struct lock_class_key *key)
++{
++ debug_init(timer);
++ __init_timer(timer, name, key);
++}
++EXPORT_SYMBOL(init_timer_key);
++
++void init_timer_deferrable_key(struct timer_list *timer,
++ const char *name,
++ struct lock_class_key *key)
++{
++ init_timer_key(timer, name, key);
++ timer_set_deferrable(timer);
++}
++EXPORT_SYMBOL(init_timer_deferrable_key);
++
++static inline void detach_timer(struct timer_list *timer,
++ int clear_pending)
++{
++ struct list_head *entry = &timer->entry;
++
++ debug_deactivate(timer);
++
++ __list_del(entry->prev, entry->next);
++ if (clear_pending)
++ entry->next = NULL;
++ entry->prev = LIST_POISON2;
++}
++
++/*
++ * We are using hashed locking: holding per_cpu(tvec_bases).lock
++ * means that all timers which are tied to this base via timer->base are
++ * locked, and the base itself is locked too.
++ *
++ * So __run_timers/migrate_timers can safely modify all timers which could
++ * be found on ->tvX lists.
++ *
++ * When the timer's base is locked, and the timer removed from list, it is
++ * possible to set timer->base = NULL and drop the lock: the timer remains
++ * locked.
++ */
++static struct tvec_base *lock_timer_base(struct timer_list *timer,
++ unsigned long *flags)
++ __acquires(timer->base->lock)
++{
++ struct tvec_base *base;
++
++ for (;;) {
++ struct tvec_base *prelock_base = timer->base;
++ base = tbase_get_base(prelock_base);
++ if (likely(base != NULL)) {
++ spin_lock_irqsave(&base->lock, *flags);
++ if (likely(prelock_base == timer->base))
++ return base;
++ /* The timer has migrated to another CPU */
++ spin_unlock_irqrestore(&base->lock, *flags);
++ }
++ cpu_relax();
++ }
++}
++
++static inline int
++__mod_timer(struct timer_list *timer, unsigned long expires,
++ bool pending_only, int pinned)
++{
++ struct tvec_base *base, *new_base;
++ unsigned long flags;
++ int ret = 0 , cpu;
++
++ timer_stats_timer_set_start_info(timer);
++ BUG_ON(!timer->function);
++
++ base = lock_timer_base(timer, &flags);
++
++ if (timer_pending(timer)) {
++ detach_timer(timer, 0);
++ if (timer->expires == base->next_timer &&
++ !tbase_get_deferrable(timer->base))
++ base->next_timer = base->timer_jiffies;
++ ret = 1;
++ } else {
++ if (pending_only)
++ goto out_unlock;
++ }
++
++ debug_activate(timer, expires);
++
++ cpu = smp_processor_id();
++
++#if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP)
++ if (!pinned && get_sysctl_timer_migration() && idle_cpu(cpu)) {
++ int preferred_cpu = get_nohz_load_balancer();
++
++ if (preferred_cpu >= 0)
++ cpu = preferred_cpu;
++ }
++#endif
++ new_base = per_cpu(tvec_bases, cpu);
++
++ if (base != new_base) {
++ /*
++ * We are trying to schedule the timer on the local CPU.
++ * However we can't change timer's base while it is running,
++ * otherwise del_timer_sync() can't detect that the timer's
++ * handler yet has not finished. This also guarantees that
++ * the timer is serialized wrt itself.
++ */
++ if (likely(base->running_timer != timer)) {
++ /* See the comment in lock_timer_base() */
++ timer_set_base(timer, NULL);
++ spin_unlock(&base->lock);
++ base = new_base;
++ spin_lock(&base->lock);
++ timer_set_base(timer, base);
++ }
++ }
++
++ timer->expires = expires;
++ if (time_before(timer->expires, base->next_timer) &&
++ !tbase_get_deferrable(timer->base))
++ base->next_timer = timer->expires;
++ internal_add_timer(base, timer);
++
++out_unlock:
++ spin_unlock_irqrestore(&base->lock, flags);
++
++ return ret;
++}
++
++/**
++ * mod_timer_pending - modify a pending timer's timeout
++ * @timer: the pending timer to be modified
++ * @expires: new timeout in jiffies
++ *
++ * mod_timer_pending() is the same for pending timers as mod_timer(),
++ * but will not re-activate and modify already deleted timers.
++ *
++ * It is useful for unserialized use of timers.
++ */
++int mod_timer_pending(struct timer_list *timer, unsigned long expires)
++{
++ return __mod_timer(timer, expires, true, TIMER_NOT_PINNED);
++}
++EXPORT_SYMBOL(mod_timer_pending);
++
++/*
++ * Decide where to put the timer while taking the slack into account
++ *
++ * Algorithm:
++ * 1) calculate the maximum (absolute) time
++ * 2) calculate the highest bit where the expires and new max are different
++ * 3) use this bit to make a mask
++ * 4) use the bitmask to round down the maximum time, so that all last
++ * bits are zeros
++ */
++static inline
++unsigned long apply_slack(struct timer_list *timer, unsigned long expires)
++{
++ unsigned long expires_limit, mask;
++ int bit;
++
++ expires_limit = expires;
++
++ if (timer->slack >= 0) {
++ expires_limit = expires + timer->slack;
++ } else {
++ unsigned long now = jiffies;
++
++ /* No slack, if already expired else auto slack 0.4% */
++ if (time_after(expires, now))
++ expires_limit = expires + (expires - now)/256;
++ }
++ mask = expires ^ expires_limit;
++ if (mask == 0)
++ return expires;
++
++ bit = find_last_bit(&mask, BITS_PER_LONG);
++
++ mask = (1 << bit) - 1;
++
++ expires_limit = expires_limit & ~(mask);
++
++ return expires_limit;
++}
++
++/**
++ * mod_timer - modify a timer's timeout
++ * @timer: the timer to be modified
++ * @expires: new timeout in jiffies
++ *
++ * mod_timer() is a more efficient way to update the expire field of an
++ * active timer (if the timer is inactive it will be activated)
++ *
++ * mod_timer(timer, expires) is equivalent to:
++ *
++ * del_timer(timer); timer->expires = expires; add_timer(timer);
++ *
++ * Note that if there are multiple unserialized concurrent users of the
++ * same timer, then mod_timer() is the only safe way to modify the timeout,
++ * since add_timer() cannot modify an already running timer.
++ *
++ * The function returns whether it has modified a pending timer or not.
++ * (ie. mod_timer() of an inactive timer returns 0, mod_timer() of an
++ * active timer returns 1.)
++ */
++int mod_timer(struct timer_list *timer, unsigned long expires)
++{
++ /*
++ * This is a common optimization triggered by the
++ * networking code - if the timer is re-modified
++ * to be the same thing then just return:
++ */
++ if (timer_pending(timer) && timer->expires == expires)
++ return 1;
++
++ expires = apply_slack(timer, expires);
++
++ return __mod_timer(timer, expires, false, TIMER_NOT_PINNED);
++}
++EXPORT_SYMBOL(mod_timer);
++
++/**
++ * mod_timer_pinned - modify a timer's timeout
++ * @timer: the timer to be modified
++ * @expires: new timeout in jiffies
++ *
++ * mod_timer_pinned() is a way to update the expire field of an
++ * active timer (if the timer is inactive it will be activated)
++ * and not allow the timer to be migrated to a different CPU.
++ *
++ * mod_timer_pinned(timer, expires) is equivalent to:
++ *
++ * del_timer(timer); timer->expires = expires; add_timer(timer);
++ */
++int mod_timer_pinned(struct timer_list *timer, unsigned long expires)
++{
++ if (timer->expires == expires && timer_pending(timer))
++ return 1;
++
++ return __mod_timer(timer, expires, false, TIMER_PINNED);
++}
++EXPORT_SYMBOL(mod_timer_pinned);
++
++/**
++ * add_timer - start a timer
++ * @timer: the timer to be added
++ *
++ * The kernel will do a ->function(->data) callback from the
++ * timer interrupt at the ->expires point in the future. The
++ * current time is 'jiffies'.
++ *
++ * The timer's ->expires, ->function (and if the handler uses it, ->data)
++ * fields must be set prior calling this function.
++ *
++ * Timers with an ->expires field in the past will be executed in the next
++ * timer tick.
++ */
++void add_timer(struct timer_list *timer)
++{
++ BUG_ON(timer_pending(timer));
++ mod_timer(timer, timer->expires);
++}
++EXPORT_SYMBOL(add_timer);
++
++/**
++ * add_timer_on - start a timer on a particular CPU
++ * @timer: the timer to be added
++ * @cpu: the CPU to start it on
++ *
++ * This is not very scalable on SMP. Double adds are not possible.
++ */
++void add_timer_on(struct timer_list *timer, int cpu)
++{
++ struct tvec_base *base = per_cpu(tvec_bases, cpu);
++ unsigned long flags;
++
++ timer_stats_timer_set_start_info(timer);
++ BUG_ON(timer_pending(timer) || !timer->function);
++ spin_lock_irqsave(&base->lock, flags);
++ timer_set_base(timer, base);
++ debug_activate(timer, timer->expires);
++ if (time_before(timer->expires, base->next_timer) &&
++ !tbase_get_deferrable(timer->base))
++ base->next_timer = timer->expires;
++ internal_add_timer(base, timer);
++ /*
++ * Check whether the other CPU is idle and needs to be
++ * triggered to reevaluate the timer wheel when nohz is
++ * active. We are protected against the other CPU fiddling
++ * with the timer by holding the timer base lock. This also
++ * makes sure that a CPU on the way to idle can not evaluate
++ * the timer wheel.
++ */
++ wake_up_idle_cpu(cpu);
++ spin_unlock_irqrestore(&base->lock, flags);
++}
++EXPORT_SYMBOL_GPL(add_timer_on);
++
++/**
++ * del_timer - deactive a timer.
++ * @timer: the timer to be deactivated
++ *
++ * del_timer() deactivates a timer - this works on both active and inactive
++ * timers.
++ *
++ * The function returns whether it has deactivated a pending timer or not.
++ * (ie. del_timer() of an inactive timer returns 0, del_timer() of an
++ * active timer returns 1.)
++ */
++int del_timer(struct timer_list *timer)
++{
++ struct tvec_base *base;
++ unsigned long flags;
++ int ret = 0;
++
++ timer_stats_timer_clear_start_info(timer);
++ if (timer_pending(timer)) {
++ base = lock_timer_base(timer, &flags);
++ if (timer_pending(timer)) {
++ detach_timer(timer, 1);
++ if (timer->expires == base->next_timer &&
++ !tbase_get_deferrable(timer->base))
++ base->next_timer = base->timer_jiffies;
++ ret = 1;
++ }
++ spin_unlock_irqrestore(&base->lock, flags);
++ }
++
++ return ret;
++}
++EXPORT_SYMBOL(del_timer);
++
++#ifdef CONFIG_SMP
++/**
++ * try_to_del_timer_sync - Try to deactivate a timer
++ * @timer: timer do del
++ *
++ * This function tries to deactivate a timer. Upon successful (ret >= 0)
++ * exit the timer is not queued and the handler is not running on any CPU.
++ *
++ * It must not be called from interrupt contexts.
++ */
++int try_to_del_timer_sync(struct timer_list *timer)
++{
++ struct tvec_base *base;
++ unsigned long flags;
++ int ret = -1;
++
++ base = lock_timer_base(timer, &flags);
++
++ if (base->running_timer == timer)
++ goto out;
++
++ timer_stats_timer_clear_start_info(timer);
++ ret = 0;
++ if (timer_pending(timer)) {
++ detach_timer(timer, 1);
++ if (timer->expires == base->next_timer &&
++ !tbase_get_deferrable(timer->base))
++ base->next_timer = base->timer_jiffies;
++ ret = 1;
++ }
++out:
++ spin_unlock_irqrestore(&base->lock, flags);
++
++ return ret;
++}
++EXPORT_SYMBOL(try_to_del_timer_sync);
++
++/**
++ * del_timer_sync - deactivate a timer and wait for the handler to finish.
++ * @timer: the timer to be deactivated
++ *
++ * This function only differs from del_timer() on SMP: besides deactivating
++ * the timer it also makes sure the handler has finished executing on other
++ * CPUs.
++ *
++ * Synchronization rules: Callers must prevent restarting of the timer,
++ * otherwise this function is meaningless. It must not be called from
++ * interrupt contexts. The caller must not hold locks which would prevent
++ * completion of the timer's handler. The timer's handler must not call
++ * add_timer_on(). Upon exit the timer is not queued and the handler is
++ * not running on any CPU.
++ *
++ * The function returns whether it has deactivated a pending timer or not.
++ */
++int del_timer_sync(struct timer_list *timer)
++{
++#ifdef CONFIG_LOCKDEP
++ unsigned long flags;
++
++ local_irq_save(flags);
++ lock_map_acquire(&timer->lockdep_map);
++ lock_map_release(&timer->lockdep_map);
++ local_irq_restore(flags);
++#endif
++
++ for (;;) {
++ int ret = try_to_del_timer_sync(timer);
++ if (ret >= 0)
++ return ret;
++ cpu_relax();
++ }
++}
++EXPORT_SYMBOL(del_timer_sync);
++#endif
++
++static int cascade(struct tvec_base *base, struct tvec *tv, int index)
++{
++ /* cascade all the timers from tv up one level */
++ struct timer_list *timer, *tmp;
++ struct list_head tv_list;
++
++ list_replace_init(tv->vec + index, &tv_list);
++
++ /*
++ * We are removing _all_ timers from the list, so we
++ * don't have to detach them individually.
++ */
++ list_for_each_entry_safe(timer, tmp, &tv_list, entry) {
++ BUG_ON(tbase_get_base(timer->base) != base);
++ internal_add_timer(base, timer);
++ }
++
++ return index;
++}
++
++static void call_timer_fn(struct timer_list *timer, void (*fn)(unsigned long),
++ unsigned long data)
++{
++ int preempt_count = preempt_count();
++
++#ifdef CONFIG_LOCKDEP
++ /*
++ * It is permissible to free the timer from inside the
++ * function that is called from it, this we need to take into
++ * account for lockdep too. To avoid bogus "held lock freed"
++ * warnings as well as problems when looking into
++ * timer->lockdep_map, make a copy and use that here.
++ */
++ struct lockdep_map lockdep_map = timer->lockdep_map;
++#endif
++ /*
++ * Couple the lock chain with the lock chain at
++ * del_timer_sync() by acquiring the lock_map around the fn()
++ * call here and in del_timer_sync().
++ */
++ lock_map_acquire(&lockdep_map);
++
++ trace_timer_expire_entry(timer);
++ fn(data);
++ trace_timer_expire_exit(timer);
++
++ lock_map_release(&lockdep_map);
++
++ if (preempt_count != preempt_count()) {
++ WARN_ONCE(1, "timer: %pF preempt leak: %08x -> %08x\n",
++ fn, preempt_count, preempt_count());
++ /*
++ * Restore the preempt count. That gives us a decent
++ * chance to survive and extract information. If the
++ * callback kept a lock held, bad luck, but not worse
++ * than the BUG() we had.
++ */
++ preempt_count() = preempt_count;
++ }
++}
++
++#define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)
++
++/**
++ * __run_timers - run all expired timers (if any) on this CPU.
++ * @base: the timer vector to be processed.
++ *
++ * This function cascades all vectors and executes all expired timer
++ * vectors.
++ */
++static inline void __run_timers(struct tvec_base *base)
++{
++ struct timer_list *timer;
++
++ spin_lock_irq(&base->lock);
++ while (time_after_eq(jiffies, base->timer_jiffies)) {
++ struct list_head work_list;
++ struct list_head *head = &work_list;
++ int index = base->timer_jiffies & TVR_MASK;
++
++ /*
++ * Cascade timers:
++ */
++ if (!index &&
++ (!cascade(base, &base->tv2, INDEX(0))) &&
++ (!cascade(base, &base->tv3, INDEX(1))) &&
++ !cascade(base, &base->tv4, INDEX(2)))
++ cascade(base, &base->tv5, INDEX(3));
++ ++base->timer_jiffies;
++ list_replace_init(base->tv1.vec + index, &work_list);
++ while (!list_empty(head)) {
++ void (*fn)(unsigned long);
++ unsigned long data;
++
++ timer = list_first_entry(head, struct timer_list,entry);
++ fn = timer->function;
++ data = timer->data;
++
++ timer_stats_account_timer(timer);
++
++ set_running_timer(base, timer);
++ detach_timer(timer, 1);
++
++ spin_unlock_irq(&base->lock);
++ call_timer_fn(timer, fn, data);
++ spin_lock_irq(&base->lock);
++ }
++ }
++ set_running_timer(base, NULL);
++ spin_unlock_irq(&base->lock);
++}
++
++#ifdef CONFIG_NO_HZ
++/*
++ * Find out when the next timer event is due to happen. This
++ * is used on S/390 to stop all activity when a CPU is idle.
++ * This function needs to be called with interrupts disabled.
++ */
++static unsigned long __next_timer_interrupt(struct tvec_base *base)
++{
++ unsigned long timer_jiffies = base->timer_jiffies;
++ unsigned long expires = timer_jiffies + NEXT_TIMER_MAX_DELTA;
++ int index, slot, array, found = 0;
++ struct timer_list *nte;
++ struct tvec *varray[4];
++
++ /* Look for timer events in tv1. */
++ index = slot = timer_jiffies & TVR_MASK;
++ do {
++ list_for_each_entry(nte, base->tv1.vec + slot, entry) {
++ if (tbase_get_deferrable(nte->base))
++ continue;
++
++ found = 1;
++ expires = nte->expires;
++ /* Look at the cascade bucket(s)? */
++ if (!index || slot < index)
++ goto cascade;
++ return expires;
++ }
++ slot = (slot + 1) & TVR_MASK;
++ } while (slot != index);
++
++cascade:
++ /* Calculate the next cascade event */
++ if (index)
++ timer_jiffies += TVR_SIZE - index;
++ timer_jiffies >>= TVR_BITS;
++
++ /* Check tv2-tv5. */
++ varray[0] = &base->tv2;
++ varray[1] = &base->tv3;
++ varray[2] = &base->tv4;
++ varray[3] = &base->tv5;
++
++ for (array = 0; array < 4; array++) {
++ struct tvec *varp = varray[array];
++
++ index = slot = timer_jiffies & TVN_MASK;
++ do {
++ list_for_each_entry(nte, varp->vec + slot, entry) {
++ if (tbase_get_deferrable(nte->base))
++ continue;
++
++ found = 1;
++ if (time_before(nte->expires, expires))
++ expires = nte->expires;
++ }
++ /*
++ * Do we still search for the first timer or are
++ * we looking up the cascade buckets ?
++ */
++ if (found) {
++ /* Look at the cascade bucket(s)? */
++ if (!index || slot < index)
++ break;
++ return expires;
++ }
++ slot = (slot + 1) & TVN_MASK;
++ } while (slot != index);
++
++ if (index)
++ timer_jiffies += TVN_SIZE - index;
++ timer_jiffies >>= TVN_BITS;
++ }
++ return expires;
++}
++
++/*
++ * Check, if the next hrtimer event is before the next timer wheel
++ * event:
++ */
++static unsigned long cmp_next_hrtimer_event(unsigned long now,
++ unsigned long expires)
++{
++ ktime_t hr_delta = hrtimer_get_next_event();
++ struct timespec tsdelta;
++ unsigned long delta;
++
++ if (hr_delta.tv64 == KTIME_MAX)
++ return expires;
++
++ /*
++ * Expired timer available, let it expire in the next tick
++ */
++ if (hr_delta.tv64 <= 0)
++ return now + 1;
++
++ tsdelta = ktime_to_timespec(hr_delta);
++ delta = timespec_to_jiffies(&tsdelta);
++
++ /*
++ * Limit the delta to the max value, which is checked in
++ * tick_nohz_stop_sched_tick():
++ */
++ if (delta > NEXT_TIMER_MAX_DELTA)
++ delta = NEXT_TIMER_MAX_DELTA;
++
++ /*
++ * Take rounding errors in to account and make sure, that it
++ * expires in the next tick. Otherwise we go into an endless
++ * ping pong due to tick_nohz_stop_sched_tick() retriggering
++ * the timer softirq
++ */
++ if (delta < 1)
++ delta = 1;
++ now += delta;
++ if (time_before(now, expires))
++ return now;
++ return expires;
++}
++
++/**
++ * get_next_timer_interrupt - return the jiffy of the next pending timer
++ * @now: current time (in jiffies)
++ */
++unsigned long get_next_timer_interrupt(unsigned long now)
++{
++ struct tvec_base *base = __get_cpu_var(tvec_bases);
++ unsigned long expires;
++
++ /*
++ * Pretend that there is no timer pending if the cpu is offline.
++ * Possible pending timers will be migrated later to an active cpu.
++ */
++ if (cpu_is_offline(smp_processor_id()))
++ return now + NEXT_TIMER_MAX_DELTA;
++ spin_lock(&base->lock);
++ if (time_before_eq(base->next_timer, base->timer_jiffies))
++ base->next_timer = __next_timer_interrupt(base);
++ expires = base->next_timer;
++ spin_unlock(&base->lock);
++
++ if (time_before_eq(expires, now))
++ return now;
++
++ return cmp_next_hrtimer_event(now, expires);
++}
++#endif
++
++/*
++ * Called from the timer interrupt handler to charge one tick to the current
++ * process. user_tick is 1 if the tick is user time, 0 for system.
++ */
++void update_process_times(int user_tick)
++{
++ struct task_struct *p = current;
++ int cpu = smp_processor_id();
++
++ /* Note: this timer irq context must be accounted for as well. */
++ account_process_tick(p, user_tick);
++ run_local_timers();
++ rcu_check_callbacks(cpu, user_tick);
++ printk_tick();
++ perf_event_do_pending();
++ scheduler_tick();
++ run_posix_cpu_timers(p);
++}
++
++/*
++ * This function runs timers and the timer-tq in bottom half context.
++ */
++static void run_timer_softirq(struct softirq_action *h)
++{
++ struct tvec_base *base = __get_cpu_var(tvec_bases);
++
++ hrtimer_run_pending();
++
++ if (time_after_eq(jiffies, base->timer_jiffies))
++ __run_timers(base);
++}
++
++/*
++ * Called by the local, per-CPU timer interrupt on SMP.
++ */
++void run_local_timers(void)
++{
++ hrtimer_run_queues();
++ raise_softirq(TIMER_SOFTIRQ);
++ softlockup_tick();
++}
++
++/*
++ * The 64-bit jiffies value is not atomic - you MUST NOT read it
++ * without sampling the sequence number in xtime_lock.
++ * jiffies is defined in the linker script...
++ */
++
++void do_timer(unsigned long ticks)
++{
++ jiffies_64 += ticks;
++ update_wall_time();
++ calc_global_load(ticks);
++}
++
++#ifdef __ARCH_WANT_SYS_ALARM
++
++/*
++ * For backwards compatibility? This can be done in libc so Alpha
++ * and all newer ports shouldn't need it.
++ */
++SYSCALL_DEFINE1(alarm, unsigned int, seconds)
++{
++ return alarm_setitimer(seconds);
++}
++
++#endif
++
++#ifndef __alpha__
++
++/*
++ * The Alpha uses getxpid, getxuid, and getxgid instead. Maybe this
++ * should be moved into arch/i386 instead?
++ */
++
++/**
++ * sys_getpid - return the thread group id of the current process
++ *
++ * Note, despite the name, this returns the tgid not the pid. The tgid and
++ * the pid are identical unless CLONE_THREAD was specified on clone() in
++ * which case the tgid is the same in all threads of the same group.
++ *
++ * This is SMP safe as current->tgid does not change.
++ */
++SYSCALL_DEFINE0(getpid)
++{
++ return task_tgid_vnr(current);
++}
++
++/*
++ * Accessing ->real_parent is not SMP-safe, it could
++ * change from under us. However, we can use a stale
++ * value of ->real_parent under rcu_read_lock(), see
++ * release_task()->call_rcu(delayed_put_task_struct).
++ */
++SYSCALL_DEFINE0(getppid)
++{
++ int pid;
++
++ rcu_read_lock();
++ pid = task_tgid_vnr(current->real_parent);
++ rcu_read_unlock();
++
++ return pid;
++}
++
++SYSCALL_DEFINE0(getuid)
++{
++ /* Only we change this so SMP safe */
++ return current_uid();
++}
++
++SYSCALL_DEFINE0(geteuid)
++{
++ /* Only we change this so SMP safe */
++ return current_euid();
++}
++
++SYSCALL_DEFINE0(getgid)
++{
++ /* Only we change this so SMP safe */
++ return current_gid();
++}
++
++SYSCALL_DEFINE0(getegid)
++{
++ /* Only we change this so SMP safe */
++ return current_egid();
++}
++
++#endif
++
++static void process_timeout(unsigned long __data)
++{
++ wake_up_process((struct task_struct *)__data);
++}
++
++/**
++ * schedule_timeout - sleep until timeout
++ * @timeout: timeout value in jiffies
++ *
++ * Make the current task sleep until @timeout jiffies have
++ * elapsed. The routine will return immediately unless
++ * the current task state has been set (see set_current_state()).
++ *
++ * You can set the task state as follows -
++ *
++ * %TASK_UNINTERRUPTIBLE - at least @timeout jiffies are guaranteed to
++ * pass before the routine returns. The routine will return 0
++ *
++ * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
++ * delivered to the current task. In this case the remaining time
++ * in jiffies will be returned, or 0 if the timer expired in time
++ *
++ * The current task state is guaranteed to be TASK_RUNNING when this
++ * routine returns.
++ *
++ * Specifying a @timeout value of %MAX_SCHEDULE_TIMEOUT will schedule
++ * the CPU away without a bound on the timeout. In this case the return
++ * value will be %MAX_SCHEDULE_TIMEOUT.
++ *
++ * In all cases the return value is guaranteed to be non-negative.
++ */
++signed long __sched schedule_timeout(signed long timeout)
++{
++ struct timer_list timer;
++ unsigned long expire;
++
++ switch (timeout)
++ {
++ case MAX_SCHEDULE_TIMEOUT:
++ /*
++ * These two special cases are useful to be comfortable
++ * in the caller. Nothing more. We could take
++ * MAX_SCHEDULE_TIMEOUT from one of the negative value
++ * but I' d like to return a valid offset (>=0) to allow
++ * the caller to do everything it want with the retval.
++ */
++ schedule();
++ goto out;
++ default:
++ /*
++ * Another bit of PARANOID. Note that the retval will be
++ * 0 since no piece of kernel is supposed to do a check
++ * for a negative retval of schedule_timeout() (since it
++ * should never happens anyway). You just have the printk()
++ * that will tell you if something is gone wrong and where.
++ */
++ if (timeout < 0) {
++ printk(KERN_ERR "schedule_timeout: wrong timeout "
++ "value %lx\n", timeout);
++ dump_stack();
++ current->state = TASK_RUNNING;
++ goto out;
++ }
++ }
++
++ expire = timeout + jiffies;
++
++ setup_timer_on_stack(&timer, process_timeout, (unsigned long)current);
++ __mod_timer(&timer, expire, false, TIMER_NOT_PINNED);
++ schedule();
++ del_singleshot_timer_sync(&timer);
++
++ /* Remove the timer from the object tracker */
++ destroy_timer_on_stack(&timer);
++
++ timeout = expire - jiffies;
++
++ out:
++ return timeout < 0 ? 0 : timeout;
++}
++EXPORT_SYMBOL(schedule_timeout);
++
++/*
++ * We can use __set_current_state() here because schedule_timeout() calls
++ * schedule() unconditionally.
++ */
++signed long __sched schedule_timeout_interruptible(signed long timeout)
++{
++ __set_current_state(TASK_INTERRUPTIBLE);
++ return schedule_timeout(timeout);
++}
++EXPORT_SYMBOL(schedule_timeout_interruptible);
++
++signed long __sched schedule_timeout_killable(signed long timeout)
++{
++ __set_current_state(TASK_KILLABLE);
++ return schedule_timeout(timeout);
++}
++EXPORT_SYMBOL(schedule_timeout_killable);
++
++signed long __sched schedule_timeout_uninterruptible(signed long timeout)
++{
++ __set_current_state(TASK_UNINTERRUPTIBLE);
++ return schedule_timeout(timeout);
++}
++EXPORT_SYMBOL(schedule_timeout_uninterruptible);
++
++/* Thread ID - the internal kernel "pid" */
++SYSCALL_DEFINE0(gettid)
++{
++ return task_pid_vnr(current);
++}
++
++/**
++ * do_sysinfo - fill in sysinfo struct
++ * @info: pointer to buffer to fill
++ */
++int do_sysinfo(struct sysinfo *info)
++{
++ unsigned long mem_total, sav_total;
++ unsigned int mem_unit, bitcount;
++ struct timespec tp;
++
++ memset(info, 0, sizeof(struct sysinfo));
++
++ ktime_get_ts(&tp);
++ monotonic_to_bootbased(&tp);
++ info->uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0);
++
++ get_avenrun(info->loads, 0, SI_LOAD_SHIFT - FSHIFT);
++
++ info->procs = nr_threads;
++
++ si_meminfo(info);
++ si_swapinfo(info);
++
++ /*
++ * If the sum of all the available memory (i.e. ram + swap)
++ * is less than can be stored in a 32 bit unsigned long then
++ * we can be binary compatible with 2.2.x kernels. If not,
++ * well, in that case 2.2.x was broken anyways...
++ *
++ * -Erik Andersen <andersee at debian.org>
++ */
++
++ mem_total = info->totalram + info->totalswap;
++ if (mem_total < info->totalram || mem_total < info->totalswap)
++ goto out;
++ bitcount = 0;
++ mem_unit = info->mem_unit;
++ while (mem_unit > 1) {
++ bitcount++;
++ mem_unit >>= 1;
++ sav_total = mem_total;
++ mem_total <<= 1;
++ if (mem_total < sav_total)
++ goto out;
++ }
++
++ /*
++ * If mem_total did not overflow, multiply all memory values by
++ * info->mem_unit and set it to 1. This leaves things compatible
++ * with 2.2.x, and also retains compatibility with earlier 2.4.x
++ * kernels...
++ */
++
++ info->mem_unit = 1;
++ info->totalram <<= bitcount;
++ info->freeram <<= bitcount;
++ info->sharedram <<= bitcount;
++ info->bufferram <<= bitcount;
++ info->totalswap <<= bitcount;
++ info->freeswap <<= bitcount;
++ info->totalhigh <<= bitcount;
++ info->freehigh <<= bitcount;
++
++out:
++ return 0;
++}
++
++SYSCALL_DEFINE1(sysinfo, struct sysinfo __user *, info)
++{
++ struct sysinfo val;
++
++ do_sysinfo(&val);
++
++ if (copy_to_user(info, &val, sizeof(struct sysinfo)))
++ return -EFAULT;
++
++ return 0;
++}
++
++static int __cpuinit init_timers_cpu(int cpu)
++{
++ int j;
++ struct tvec_base *base;
++ static char __cpuinitdata tvec_base_done[NR_CPUS];
++
++ if (!tvec_base_done[cpu]) {
++ static char boot_done;
++
++ if (boot_done) {
++ /*
++ * The APs use this path later in boot
++ */
++ base = kmalloc_node(sizeof(*base),
++ GFP_KERNEL | __GFP_ZERO,
++ cpu_to_node(cpu));
++ if (!base)
++ return -ENOMEM;
++
++ /* Make sure that tvec_base is 2 byte aligned */
++ if (tbase_get_deferrable(base)) {
++ WARN_ON(1);
++ kfree(base);
++ return -ENOMEM;
++ }
++ per_cpu(tvec_bases, cpu) = base;
++ } else {
++ /*
++ * This is for the boot CPU - we use compile-time
++ * static initialisation because per-cpu memory isn't
++ * ready yet and because the memory allocators are not
++ * initialised either.
++ */
++ boot_done = 1;
++ base = &boot_tvec_bases;
++ }
++ tvec_base_done[cpu] = 1;
++ } else {
++ base = per_cpu(tvec_bases, cpu);
++ }
++
++ spin_lock_init(&base->lock);
++
++ for (j = 0; j < TVN_SIZE; j++) {
++ INIT_LIST_HEAD(base->tv5.vec + j);
++ INIT_LIST_HEAD(base->tv4.vec + j);
++ INIT_LIST_HEAD(base->tv3.vec + j);
++ INIT_LIST_HEAD(base->tv2.vec + j);
++ }
++ for (j = 0; j < TVR_SIZE; j++)
++ INIT_LIST_HEAD(base->tv1.vec + j);
++
++ base->timer_jiffies = jiffies;
++ base->next_timer = base->timer_jiffies;
++ return 0;
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++static void migrate_timer_list(struct tvec_base *new_base, struct list_head *head)
++{
++ struct timer_list *timer;
++
++ while (!list_empty(head)) {
++ timer = list_first_entry(head, struct timer_list, entry);
++ detach_timer(timer, 0);
++ timer_set_base(timer, new_base);
++ if (time_before(timer->expires, new_base->next_timer) &&
++ !tbase_get_deferrable(timer->base))
++ new_base->next_timer = timer->expires;
++ internal_add_timer(new_base, timer);
++ }
++}
++
++static void __cpuinit migrate_timers(int cpu)
++{
++ struct tvec_base *old_base;
++ struct tvec_base *new_base;
++ int i;
++
++ BUG_ON(cpu_online(cpu));
++ old_base = per_cpu(tvec_bases, cpu);
++ new_base = get_cpu_var(tvec_bases);
++ /*
++ * The caller is globally serialized and nobody else
++ * takes two locks at once, deadlock is not possible.
++ */
++ spin_lock_irq(&new_base->lock);
++ spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
++
++ BUG_ON(old_base->running_timer);
++
++ for (i = 0; i < TVR_SIZE; i++)
++ migrate_timer_list(new_base, old_base->tv1.vec + i);
++ for (i = 0; i < TVN_SIZE; i++) {
++ migrate_timer_list(new_base, old_base->tv2.vec + i);
++ migrate_timer_list(new_base, old_base->tv3.vec + i);
++ migrate_timer_list(new_base, old_base->tv4.vec + i);
++ migrate_timer_list(new_base, old_base->tv5.vec + i);
++ }
++
++ spin_unlock(&old_base->lock);
++ spin_unlock_irq(&new_base->lock);
++ put_cpu_var(tvec_bases);
++}
++#endif /* CONFIG_HOTPLUG_CPU */
++
++static int __cpuinit timer_cpu_notify(struct notifier_block *self,
++ unsigned long action, void *hcpu)
++{
++ long cpu = (long)hcpu;
++ int err;
++
++ switch(action) {
++ case CPU_UP_PREPARE:
++ case CPU_UP_PREPARE_FROZEN:
++ err = init_timers_cpu(cpu);
++ if (err < 0)
++ return notifier_from_errno(err);
++ break;
++#ifdef CONFIG_HOTPLUG_CPU
++ case CPU_DEAD:
++ case CPU_DEAD_FROZEN:
++ migrate_timers(cpu);
++ break;
++#endif
++ default:
++ break;
++ }
++ return NOTIFY_OK;
++}
++
++static struct notifier_block __cpuinitdata timers_nb = {
++ .notifier_call = timer_cpu_notify,
++};
++
++
++void __init init_timers(void)
++{
++ int err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
++ (void *)(long)smp_processor_id());
++
++ init_timer_stats();
++
++ BUG_ON(err != NOTIFY_OK);
++ register_cpu_notifier(&timers_nb);
++ open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
++}
++
++/**
++ * msleep - sleep safely even with waitqueue interruptions
++ * @msecs: Time in milliseconds to sleep for
++ */
++void msleep(unsigned int msecs)
++{
++ unsigned long timeout = msecs_to_jiffies(msecs) + 1;
++
++ while (timeout)
++ timeout = schedule_timeout_uninterruptible(timeout);
++}
++
++EXPORT_SYMBOL(msleep);
++
++/**
++ * msleep_interruptible - sleep waiting for signals
++ * @msecs: Time in milliseconds to sleep for
++ */
++unsigned long msleep_interruptible(unsigned int msecs)
++{
++ unsigned long timeout = msecs_to_jiffies(msecs) + 1;
++
++ while (timeout && !signal_pending(current))
++ timeout = schedule_timeout_interruptible(timeout);
++ return jiffies_to_msecs(timeout);
++}
++
++EXPORT_SYMBOL(msleep_interruptible);
+diff -rupN linux-2.6.35.11/lib/decompress_inflate.c linux-2.6.35.11-ts7500/lib/decompress_inflate.c
+--- linux-2.6.35.11/lib/decompress_inflate.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/lib/decompress_inflate.c 2011-03-14 11:18:24.000000000 -0400
+@@ -25,6 +25,8 @@
+
+ #include <linux/decompress/mm.h>
+
++
++
+ #define GZIP_IOBUF_SIZE (16*1024)
+
+ static int nofill(void *buffer, unsigned int len)
+@@ -32,6 +34,7 @@ static int nofill(void *buffer, unsigned
+ return -1;
+ }
+
++
+ /* Included from initramfs et al code */
+ STATIC int INIT gunzip(unsigned char *buf, int len,
+ int(*fill)(void*, unsigned int),
+@@ -39,6 +42,7 @@ STATIC int INIT gunzip(unsigned char *bu
+ unsigned char *out_buf,
+ int *pos,
+ void(*error_fn)(char *x)) {
++
+ u8 *zbuf;
+ struct z_stream_s *strm;
+ int rc;
+@@ -51,6 +55,7 @@ STATIC int INIT gunzip(unsigned char *bu
+ out_buf = malloc(out_len);
+ } else {
+ out_len = 0x7fffffff; /* no limit */
++
+ }
+ if (!out_buf) {
+ error("Out of memory while allocating output buffer");
+@@ -69,6 +74,7 @@ STATIC int INIT gunzip(unsigned char *bu
+ }
+
+ strm = malloc(sizeof(*strm));
++
+ if (strm == NULL) {
+ error("Out of memory while allocating z_stream");
+ goto gunzip_nomem3;
+@@ -143,7 +149,7 @@ STATIC int INIT gunzip(unsigned char *bu
+ strm->next_out = out_buf;
+ strm->avail_out = out_len;
+ }
+-
++
+ /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
+ if (rc == Z_STREAM_END) {
+ rc = 0;
+@@ -169,7 +175,7 @@ gunzip_nomem3:
+ gunzip_nomem2:
+ if (flush)
+ free(out_buf);
+-gunzip_nomem1:
++gunzip_nomem1:
+ return rc; /* returns Z_OK (0) if successful */
+ }
+
+diff -rupN linux-2.6.35.11/lib/inflate.c linux-2.6.35.11-ts7500/lib/inflate.c
+--- linux-2.6.35.11/lib/inflate.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/lib/inflate.c 2011-03-14 11:18:24.000000000 -0400
+@@ -243,6 +243,7 @@ static void *malloc(int size)
+ {
+ void *p;
+
++
+ if (size < 0)
+ error("Malloc error");
+ if (!malloc_ptr)
+@@ -268,6 +269,7 @@ static void free(void *where)
+ }
+ #else
+ #define malloc(a) kmalloc(a, GFP_KERNEL)
++
+ #define free(a) kfree(a)
+ #endif
+
+diff -rupN linux-2.6.35.11/lib/inflate.c.orig linux-2.6.35.11-ts7500/lib/inflate.c.orig
+--- linux-2.6.35.11/lib/inflate.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/lib/inflate.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,1307 @@
++#define DEBG(x)
++#define DEBG1(x)
++/* inflate.c -- Not copyrighted 1992 by Mark Adler
++ version c10p1, 10 January 1993 */
++
++/*
++ * Adapted for booting Linux by Hannu Savolainen 1993
++ * based on gzip-1.0.3
++ *
++ * Nicolas Pitre <nico at fluxnic.net>, 1999/04/14 :
++ * Little mods for all variable to reside either into rodata or bss segments
++ * by marking constant variables with 'const' and initializing all the others
++ * at run-time only. This allows for the kernel uncompressor to run
++ * directly from Flash or ROM memory on embedded systems.
++ */
++
++/*
++ Inflate deflated (PKZIP's method 8 compressed) data. The compression
++ method searches for as much of the current string of bytes (up to a
++ length of 258) in the previous 32 K bytes. If it doesn't find any
++ matches (of at least length 3), it codes the next byte. Otherwise, it
++ codes the length of the matched string and its distance backwards from
++ the current position. There is a single Huffman code that codes both
++ single bytes (called "literals") and match lengths. A second Huffman
++ code codes the distance information, which follows a length code. Each
++ length or distance code actually represents a base value and a number
++ of "extra" (sometimes zero) bits to get to add to the base value. At
++ the end of each deflated block is a special end-of-block (EOB) literal/
++ length code. The decoding process is basically: get a literal/length
++ code; if EOB then done; if a literal, emit the decoded byte; if a
++ length then get the distance and emit the referred-to bytes from the
++ sliding window of previously emitted data.
++
++ There are (currently) three kinds of inflate blocks: stored, fixed, and
++ dynamic. The compressor deals with some chunk of data at a time, and
++ decides which method to use on a chunk-by-chunk basis. A chunk might
++ typically be 32 K or 64 K. If the chunk is incompressible, then the
++ "stored" method is used. In this case, the bytes are simply stored as
++ is, eight bits per byte, with none of the above coding. The bytes are
++ preceded by a count, since there is no longer an EOB code.
++
++ If the data is compressible, then either the fixed or dynamic methods
++ are used. In the dynamic method, the compressed data is preceded by
++ an encoding of the literal/length and distance Huffman codes that are
++ to be used to decode this block. The representation is itself Huffman
++ coded, and so is preceded by a description of that code. These code
++ descriptions take up a little space, and so for small blocks, there is
++ a predefined set of codes, called the fixed codes. The fixed method is
++ used if the block codes up smaller that way (usually for quite small
++ chunks), otherwise the dynamic method is used. In the latter case, the
++ codes are customized to the probabilities in the current block, and so
++ can code it much better than the pre-determined fixed codes.
++
++ The Huffman codes themselves are decoded using a multi-level table
++ lookup, in order to maximize the speed of decoding plus the speed of
++ building the decoding tables. See the comments below that precede the
++ lbits and dbits tuning parameters.
++ */
++
++
++/*
++ Notes beyond the 1.93a appnote.txt:
++
++ 1. Distance pointers never point before the beginning of the output
++ stream.
++ 2. Distance pointers can point back across blocks, up to 32k away.
++ 3. There is an implied maximum of 7 bits for the bit length table and
++ 15 bits for the actual data.
++ 4. If only one code exists, then it is encoded using one bit. (Zero
++ would be more efficient, but perhaps a little confusing.) If two
++ codes exist, they are coded using one bit each (0 and 1).
++ 5. There is no way of sending zero distance codes--a dummy must be
++ sent if there are none. (History: a pre 2.0 version of PKZIP would
++ store blocks with no distance codes, but this was discovered to be
++ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
++ zero distance codes, which is sent as one code of zero bits in
++ length.
++ 6. There are up to 286 literal/length codes. Code 256 represents the
++ end-of-block. Note however that the static length tree defines
++ 288 codes just to fill out the Huffman codes. Codes 286 and 287
++ cannot be used though, since there is no length base or extra bits
++ defined for them. Similarly, there are up to 30 distance codes.
++ However, static trees define 32 codes (all 5 bits) to fill out the
++ Huffman codes, but the last two had better not show up in the data.
++ 7. Unzip can check dynamic Huffman blocks for complete code sets.
++ The exception is that a single code would not be complete (see #4).
++ 8. The five bits following the block type is really the number of
++ literal codes sent minus 257.
++ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
++ (1+6+6). Therefore, to output three times the length, you output
++ three codes (1+1+1), whereas to output four times the same length,
++ you only need two codes (1+3). Hmm.
++ 10. In the tree reconstruction algorithm, Code = Code + Increment
++ only if BitLength(i) is not zero. (Pretty obvious.)
++ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
++ 12. Note: length code 284 can represent 227-258, but length code 285
++ really is 258. The last length deserves its own, short code
++ since it gets used a lot in very redundant files. The length
++ 258 is special since 258 - 3 (the min match length) is 255.
++ 13. The literal/length and distance code bit lengths are read as a
++ single stream of lengths. It is possible (and advantageous) for
++ a repeat code (16, 17, or 18) to go across the boundary between
++ the two sets of lengths.
++ */
++#include <linux/compiler.h>
++#include <linux/slab.h>
++
++#ifdef RCSID
++static char rcsid[] = "#Id: inflate.c,v 0.14 1993/06/10 13:27:04 jloup Exp #";
++#endif
++
++#ifndef STATIC
++
++#if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H)
++# include <sys/types.h>
++# include <stdlib.h>
++#endif
++
++#include "gzip.h"
++#define STATIC
++#endif /* !STATIC */
++
++#ifndef INIT
++#define INIT
++#endif
++
++#define slide window
++
++/* Huffman code lookup table entry--this entry is four bytes for machines
++ that have 16-bit pointers (e.g. PC's in the small or medium model).
++ Valid extra bits are 0..13. e == 15 is EOB (end of block), e == 16
++ means that v is a literal, 16 < e < 32 means that v is a pointer to
++ the next table, which codes e - 16 bits, and lastly e == 99 indicates
++ an unused code. If a code with e == 99 is looked up, this implies an
++ error in the data. */
++struct huft {
++ uch e; /* number of extra bits or operation */
++ uch b; /* number of bits in this code or subcode */
++ union {
++ ush n; /* literal, length base, or distance base */
++ struct huft *t; /* pointer to next level of table */
++ } v;
++};
++
++
++/* Function prototypes */
++STATIC int INIT huft_build OF((unsigned *, unsigned, unsigned,
++ const ush *, const ush *, struct huft **, int *));
++STATIC int INIT huft_free OF((struct huft *));
++STATIC int INIT inflate_codes OF((struct huft *, struct huft *, int, int));
++STATIC int INIT inflate_stored OF((void));
++STATIC int INIT inflate_fixed OF((void));
++STATIC int INIT inflate_dynamic OF((void));
++STATIC int INIT inflate_block OF((int *));
++STATIC int INIT inflate OF((void));
++
++
++/* The inflate algorithm uses a sliding 32 K byte window on the uncompressed
++ stream to find repeated byte strings. This is implemented here as a
++ circular buffer. The index is updated simply by incrementing and then
++ ANDing with 0x7fff (32K-1). */
++/* It is left to other modules to supply the 32 K area. It is assumed
++ to be usable as if it were declared "uch slide[32768];" or as just
++ "uch *slide;" and then malloc'ed in the latter case. The definition
++ must be in unzip.h, included above. */
++/* unsigned wp; current position in slide */
++#define wp outcnt
++#define flush_output(w) (wp=(w),flush_window())
++
++/* Tables for deflate from PKZIP's appnote.txt. */
++static const unsigned border[] = { /* Order of the bit length code lengths */
++ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
++static const ush cplens[] = { /* Copy lengths for literal codes 257..285 */
++ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
++ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
++ /* note: see note #13 above about the 258 in this list. */
++static const ush cplext[] = { /* Extra bits for literal codes 257..285 */
++ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
++ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */
++static const ush cpdist[] = { /* Copy offsets for distance codes 0..29 */
++ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
++ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
++ 8193, 12289, 16385, 24577};
++static const ush cpdext[] = { /* Extra bits for distance codes */
++ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
++ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
++ 12, 12, 13, 13};
++
++
++
++/* Macros for inflate() bit peeking and grabbing.
++ The usage is:
++
++ NEEDBITS(j)
++ x = b & mask_bits[j];
++ DUMPBITS(j)
++
++ where NEEDBITS makes sure that b has at least j bits in it, and
++ DUMPBITS removes the bits from b. The macros use the variable k
++ for the number of bits in b. Normally, b and k are register
++ variables for speed, and are initialized at the beginning of a
++ routine that uses these macros from a global bit buffer and count.
++
++ If we assume that EOB will be the longest code, then we will never
++ ask for bits with NEEDBITS that are beyond the end of the stream.
++ So, NEEDBITS should not read any more bytes than are needed to
++ meet the request. Then no bytes need to be "returned" to the buffer
++ at the end of the last block.
++
++ However, this assumption is not true for fixed blocks--the EOB code
++ is 7 bits, but the other literal/length codes can be 8 or 9 bits.
++ (The EOB code is shorter than other codes because fixed blocks are
++ generally short. So, while a block always has an EOB, many other
++ literal/length codes have a significantly lower probability of
++ showing up at all.) However, by making the first table have a
++ lookup of seven bits, the EOB code will be found in that first
++ lookup, and so will not require that too many bits be pulled from
++ the stream.
++ */
++
++STATIC ulg bb; /* bit buffer */
++STATIC unsigned bk; /* bits in bit buffer */
++
++STATIC const ush mask_bits[] = {
++ 0x0000,
++ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
++ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
++};
++
++#define NEXTBYTE() ({ int v = get_byte(); if (v < 0) goto underrun; (uch)v; })
++#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
++#define DUMPBITS(n) {b>>=(n);k-=(n);}
++
++#ifndef NO_INFLATE_MALLOC
++/* A trivial malloc implementation, adapted from
++ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
++ */
++
++static unsigned long malloc_ptr;
++static int malloc_count;
++
++static void *malloc(int size)
++{
++ void *p;
++
++ if (size < 0)
++ error("Malloc error");
++ if (!malloc_ptr)
++ malloc_ptr = free_mem_ptr;
++
++ malloc_ptr = (malloc_ptr + 3) & ~3; /* Align */
++
++ p = (void *)malloc_ptr;
++ malloc_ptr += size;
++
++ if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr)
++ error("Out of memory");
++
++ malloc_count++;
++ return p;
++}
++
++static void free(void *where)
++{
++ malloc_count--;
++ if (!malloc_count)
++ malloc_ptr = free_mem_ptr;
++}
++#else
++#define malloc(a) kmalloc(a, GFP_KERNEL)
++#define free(a) kfree(a)
++#endif
++
++/*
++ Huffman code decoding is performed using a multi-level table lookup.
++ The fastest way to decode is to simply build a lookup table whose
++ size is determined by the longest code. However, the time it takes
++ to build this table can also be a factor if the data being decoded
++ is not very long. The most common codes are necessarily the
++ shortest codes, so those codes dominate the decoding time, and hence
++ the speed. The idea is you can have a shorter table that decodes the
++ shorter, more probable codes, and then point to subsidiary tables for
++ the longer codes. The time it costs to decode the longer codes is
++ then traded against the time it takes to make longer tables.
++
++ This results of this trade are in the variables lbits and dbits
++ below. lbits is the number of bits the first level table for literal/
++ length codes can decode in one step, and dbits is the same thing for
++ the distance codes. Subsequent tables are also less than or equal to
++ those sizes. These values may be adjusted either when all of the
++ codes are shorter than that, in which case the longest code length in
++ bits is used, or when the shortest code is *longer* than the requested
++ table size, in which case the length of the shortest code in bits is
++ used.
++
++ There are two different values for the two tables, since they code a
++ different number of possibilities each. The literal/length table
++ codes 286 possible values, or in a flat code, a little over eight
++ bits. The distance table codes 30 possible values, or a little less
++ than five bits, flat. The optimum values for speed end up being
++ about one bit more than those, so lbits is 8+1 and dbits is 5+1.
++ The optimum values may differ though from machine to machine, and
++ possibly even between compilers. Your mileage may vary.
++ */
++
++
++STATIC const int lbits = 9; /* bits in base literal/length lookup table */
++STATIC const int dbits = 6; /* bits in base distance lookup table */
++
++
++/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
++#define BMAX 16 /* maximum bit length of any code (16 for explode) */
++#define N_MAX 288 /* maximum number of codes in any set */
++
++
++STATIC unsigned hufts; /* track memory usage */
++
++
++STATIC int INIT huft_build(
++ unsigned *b, /* code lengths in bits (all assumed <= BMAX) */
++ unsigned n, /* number of codes (assumed <= N_MAX) */
++ unsigned s, /* number of simple-valued codes (0..s-1) */
++ const ush *d, /* list of base values for non-simple codes */
++ const ush *e, /* list of extra bits for non-simple codes */
++ struct huft **t, /* result: starting table */
++ int *m /* maximum lookup bits, returns actual */
++ )
++/* Given a list of code lengths and a maximum table size, make a set of
++ tables to decode that set of codes. Return zero on success, one if
++ the given code set is incomplete (the tables are still built in this
++ case), two if the input is invalid (all zero length codes or an
++ oversubscribed set of lengths), and three if not enough memory. */
++{
++ unsigned a; /* counter for codes of length k */
++ unsigned f; /* i repeats in table every f entries */
++ int g; /* maximum code length */
++ int h; /* table level */
++ register unsigned i; /* counter, current code */
++ register unsigned j; /* counter */
++ register int k; /* number of bits in current code */
++ int l; /* bits per table (returned in m) */
++ register unsigned *p; /* pointer into c[], b[], or v[] */
++ register struct huft *q; /* points to current table */
++ struct huft r; /* table entry for structure assignment */
++ register int w; /* bits before this table == (l * h) */
++ unsigned *xp; /* pointer into x */
++ int y; /* number of dummy codes added */
++ unsigned z; /* number of entries in current table */
++ struct {
++ unsigned c[BMAX+1]; /* bit length count table */
++ struct huft *u[BMAX]; /* table stack */
++ unsigned v[N_MAX]; /* values in order of bit length */
++ unsigned x[BMAX+1]; /* bit offsets, then code stack */
++ } *stk;
++ unsigned *c, *v, *x;
++ struct huft **u;
++ int ret;
++
++DEBG("huft1 ");
++
++ stk = malloc(sizeof(*stk));
++ if (stk == NULL)
++ return 3; /* out of memory */
++
++ c = stk->c;
++ v = stk->v;
++ x = stk->x;
++ u = stk->u;
++
++ /* Generate counts for each bit length */
++ memzero(stk->c, sizeof(stk->c));
++ p = b; i = n;
++ do {
++ Tracecv(*p, (stderr, (n-i >= ' ' && n-i <= '~' ? "%c %d\n" : "0x%x %d\n"),
++ n-i, *p));
++ c[*p]++; /* assume all entries <= BMAX */
++ p++; /* Can't combine with above line (Solaris bug) */
++ } while (--i);
++ if (c[0] == n) /* null input--all zero length codes */
++ {
++ *t = (struct huft *)NULL;
++ *m = 0;
++ ret = 2;
++ goto out;
++ }
++
++DEBG("huft2 ");
++
++ /* Find minimum and maximum length, bound *m by those */
++ l = *m;
++ for (j = 1; j <= BMAX; j++)
++ if (c[j])
++ break;
++ k = j; /* minimum code length */
++ if ((unsigned)l < j)
++ l = j;
++ for (i = BMAX; i; i--)
++ if (c[i])
++ break;
++ g = i; /* maximum code length */
++ if ((unsigned)l > i)
++ l = i;
++ *m = l;
++
++DEBG("huft3 ");
++
++ /* Adjust last length count to fill out codes, if needed */
++ for (y = 1 << j; j < i; j++, y <<= 1)
++ if ((y -= c[j]) < 0) {
++ ret = 2; /* bad input: more codes than bits */
++ goto out;
++ }
++ if ((y -= c[i]) < 0) {
++ ret = 2;
++ goto out;
++ }
++ c[i] += y;
++
++DEBG("huft4 ");
++
++ /* Generate starting offsets into the value table for each length */
++ x[1] = j = 0;
++ p = c + 1; xp = x + 2;
++ while (--i) { /* note that i == g from above */
++ *xp++ = (j += *p++);
++ }
++
++DEBG("huft5 ");
++
++ /* Make a table of values in order of bit lengths */
++ p = b; i = 0;
++ do {
++ if ((j = *p++) != 0)
++ v[x[j]++] = i;
++ } while (++i < n);
++ n = x[g]; /* set n to length of v */
++
++DEBG("h6 ");
++
++ /* Generate the Huffman codes and for each, make the table entries */
++ x[0] = i = 0; /* first Huffman code is zero */
++ p = v; /* grab values in bit order */
++ h = -1; /* no tables yet--level -1 */
++ w = -l; /* bits decoded == (l * h) */
++ u[0] = (struct huft *)NULL; /* just to keep compilers happy */
++ q = (struct huft *)NULL; /* ditto */
++ z = 0; /* ditto */
++DEBG("h6a ");
++
++ /* go through the bit lengths (k already is bits in shortest code) */
++ for (; k <= g; k++)
++ {
++DEBG("h6b ");
++ a = c[k];
++ while (a--)
++ {
++DEBG("h6b1 ");
++ /* here i is the Huffman code of length k bits for value *p */
++ /* make tables up to required level */
++ while (k > w + l)
++ {
++DEBG1("1 ");
++ h++;
++ w += l; /* previous table always l bits */
++
++ /* compute minimum size table less than or equal to l bits */
++ z = (z = g - w) > (unsigned)l ? l : z; /* upper limit on table size */
++ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
++ { /* too few codes for k-w bit table */
++DEBG1("2 ");
++ f -= a + 1; /* deduct codes from patterns left */
++ xp = c + k;
++ if (j < z)
++ while (++j < z) /* try smaller tables up to z bits */
++ {
++ if ((f <<= 1) <= *++xp)
++ break; /* enough codes to use up j bits */
++ f -= *xp; /* else deduct codes from patterns */
++ }
++ }
++DEBG1("3 ");
++ z = 1 << j; /* table entries for j-bit table */
++
++ /* allocate and link in new table */
++ if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
++ (struct huft *)NULL)
++ {
++ if (h)
++ huft_free(u[0]);
++ ret = 3; /* not enough memory */
++ goto out;
++ }
++DEBG1("4 ");
++ hufts += z + 1; /* track memory usage */
++ *t = q + 1; /* link to list for huft_free() */
++ *(t = &(q->v.t)) = (struct huft *)NULL;
++ u[h] = ++q; /* table starts after link */
++
++DEBG1("5 ");
++ /* connect to last table, if there is one */
++ if (h)
++ {
++ x[h] = i; /* save pattern for backing up */
++ r.b = (uch)l; /* bits to dump before this table */
++ r.e = (uch)(16 + j); /* bits in this table */
++ r.v.t = q; /* pointer to this table */
++ j = i >> (w - l); /* (get around Turbo C bug) */
++ u[h-1][j] = r; /* connect to last table */
++ }
++DEBG1("6 ");
++ }
++DEBG("h6c ");
++
++ /* set up table entry in r */
++ r.b = (uch)(k - w);
++ if (p >= v + n)
++ r.e = 99; /* out of values--invalid code */
++ else if (*p < s)
++ {
++ r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
++ r.v.n = (ush)(*p); /* simple code is just the value */
++ p++; /* one compiler does not like *p++ */
++ }
++ else
++ {
++ r.e = (uch)e[*p - s]; /* non-simple--look up in lists */
++ r.v.n = d[*p++ - s];
++ }
++DEBG("h6d ");
++
++ /* fill code-like entries with r */
++ f = 1 << (k - w);
++ for (j = i >> w; j < z; j += f)
++ q[j] = r;
++
++ /* backwards increment the k-bit code i */
++ for (j = 1 << (k - 1); i & j; j >>= 1)
++ i ^= j;
++ i ^= j;
++
++ /* backup over finished tables */
++ while ((i & ((1 << w) - 1)) != x[h])
++ {
++ h--; /* don't need to update q */
++ w -= l;
++ }
++DEBG("h6e ");
++ }
++DEBG("h6f ");
++ }
++
++DEBG("huft7 ");
++
++ /* Return true (1) if we were given an incomplete table */
++ ret = y != 0 && g != 1;
++
++ out:
++ free(stk);
++ return ret;
++}
++
++
++
++STATIC int INIT huft_free(
++ struct huft *t /* table to free */
++ )
++/* Free the malloc'ed tables built by huft_build(), which makes a linked
++ list of the tables it made, with the links in a dummy first entry of
++ each table. */
++{
++ register struct huft *p, *q;
++
++
++ /* Go through linked list, freeing from the malloced (t[-1]) address. */
++ p = t;
++ while (p != (struct huft *)NULL)
++ {
++ q = (--p)->v.t;
++ free((char*)p);
++ p = q;
++ }
++ return 0;
++}
++
++
++STATIC int INIT inflate_codes(
++ struct huft *tl, /* literal/length decoder tables */
++ struct huft *td, /* distance decoder tables */
++ int bl, /* number of bits decoded by tl[] */
++ int bd /* number of bits decoded by td[] */
++ )
++/* inflate (decompress) the codes in a deflated (compressed) block.
++ Return an error code or zero if it all goes ok. */
++{
++ register unsigned e; /* table entry flag/number of extra bits */
++ unsigned n, d; /* length and index for copy */
++ unsigned w; /* current window position */
++ struct huft *t; /* pointer to table entry */
++ unsigned ml, md; /* masks for bl and bd bits */
++ register ulg b; /* bit buffer */
++ register unsigned k; /* number of bits in bit buffer */
++
++
++ /* make local copies of globals */
++ b = bb; /* initialize bit buffer */
++ k = bk;
++ w = wp; /* initialize window position */
++
++ /* inflate the coded data */
++ ml = mask_bits[bl]; /* precompute masks for speed */
++ md = mask_bits[bd];
++ for (;;) /* do until end of block */
++ {
++ NEEDBITS((unsigned)bl)
++ if ((e = (t = tl + ((unsigned)b & ml))->e) > 16)
++ do {
++ if (e == 99)
++ return 1;
++ DUMPBITS(t->b)
++ e -= 16;
++ NEEDBITS(e)
++ } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
++ DUMPBITS(t->b)
++ if (e == 16) /* then it's a literal */
++ {
++ slide[w++] = (uch)t->v.n;
++ Tracevv((stderr, "%c", slide[w-1]));
++ if (w == WSIZE)
++ {
++ flush_output(w);
++ w = 0;
++ }
++ }
++ else /* it's an EOB or a length */
++ {
++ /* exit if end of block */
++ if (e == 15)
++ break;
++
++ /* get length of block to copy */
++ NEEDBITS(e)
++ n = t->v.n + ((unsigned)b & mask_bits[e]);
++ DUMPBITS(e);
++
++ /* decode distance of block to copy */
++ NEEDBITS((unsigned)bd)
++ if ((e = (t = td + ((unsigned)b & md))->e) > 16)
++ do {
++ if (e == 99)
++ return 1;
++ DUMPBITS(t->b)
++ e -= 16;
++ NEEDBITS(e)
++ } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
++ DUMPBITS(t->b)
++ NEEDBITS(e)
++ d = w - t->v.n - ((unsigned)b & mask_bits[e]);
++ DUMPBITS(e)
++ Tracevv((stderr,"\\[%d,%d]", w-d, n));
++
++ /* do the copy */
++ do {
++ n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
++#if !defined(NOMEMCPY) && !defined(DEBUG)
++ if (w - d >= e) /* (this test assumes unsigned comparison) */
++ {
++ memcpy(slide + w, slide + d, e);
++ w += e;
++ d += e;
++ }
++ else /* do it slow to avoid memcpy() overlap */
++#endif /* !NOMEMCPY */
++ do {
++ slide[w++] = slide[d++];
++ Tracevv((stderr, "%c", slide[w-1]));
++ } while (--e);
++ if (w == WSIZE)
++ {
++ flush_output(w);
++ w = 0;
++ }
++ } while (n);
++ }
++ }
++
++
++ /* restore the globals from the locals */
++ wp = w; /* restore global window pointer */
++ bb = b; /* restore global bit buffer */
++ bk = k;
++
++ /* done */
++ return 0;
++
++ underrun:
++ return 4; /* Input underrun */
++}
++
++
++
++STATIC int INIT inflate_stored(void)
++/* "decompress" an inflated type 0 (stored) block. */
++{
++ unsigned n; /* number of bytes in block */
++ unsigned w; /* current window position */
++ register ulg b; /* bit buffer */
++ register unsigned k; /* number of bits in bit buffer */
++
++DEBG("<stor");
++
++ /* make local copies of globals */
++ b = bb; /* initialize bit buffer */
++ k = bk;
++ w = wp; /* initialize window position */
++
++
++ /* go to byte boundary */
++ n = k & 7;
++ DUMPBITS(n);
++
++
++ /* get the length and its complement */
++ NEEDBITS(16)
++ n = ((unsigned)b & 0xffff);
++ DUMPBITS(16)
++ NEEDBITS(16)
++ if (n != (unsigned)((~b) & 0xffff))
++ return 1; /* error in compressed data */
++ DUMPBITS(16)
++
++
++ /* read and output the compressed data */
++ while (n--)
++ {
++ NEEDBITS(8)
++ slide[w++] = (uch)b;
++ if (w == WSIZE)
++ {
++ flush_output(w);
++ w = 0;
++ }
++ DUMPBITS(8)
++ }
++
++
++ /* restore the globals from the locals */
++ wp = w; /* restore global window pointer */
++ bb = b; /* restore global bit buffer */
++ bk = k;
++
++ DEBG(">");
++ return 0;
++
++ underrun:
++ return 4; /* Input underrun */
++}
++
++
++/*
++ * We use `noinline' here to prevent gcc-3.5 from using too much stack space
++ */
++STATIC int noinline INIT inflate_fixed(void)
++/* decompress an inflated type 1 (fixed Huffman codes) block. We should
++ either replace this with a custom decoder, or at least precompute the
++ Huffman tables. */
++{
++ int i; /* temporary variable */
++ struct huft *tl; /* literal/length code table */
++ struct huft *td; /* distance code table */
++ int bl; /* lookup bits for tl */
++ int bd; /* lookup bits for td */
++ unsigned *l; /* length list for huft_build */
++
++DEBG("<fix");
++
++ l = malloc(sizeof(*l) * 288);
++ if (l == NULL)
++ return 3; /* out of memory */
++
++ /* set up literal table */
++ for (i = 0; i < 144; i++)
++ l[i] = 8;
++ for (; i < 256; i++)
++ l[i] = 9;
++ for (; i < 280; i++)
++ l[i] = 7;
++ for (; i < 288; i++) /* make a complete, but wrong code set */
++ l[i] = 8;
++ bl = 7;
++ if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0) {
++ free(l);
++ return i;
++ }
++
++ /* set up distance table */
++ for (i = 0; i < 30; i++) /* make an incomplete code set */
++ l[i] = 5;
++ bd = 5;
++ if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1)
++ {
++ huft_free(tl);
++ free(l);
++
++ DEBG(">");
++ return i;
++ }
++
++
++ /* decompress until an end-of-block code */
++ if (inflate_codes(tl, td, bl, bd)) {
++ free(l);
++ return 1;
++ }
++
++ /* free the decoding tables, return */
++ free(l);
++ huft_free(tl);
++ huft_free(td);
++ return 0;
++}
++
++
++/*
++ * We use `noinline' here to prevent gcc-3.5 from using too much stack space
++ */
++STATIC int noinline INIT inflate_dynamic(void)
++/* decompress an inflated type 2 (dynamic Huffman codes) block. */
++{
++ int i; /* temporary variables */
++ unsigned j;
++ unsigned l; /* last length */
++ unsigned m; /* mask for bit lengths table */
++ unsigned n; /* number of lengths to get */
++ struct huft *tl; /* literal/length code table */
++ struct huft *td; /* distance code table */
++ int bl; /* lookup bits for tl */
++ int bd; /* lookup bits for td */
++ unsigned nb; /* number of bit length codes */
++ unsigned nl; /* number of literal/length codes */
++ unsigned nd; /* number of distance codes */
++ unsigned *ll; /* literal/length and distance code lengths */
++ register ulg b; /* bit buffer */
++ register unsigned k; /* number of bits in bit buffer */
++ int ret;
++
++DEBG("<dyn");
++
++#ifdef PKZIP_BUG_WORKAROUND
++ ll = malloc(sizeof(*ll) * (288+32)); /* literal/length and distance code lengths */
++#else
++ ll = malloc(sizeof(*ll) * (286+30)); /* literal/length and distance code lengths */
++#endif
++
++ if (ll == NULL)
++ return 1;
++
++ /* make local bit buffer */
++ b = bb;
++ k = bk;
++
++
++ /* read in table lengths */
++ NEEDBITS(5)
++ nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */
++ DUMPBITS(5)
++ NEEDBITS(5)
++ nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */
++ DUMPBITS(5)
++ NEEDBITS(4)
++ nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */
++ DUMPBITS(4)
++#ifdef PKZIP_BUG_WORKAROUND
++ if (nl > 288 || nd > 32)
++#else
++ if (nl > 286 || nd > 30)
++#endif
++ {
++ ret = 1; /* bad lengths */
++ goto out;
++ }
++
++DEBG("dyn1 ");
++
++ /* read in bit-length-code lengths */
++ for (j = 0; j < nb; j++)
++ {
++ NEEDBITS(3)
++ ll[border[j]] = (unsigned)b & 7;
++ DUMPBITS(3)
++ }
++ for (; j < 19; j++)
++ ll[border[j]] = 0;
++
++DEBG("dyn2 ");
++
++ /* build decoding table for trees--single level, 7 bit lookup */
++ bl = 7;
++ if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0)
++ {
++ if (i == 1)
++ huft_free(tl);
++ ret = i; /* incomplete code set */
++ goto out;
++ }
++
++DEBG("dyn3 ");
++
++ /* read in literal and distance code lengths */
++ n = nl + nd;
++ m = mask_bits[bl];
++ i = l = 0;
++ while ((unsigned)i < n)
++ {
++ NEEDBITS((unsigned)bl)
++ j = (td = tl + ((unsigned)b & m))->b;
++ DUMPBITS(j)
++ j = td->v.n;
++ if (j < 16) /* length of code in bits (0..15) */
++ ll[i++] = l = j; /* save last length in l */
++ else if (j == 16) /* repeat last length 3 to 6 times */
++ {
++ NEEDBITS(2)
++ j = 3 + ((unsigned)b & 3);
++ DUMPBITS(2)
++ if ((unsigned)i + j > n) {
++ ret = 1;
++ goto out;
++ }
++ while (j--)
++ ll[i++] = l;
++ }
++ else if (j == 17) /* 3 to 10 zero length codes */
++ {
++ NEEDBITS(3)
++ j = 3 + ((unsigned)b & 7);
++ DUMPBITS(3)
++ if ((unsigned)i + j > n) {
++ ret = 1;
++ goto out;
++ }
++ while (j--)
++ ll[i++] = 0;
++ l = 0;
++ }
++ else /* j == 18: 11 to 138 zero length codes */
++ {
++ NEEDBITS(7)
++ j = 11 + ((unsigned)b & 0x7f);
++ DUMPBITS(7)
++ if ((unsigned)i + j > n) {
++ ret = 1;
++ goto out;
++ }
++ while (j--)
++ ll[i++] = 0;
++ l = 0;
++ }
++ }
++
++DEBG("dyn4 ");
++
++ /* free decoding table for trees */
++ huft_free(tl);
++
++DEBG("dyn5 ");
++
++ /* restore the global bit buffer */
++ bb = b;
++ bk = k;
++
++DEBG("dyn5a ");
++
++ /* build the decoding tables for literal/length and distance codes */
++ bl = lbits;
++ if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0)
++ {
++DEBG("dyn5b ");
++ if (i == 1) {
++ error("incomplete literal tree");
++ huft_free(tl);
++ }
++ ret = i; /* incomplete code set */
++ goto out;
++ }
++DEBG("dyn5c ");
++ bd = dbits;
++ if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
++ {
++DEBG("dyn5d ");
++ if (i == 1) {
++ error("incomplete distance tree");
++#ifdef PKZIP_BUG_WORKAROUND
++ i = 0;
++ }
++#else
++ huft_free(td);
++ }
++ huft_free(tl);
++ ret = i; /* incomplete code set */
++ goto out;
++#endif
++ }
++
++DEBG("dyn6 ");
++
++ /* decompress until an end-of-block code */
++ if (inflate_codes(tl, td, bl, bd)) {
++ ret = 1;
++ goto out;
++ }
++
++DEBG("dyn7 ");
++
++ /* free the decoding tables, return */
++ huft_free(tl);
++ huft_free(td);
++
++ DEBG(">");
++ ret = 0;
++out:
++ free(ll);
++ return ret;
++
++underrun:
++ ret = 4; /* Input underrun */
++ goto out;
++}
++
++
++
++STATIC int INIT inflate_block(
++ int *e /* last block flag */
++ )
++/* decompress an inflated block */
++{
++ unsigned t; /* block type */
++ register ulg b; /* bit buffer */
++ register unsigned k; /* number of bits in bit buffer */
++
++ DEBG("<blk");
++
++ /* make local bit buffer */
++ b = bb;
++ k = bk;
++
++
++ /* read in last block bit */
++ NEEDBITS(1)
++ *e = (int)b & 1;
++ DUMPBITS(1)
++
++
++ /* read in block type */
++ NEEDBITS(2)
++ t = (unsigned)b & 3;
++ DUMPBITS(2)
++
++
++ /* restore the global bit buffer */
++ bb = b;
++ bk = k;
++
++ /* inflate that block type */
++ if (t == 2)
++ return inflate_dynamic();
++ if (t == 0)
++ return inflate_stored();
++ if (t == 1)
++ return inflate_fixed();
++
++ DEBG(">");
++
++ /* bad block type */
++ return 2;
++
++ underrun:
++ return 4; /* Input underrun */
++}
++
++
++
++STATIC int INIT inflate(void)
++/* decompress an inflated entry */
++{
++ int e; /* last block flag */
++ int r; /* result code */
++ unsigned h; /* maximum struct huft's malloc'ed */
++
++ /* initialize window, bit buffer */
++ wp = 0;
++ bk = 0;
++ bb = 0;
++
++
++ /* decompress until the last block */
++ h = 0;
++ do {
++ hufts = 0;
++#ifdef ARCH_HAS_DECOMP_WDOG
++ arch_decomp_wdog();
++#endif
++ r = inflate_block(&e);
++ if (r)
++ return r;
++ if (hufts > h)
++ h = hufts;
++ } while (!e);
++
++ /* Undo too much lookahead. The next read will be byte aligned so we
++ * can discard unused bits in the last meaningful byte.
++ */
++ while (bk >= 8) {
++ bk -= 8;
++ inptr--;
++ }
++
++ /* flush out slide */
++ flush_output(wp);
++
++
++ /* return success */
++#ifdef DEBUG
++ fprintf(stderr, "<%u> ", h);
++#endif /* DEBUG */
++ return 0;
++}
++
++/**********************************************************************
++ *
++ * The following are support routines for inflate.c
++ *
++ **********************************************************************/
++
++static ulg crc_32_tab[256];
++static ulg crc; /* initialized in makecrc() so it'll reside in bss */
++#define CRC_VALUE (crc ^ 0xffffffffUL)
++
++/*
++ * Code to compute the CRC-32 table. Borrowed from
++ * gzip-1.0.3/makecrc.c.
++ */
++
++static void INIT
++makecrc(void)
++{
++/* Not copyrighted 1990 Mark Adler */
++
++ unsigned long c; /* crc shift register */
++ unsigned long e; /* polynomial exclusive-or pattern */
++ int i; /* counter for all possible eight bit values */
++ int k; /* byte being shifted into crc apparatus */
++
++ /* terms of polynomial defining this crc (except x^32): */
++ static const int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
++
++ /* Make exclusive-or pattern from polynomial */
++ e = 0;
++ for (i = 0; i < sizeof(p)/sizeof(int); i++)
++ e |= 1L << (31 - p[i]);
++
++ crc_32_tab[0] = 0;
++
++ for (i = 1; i < 256; i++)
++ {
++ c = 0;
++ for (k = i | 256; k != 1; k >>= 1)
++ {
++ c = c & 1 ? (c >> 1) ^ e : c >> 1;
++ if (k & 1)
++ c ^= e;
++ }
++ crc_32_tab[i] = c;
++ }
++
++ /* this is initialized here so this code could reside in ROM */
++ crc = (ulg)0xffffffffUL; /* shift register contents */
++}
++
++/* gzip flag byte */
++#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
++#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
++#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
++#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
++#define COMMENT 0x10 /* bit 4 set: file comment present */
++#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
++#define RESERVED 0xC0 /* bit 6,7: reserved */
++
++/*
++ * Do the uncompression!
++ */
++static int INIT gunzip(void)
++{
++ uch flags;
++ unsigned char magic[2]; /* magic header */
++ char method;
++ ulg orig_crc = 0; /* original crc */
++ ulg orig_len = 0; /* original uncompressed length */
++ int res;
++
++ magic[0] = NEXTBYTE();
++ magic[1] = NEXTBYTE();
++ method = NEXTBYTE();
++
++ if (magic[0] != 037 ||
++ ((magic[1] != 0213) && (magic[1] != 0236))) {
++ error("bad gzip magic numbers");
++ return -1;
++ }
++
++ /* We only support method #8, DEFLATED */
++ if (method != 8) {
++ error("internal error, invalid method");
++ return -1;
++ }
++
++ flags = (uch)get_byte();
++ if ((flags & ENCRYPTED) != 0) {
++ error("Input is encrypted");
++ return -1;
++ }
++ if ((flags & CONTINUATION) != 0) {
++ error("Multi part input");
++ return -1;
++ }
++ if ((flags & RESERVED) != 0) {
++ error("Input has invalid flags");
++ return -1;
++ }
++ NEXTBYTE(); /* Get timestamp */
++ NEXTBYTE();
++ NEXTBYTE();
++ NEXTBYTE();
++
++ (void)NEXTBYTE(); /* Ignore extra flags for the moment */
++ (void)NEXTBYTE(); /* Ignore OS type for the moment */
++
++ if ((flags & EXTRA_FIELD) != 0) {
++ unsigned len = (unsigned)NEXTBYTE();
++ len |= ((unsigned)NEXTBYTE())<<8;
++ while (len--) (void)NEXTBYTE();
++ }
++
++ /* Get original file name if it was truncated */
++ if ((flags & ORIG_NAME) != 0) {
++ /* Discard the old name */
++ while (NEXTBYTE() != 0) /* null */ ;
++ }
++
++ /* Discard file comment if any */
++ if ((flags & COMMENT) != 0) {
++ while (NEXTBYTE() != 0) /* null */ ;
++ }
++
++ /* Decompress */
++ if ((res = inflate())) {
++ switch (res) {
++ case 0:
++ break;
++ case 1:
++ error("invalid compressed format (err=1)");
++ break;
++ case 2:
++ error("invalid compressed format (err=2)");
++ break;
++ case 3:
++ error("out of memory");
++ break;
++ case 4:
++ error("out of input data");
++ break;
++ default:
++ error("invalid compressed format (other)");
++ }
++ return -1;
++ }
++
++ /* Get the crc and original length */
++ /* crc32 (see algorithm.doc)
++ * uncompressed input size modulo 2^32
++ */
++ orig_crc = (ulg) NEXTBYTE();
++ orig_crc |= (ulg) NEXTBYTE() << 8;
++ orig_crc |= (ulg) NEXTBYTE() << 16;
++ orig_crc |= (ulg) NEXTBYTE() << 24;
++
++ orig_len = (ulg) NEXTBYTE();
++ orig_len |= (ulg) NEXTBYTE() << 8;
++ orig_len |= (ulg) NEXTBYTE() << 16;
++ orig_len |= (ulg) NEXTBYTE() << 24;
++
++ /* Validate decompression */
++ if (orig_crc != CRC_VALUE) {
++ error("crc error");
++ return -1;
++ }
++ if (orig_len != bytes_out) {
++ error("length error");
++ return -1;
++ }
++ return 0;
++
++ underrun: /* NEXTBYTE() goto's here if needed */
++ error("out of input data");
++ return -1;
++}
++
++
+diff -rupN linux-2.6.35.11/lib/kobject.c linux-2.6.35.11-ts7500/lib/kobject.c
+--- linux-2.6.35.11/lib/kobject.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/lib/kobject.c 2011-03-14 11:18:24.000000000 -0400
+@@ -795,10 +795,15 @@ static struct kset *kset_create(const ch
+ struct kset *kset;
+ int retval;
+
++ //printk("kset_create(%s), calling kzalloc()\n", name);
++
+ kset = kzalloc(sizeof(*kset), GFP_KERNEL);
++ //printk("Got kset = 0x%08lX\n", kset);
+ if (!kset)
+ return NULL;
++ //printk("kset_create(%s) calling kobject_set_name()\n", name);
+ retval = kobject_set_name(&kset->kobj, name);
++ //printk("Got retval = %d\n", retval);
+ if (retval) {
+ kfree(kset);
+ return NULL;
+@@ -838,14 +843,19 @@ struct kset *kset_create_and_add(const c
+ struct kset *kset;
+ int error;
+
++ // printk("kset_create_and_add(%s), calling kset_create()\n", name);
++
+ kset = kset_create(name, uevent_ops, parent_kobj);
++ //printk("got kset = 0x%08lX\n", kset);
+ if (!kset)
+ return NULL;
+ error = kset_register(kset);
++ // printk("Got error = %d\n", error);
+ if (error) {
+ kfree(kset);
+ return NULL;
+ }
++ //printk("kset_create_and_add(%s) is done\n", name);
+ return kset;
+ }
+ EXPORT_SYMBOL_GPL(kset_create_and_add);
+diff -rupN linux-2.6.35.11/Makefile linux-2.6.35.11-ts7500/Makefile
+--- linux-2.6.35.11/Makefile 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/Makefile 2011-03-14 11:18:24.000000000 -0400
+@@ -532,7 +532,7 @@ all: vmlinux
+ ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
+ KBUILD_CFLAGS += -Os
+ else
+-KBUILD_CFLAGS += -O2
++KBUILD_CFLAGS += -O3
+ endif
+
+ include $(srctree)/arch/$(SRCARCH)/Makefile
+diff -rupN linux-2.6.35.11/Makefile.orig linux-2.6.35.11-ts7500/Makefile.orig
+--- linux-2.6.35.11/Makefile.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/Makefile.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,1503 @@
++VERSION = 2
++PATCHLEVEL = 6
++SUBLEVEL = 35
++EXTRAVERSION = .11
++NAME = Yokohama
++
++# *DOCUMENTATION*
++# To see a list of typical targets execute "make help"
++# More info can be located in ./README
++# Comments in this file are targeted only to the developer, do not
++# expect to learn how to build the kernel reading this file.
++
++# Do not:
++# o use make's built-in rules and variables
++# (this increases performance and avoids hard-to-debug behaviour);
++# o print "Entering directory ...";
++MAKEFLAGS += -rR --no-print-directory
++
++# Avoid funny character set dependencies
++unexport LC_ALL
++LC_COLLATE=C
++LC_NUMERIC=C
++export LC_COLLATE LC_NUMERIC
++
++# We are using a recursive build, so we need to do a little thinking
++# to get the ordering right.
++#
++# Most importantly: sub-Makefiles should only ever modify files in
++# their own directory. If in some directory we have a dependency on
++# a file in another dir (which doesn't happen often, but it's often
++# unavoidable when linking the built-in.o targets which finally
++# turn into vmlinux), we will call a sub make in that other dir, and
++# after that we are sure that everything which is in that other dir
++# is now up to date.
++#
++# The only cases where we need to modify files which have global
++# effects are thus separated out and done before the recursive
++# descending is started. They are now explicitly listed as the
++# prepare rule.
++
++# To put more focus on warnings, be less verbose as default
++# Use 'make V=1' to see the full commands
++
++ifeq ("$(origin V)", "command line")
++ KBUILD_VERBOSE = $(V)
++endif
++ifndef KBUILD_VERBOSE
++ KBUILD_VERBOSE = 0
++endif
++
++# Call a source code checker (by default, "sparse") as part of the
++# C compilation.
++#
++# Use 'make C=1' to enable checking of only re-compiled files.
++# Use 'make C=2' to enable checking of *all* source files, regardless
++# of whether they are re-compiled or not.
++#
++# See the file "Documentation/sparse.txt" for more details, including
++# where to get the "sparse" utility.
++
++ifeq ("$(origin C)", "command line")
++ KBUILD_CHECKSRC = $(C)
++endif
++ifndef KBUILD_CHECKSRC
++ KBUILD_CHECKSRC = 0
++endif
++
++# Use make M=dir to specify directory of external module to build
++# Old syntax make ... SUBDIRS=$PWD is still supported
++# Setting the environment variable KBUILD_EXTMOD take precedence
++ifdef SUBDIRS
++ KBUILD_EXTMOD ?= $(SUBDIRS)
++endif
++
++ifeq ("$(origin M)", "command line")
++ KBUILD_EXTMOD := $(M)
++endif
++
++# kbuild supports saving output files in a separate directory.
++# To locate output files in a separate directory two syntaxes are supported.
++# In both cases the working directory must be the root of the kernel src.
++# 1) O=
++# Use "make O=dir/to/store/output/files/"
++#
++# 2) Set KBUILD_OUTPUT
++# Set the environment variable KBUILD_OUTPUT to point to the directory
++# where the output files shall be placed.
++# export KBUILD_OUTPUT=dir/to/store/output/files/
++# make
++#
++# The O= assignment takes precedence over the KBUILD_OUTPUT environment
++# variable.
++
++
++# KBUILD_SRC is set on invocation of make in OBJ directory
++# KBUILD_SRC is not intended to be used by the regular user (for now)
++ifeq ($(KBUILD_SRC),)
++
++# OK, Make called in directory where kernel src resides
++# Do we want to locate output files in a separate directory?
++ifeq ("$(origin O)", "command line")
++ KBUILD_OUTPUT := $(O)
++endif
++
++# That's our default target when none is given on the command line
++PHONY := _all
++_all:
++
++# Cancel implicit rules on top Makefile
++$(CURDIR)/Makefile Makefile: ;
++
++ifneq ($(KBUILD_OUTPUT),)
++# Invoke a second make in the output directory, passing relevant variables
++# check that the output directory actually exists
++saved-output := $(KBUILD_OUTPUT)
++KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd)
++$(if $(KBUILD_OUTPUT),, \
++ $(error output directory "$(saved-output)" does not exist))
++
++PHONY += $(MAKECMDGOALS) sub-make
++
++$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
++ $(Q)@:
++
++sub-make: FORCE
++ $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
++ KBUILD_SRC=$(CURDIR) \
++ KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile \
++ $(filter-out _all sub-make,$(MAKECMDGOALS))
++
++# Leave processing to above invocation of make
++skip-makefile := 1
++endif # ifneq ($(KBUILD_OUTPUT),)
++endif # ifeq ($(KBUILD_SRC),)
++
++# We process the rest of the Makefile if this is the final invocation of make
++ifeq ($(skip-makefile),)
++
++# If building an external module we do not care about the all: rule
++# but instead _all depend on modules
++PHONY += all
++ifeq ($(KBUILD_EXTMOD),)
++_all: all
++else
++_all: modules
++endif
++
++srctree := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR))
++objtree := $(CURDIR)
++src := $(srctree)
++obj := $(objtree)
++
++VPATH := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))
++
++export srctree objtree VPATH
++
++
++# SUBARCH tells the usermode build what the underlying arch is. That is set
++# first, and if a usermode build is happening, the "ARCH=um" on the command
++# line overrides the setting of ARCH below. If a native build is happening,
++# then ARCH is assigned, getting whatever value it gets normally, and
++# SUBARCH is subsequently ignored.
++
++SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
++ -e s/arm.*/arm/ -e s/sa110/arm/ \
++ -e s/s390x/s390/ -e s/parisc64/parisc/ \
++ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
++ -e s/sh[234].*/sh/ )
++
++# Cross compiling and selecting different set of gcc/bin-utils
++# ---------------------------------------------------------------------------
++#
++# When performing cross compilation for other architectures ARCH shall be set
++# to the target architecture. (See arch/* for the possibilities).
++# ARCH can be set during invocation of make:
++# make ARCH=ia64
++# Another way is to have ARCH set in the environment.
++# The default ARCH is the host where make is executed.
++
++# CROSS_COMPILE specify the prefix used for all executables used
++# during compilation. Only gcc and related bin-utils executables
++# are prefixed with $(CROSS_COMPILE).
++# CROSS_COMPILE can be set on the command line
++# make CROSS_COMPILE=ia64-linux-
++# Alternatively CROSS_COMPILE can be set in the environment.
++# A third alternative is to store a setting in .config so that plain
++# "make" in the configured kernel build directory always uses that.
++# Default value for CROSS_COMPILE is not to prefix executables
++# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
++export KBUILD_BUILDHOST := $(SUBARCH)
++ARCH ?= $(SUBARCH)
++CROSS_COMPILE ?=
++CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
++
++# Architecture as present in compile.h
++UTS_MACHINE := $(ARCH)
++SRCARCH := $(ARCH)
++
++# Additional ARCH settings for x86
++ifeq ($(ARCH),i386)
++ SRCARCH := x86
++endif
++ifeq ($(ARCH),x86_64)
++ SRCARCH := x86
++endif
++
++# Additional ARCH settings for sparc
++ifeq ($(ARCH),sparc64)
++ SRCARCH := sparc
++endif
++
++# Additional ARCH settings for sh
++ifeq ($(ARCH),sh64)
++ SRCARCH := sh
++endif
++
++# Where to locate arch specific headers
++hdr-arch := $(SRCARCH)
++
++ifeq ($(ARCH),m68knommu)
++ hdr-arch := m68k
++endif
++
++KCONFIG_CONFIG ?= .config
++
++# SHELL used by kbuild
++CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
++ else if [ -x /bin/bash ]; then echo /bin/bash; \
++ else echo sh; fi ; fi)
++
++HOSTCC = gcc
++HOSTCXX = g++
++HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer
++HOSTCXXFLAGS = -O2
++
++# Decide whether to build built-in, modular, or both.
++# Normally, just do built-in.
++
++KBUILD_MODULES :=
++KBUILD_BUILTIN := 1
++
++# If we have only "make modules", don't compile built-in objects.
++# When we're building modules with modversions, we need to consider
++# the built-in objects during the descend as well, in order to
++# make sure the checksums are up to date before we record them.
++
++ifeq ($(MAKECMDGOALS),modules)
++ KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
++endif
++
++# If we have "make <whatever> modules", compile modules
++# in addition to whatever we do anyway.
++# Just "make" or "make all" shall build modules as well
++
++ifneq ($(filter all _all modules,$(MAKECMDGOALS)),)
++ KBUILD_MODULES := 1
++endif
++
++ifeq ($(MAKECMDGOALS),)
++ KBUILD_MODULES := 1
++endif
++
++export KBUILD_MODULES KBUILD_BUILTIN
++export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
++
++# Beautify output
++# ---------------------------------------------------------------------------
++#
++# Normally, we echo the whole command before executing it. By making
++# that echo $($(quiet)$(cmd)), we now have the possibility to set
++# $(quiet) to choose other forms of output instead, e.g.
++#
++# quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@
++# cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
++#
++# If $(quiet) is empty, the whole command will be printed.
++# If it is set to "quiet_", only the short version will be printed.
++# If it is set to "silent_", nothing will be printed at all, since
++# the variable $(silent_cmd_cc_o_c) doesn't exist.
++#
++# A simple variant is to prefix commands with $(Q) - that's useful
++# for commands that shall be hidden in non-verbose mode.
++#
++# $(Q)ln $@ :<
++#
++# If KBUILD_VERBOSE equals 0 then the above command will be hidden.
++# If KBUILD_VERBOSE equals 1 then the above command is displayed.
++
++ifeq ($(KBUILD_VERBOSE),1)
++ quiet =
++ Q =
++else
++ quiet=quiet_
++ Q = @
++endif
++
++# If the user is running make -s (silent mode), suppress echoing of
++# commands
++
++ifneq ($(findstring s,$(MAKEFLAGS)),)
++ quiet=silent_
++endif
++
++export quiet Q KBUILD_VERBOSE
++
++
++# Look for make include files relative to root of kernel src
++MAKEFLAGS += --include-dir=$(srctree)
++
++# We need some generic definitions (do not try to remake the file).
++$(srctree)/scripts/Kbuild.include: ;
++include $(srctree)/scripts/Kbuild.include
++
++# Make variables (CC, etc...)
++
++AS = $(CROSS_COMPILE)as
++LD = $(CROSS_COMPILE)ld
++CC = $(CROSS_COMPILE)gcc
++CPP = $(CC) -E
++AR = $(CROSS_COMPILE)ar
++NM = $(CROSS_COMPILE)nm
++STRIP = $(CROSS_COMPILE)strip
++OBJCOPY = $(CROSS_COMPILE)objcopy
++OBJDUMP = $(CROSS_COMPILE)objdump
++AWK = awk
++GENKSYMS = scripts/genksyms/genksyms
++INSTALLKERNEL := installkernel
++DEPMOD = /sbin/depmod
++KALLSYMS = scripts/kallsyms
++PERL = perl
++CHECK = sparse
++
++CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
++ -Wbitwise -Wno-return-void $(CF)
++MODFLAGS = -DMODULE
++CFLAGS_MODULE = $(MODFLAGS)
++AFLAGS_MODULE = $(MODFLAGS)
++LDFLAGS_MODULE = -T $(srctree)/scripts/module-common.lds
++CFLAGS_KERNEL =
++AFLAGS_KERNEL =
++CFLAGS_GCOV = -fprofile-arcs -ftest-coverage
++
++
++# Use LINUXINCLUDE when you must reference the include/ directory.
++# Needed to be compatible with the O= option
++LINUXINCLUDE := -I$(srctree)/arch/$(hdr-arch)/include -Iinclude \
++ $(if $(KBUILD_SRC), -I$(srctree)/include) \
++ -include include/generated/autoconf.h
++
++KBUILD_CPPFLAGS := -D__KERNEL__
++
++KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
++ -fno-strict-aliasing -fno-common \
++ -Werror-implicit-function-declaration \
++ -Wno-format-security \
++ -fno-delete-null-pointer-checks
++KBUILD_AFLAGS := -D__ASSEMBLY__
++
++# Read KERNELRELEASE from include/config/kernel.release (if it exists)
++KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
++KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
++
++export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
++export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
++export CPP AR NM STRIP OBJCOPY OBJDUMP
++export MAKE AWK GENKSYMS INSTALLKERNEL PERL UTS_MACHINE
++export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
++
++export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
++export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV
++export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
++
++# When compiling out-of-tree modules, put MODVERDIR in the module
++# tree rather than in the kernel tree. The kernel tree might
++# even be read-only.
++export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions
++
++# Files to ignore in find ... statements
++
++RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg -o -name .git \) -prune -o
++export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg --exclude .git
++
++# ===========================================================================
++# Rules shared between *config targets and build targets
++
++# Basic helpers built in scripts/
++PHONY += scripts_basic
++scripts_basic:
++ $(Q)$(MAKE) $(build)=scripts/basic
++ $(Q)rm -f .tmp_quiet_recordmcount
++
++# To avoid any implicit rule to kick in, define an empty command.
++scripts/basic/%: scripts_basic ;
++
++PHONY += outputmakefile
++# outputmakefile generates a Makefile in the output directory, if using a
++# separate output directory. This allows convenient use of make in the
++# output directory.
++outputmakefile:
++ifneq ($(KBUILD_SRC),)
++ $(Q)ln -fsn $(srctree) source
++ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
++ $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
++endif
++
++# To make sure we do not include .config for any of the *config targets
++# catch them early, and hand them over to scripts/kconfig/Makefile
++# It is allowed to specify more targets when calling make, including
++# mixing *config targets and build targets.
++# For example 'make oldconfig all'.
++# Detect when mixed targets is specified, and make a second invocation
++# of make so .config is not included in this case either (for *config).
++
++no-dot-config-targets := clean mrproper distclean \
++ cscope TAGS tags help %docs check% \
++ include/linux/version.h headers_% \
++ kernelrelease kernelversion
++
++config-targets := 0
++mixed-targets := 0
++dot-config := 1
++
++ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
++ ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
++ dot-config := 0
++ endif
++endif
++
++ifeq ($(KBUILD_EXTMOD),)
++ ifneq ($(filter config %config,$(MAKECMDGOALS)),)
++ config-targets := 1
++ ifneq ($(filter-out config %config,$(MAKECMDGOALS)),)
++ mixed-targets := 1
++ endif
++ endif
++endif
++
++ifeq ($(mixed-targets),1)
++# ===========================================================================
++# We're called with mixed targets (*config and build targets).
++# Handle them one by one.
++
++%:: FORCE
++ $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= $@
++
++else
++ifeq ($(config-targets),1)
++# ===========================================================================
++# *config targets only - make sure prerequisites are updated, and descend
++# in scripts/kconfig to make the *config target
++
++# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed.
++# KBUILD_DEFCONFIG may point out an alternative default configuration
++# used for 'make defconfig'
++include $(srctree)/arch/$(SRCARCH)/Makefile
++export KBUILD_DEFCONFIG KBUILD_KCONFIG
++
++config: scripts_basic outputmakefile FORCE
++ $(Q)mkdir -p include/linux include/config
++ $(Q)$(MAKE) $(build)=scripts/kconfig $@
++
++%config: scripts_basic outputmakefile FORCE
++ $(Q)mkdir -p include/linux include/config
++ $(Q)$(MAKE) $(build)=scripts/kconfig $@
++
++else
++# ===========================================================================
++# Build targets only - this includes vmlinux, arch specific targets, clean
++# targets and others. In general all targets except *config targets.
++
++ifeq ($(KBUILD_EXTMOD),)
++# Additional helpers built in scripts/
++# Carefully list dependencies so we do not try to build scripts twice
++# in parallel
++PHONY += scripts
++scripts: scripts_basic include/config/auto.conf include/config/tristate.conf
++ $(Q)$(MAKE) $(build)=$(@)
++
++# Objects we will link into vmlinux / subdirs we need to visit
++init-y := init/
++drivers-y := drivers/ sound/ firmware/
++net-y := net/
++libs-y := lib/
++core-y := usr/
++endif # KBUILD_EXTMOD
++
++ifeq ($(dot-config),1)
++# Read in config
++-include include/config/auto.conf
++
++ifeq ($(KBUILD_EXTMOD),)
++# Read in dependencies to all Kconfig* files, make sure to run
++# oldconfig if changes are detected.
++-include include/config/auto.conf.cmd
++
++# To avoid any implicit rule to kick in, define an empty command
++$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
++
++# If .config is newer than include/config/auto.conf, someone tinkered
++# with it and forgot to run make oldconfig.
++# if auto.conf.cmd is missing then we are probably in a cleaned tree so
++# we execute the config step to be sure to catch updated Kconfig files
++include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
++ $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
++else
++# external modules needs include/generated/autoconf.h and include/config/auto.conf
++# but do not care if they are up-to-date. Use auto.conf to trigger the test
++PHONY += include/config/auto.conf
++
++include/config/auto.conf:
++ $(Q)test -e include/generated/autoconf.h -a -e $@ || ( \
++ echo; \
++ echo " ERROR: Kernel configuration is invalid."; \
++ echo " include/generated/autoconf.h or $@ are missing.";\
++ echo " Run 'make oldconfig && make prepare' on kernel src to fix it."; \
++ echo; \
++ /bin/false)
++
++endif # KBUILD_EXTMOD
++
++else
++# Dummy target needed, because used as prerequisite
++include/config/auto.conf: ;
++endif # $(dot-config)
++
++# The all: target is the default when no target is given on the
++# command line.
++# This allow a user to issue only 'make' to build a kernel including modules
++# Defaults vmlinux but it is usually overridden in the arch makefile
++all: vmlinux
++
++ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
++KBUILD_CFLAGS += -Os
++else
++KBUILD_CFLAGS += -O2
++endif
++
++include $(srctree)/arch/$(SRCARCH)/Makefile
++
++ifneq ($(CONFIG_FRAME_WARN),0)
++KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
++endif
++
++# Force gcc to behave correct even for buggy distributions
++ifndef CONFIG_CC_STACKPROTECTOR
++KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
++endif
++
++ifdef CONFIG_FRAME_POINTER
++KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
++else
++KBUILD_CFLAGS += -fomit-frame-pointer
++endif
++
++ifdef CONFIG_DEBUG_INFO
++KBUILD_CFLAGS += -g
++KBUILD_AFLAGS += -gdwarf-2
++endif
++
++ifdef CONFIG_FUNCTION_TRACER
++KBUILD_CFLAGS += -pg
++endif
++
++# We trigger additional mismatches with less inlining
++ifdef CONFIG_DEBUG_SECTION_MISMATCH
++KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once)
++endif
++
++# arch Makefile may override CC so keep this after arch Makefile is included
++NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
++CHECKFLAGS += $(NOSTDINC_FLAGS)
++
++# warn about C99 declaration after statement
++KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
++
++# disable pointer signed / unsigned warnings in gcc 4.0
++KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,)
++
++# disable invalid "can't wrap" optimizations for signed / pointers
++KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow)
++
++# conserve stack if available
++KBUILD_CFLAGS += $(call cc-option,-fconserve-stack)
++
++# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
++# But warn user when we do so
++warn-assign = \
++$(warning "WARNING: Appending $$K$(1) ($(K$(1))) from $(origin K$(1)) to kernel $$$(1)")
++
++ifneq ($(KCPPFLAGS),)
++ $(call warn-assign,CPPFLAGS)
++ KBUILD_CPPFLAGS += $(KCPPFLAGS)
++endif
++ifneq ($(KAFLAGS),)
++ $(call warn-assign,AFLAGS)
++ KBUILD_AFLAGS += $(KAFLAGS)
++endif
++ifneq ($(KCFLAGS),)
++ $(call warn-assign,CFLAGS)
++ KBUILD_CFLAGS += $(KCFLAGS)
++endif
++
++# Use --build-id when available.
++LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\
++ $(call cc-ldoption, -Wl$(comma)--build-id,))
++LDFLAGS_MODULE += $(LDFLAGS_BUILD_ID)
++LDFLAGS_vmlinux += $(LDFLAGS_BUILD_ID)
++
++ifeq ($(CONFIG_STRIP_ASM_SYMS),y)
++LDFLAGS_vmlinux += $(call ld-option, -X,)
++endif
++
++# Default kernel image to build when no specific target is given.
++# KBUILD_IMAGE may be overruled on the command line or
++# set in the environment
++# Also any assignments in arch/$(ARCH)/Makefile take precedence over
++# this default value
++export KBUILD_IMAGE ?= vmlinux
++
++#
++# INSTALL_PATH specifies where to place the updated kernel and system map
++# images. Default is /boot, but you can set it to other values
++export INSTALL_PATH ?= /boot
++
++#
++# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
++# relocations required by build roots. This is not defined in the
++# makefile but the argument can be passed to make if needed.
++#
++
++MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
++export MODLIB
++
++#
++# INSTALL_MOD_STRIP, if defined, will cause modules to be
++# stripped after they are installed. If INSTALL_MOD_STRIP is '1', then
++# the default option --strip-debug will be used. Otherwise,
++# INSTALL_MOD_STRIP will used as the options to the strip command.
++
++ifdef INSTALL_MOD_STRIP
++ifeq ($(INSTALL_MOD_STRIP),1)
++mod_strip_cmd = $(STRIP) --strip-debug
++else
++mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP)
++endif # INSTALL_MOD_STRIP=1
++else
++mod_strip_cmd = true
++endif # INSTALL_MOD_STRIP
++export mod_strip_cmd
++
++
++ifeq ($(KBUILD_EXTMOD),)
++core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
++
++vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
++ $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
++ $(net-y) $(net-m) $(libs-y) $(libs-m)))
++
++vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \
++ $(init-n) $(init-) \
++ $(core-n) $(core-) $(drivers-n) $(drivers-) \
++ $(net-n) $(net-) $(libs-n) $(libs-))))
++
++init-y := $(patsubst %/, %/built-in.o, $(init-y))
++core-y := $(patsubst %/, %/built-in.o, $(core-y))
++drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
++net-y := $(patsubst %/, %/built-in.o, $(net-y))
++libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
++libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
++libs-y := $(libs-y1) $(libs-y2)
++
++# Build vmlinux
++# ---------------------------------------------------------------------------
++# vmlinux is built from the objects selected by $(vmlinux-init) and
++# $(vmlinux-main). Most are built-in.o files from top-level directories
++# in the kernel tree, others are specified in arch/$(ARCH)/Makefile.
++# Ordering when linking is important, and $(vmlinux-init) must be first.
++#
++# vmlinux
++# ^
++# |
++# +-< $(vmlinux-init)
++# | +--< init/version.o + more
++# |
++# +--< $(vmlinux-main)
++# | +--< driver/built-in.o mm/built-in.o + more
++# |
++# +-< kallsyms.o (see description in CONFIG_KALLSYMS section)
++#
++# vmlinux version (uname -v) cannot be updated during normal
++# descending-into-subdirs phase since we do not yet know if we need to
++# update vmlinux.
++# Therefore this step is delayed until just before final link of vmlinux -
++# except in the kallsyms case where it is done just before adding the
++# symbols to the kernel.
++#
++# System.map is generated to document addresses of all kernel symbols
++
++vmlinux-init := $(head-y) $(init-y)
++vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
++vmlinux-all := $(vmlinux-init) $(vmlinux-main)
++vmlinux-lds := arch/$(SRCARCH)/kernel/vmlinux.lds
++export KBUILD_VMLINUX_OBJS := $(vmlinux-all)
++
++# Rule to link vmlinux - also used during CONFIG_KALLSYMS
++# May be overridden by arch/$(ARCH)/Makefile
++quiet_cmd_vmlinux__ ?= LD $@
++ cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
++ -T $(vmlinux-lds) $(vmlinux-init) \
++ --start-group $(vmlinux-main) --end-group \
++ $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o FORCE ,$^)
++
++# Generate new vmlinux version
++quiet_cmd_vmlinux_version = GEN .version
++ cmd_vmlinux_version = set -e; \
++ if [ ! -r .version ]; then \
++ rm -f .version; \
++ echo 1 >.version; \
++ else \
++ mv .version .old_version; \
++ expr 0$$(cat .old_version) + 1 >.version; \
++ fi; \
++ $(MAKE) $(build)=init
++
++# Generate System.map
++quiet_cmd_sysmap = SYSMAP
++ cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
++
++# Link of vmlinux
++# If CONFIG_KALLSYMS is set .version is already updated
++# Generate System.map and verify that the content is consistent
++# Use + in front of the vmlinux_version rule to silent warning with make -j2
++# First command is ':' to allow us to use + in front of the rule
++define rule_vmlinux__
++ :
++ $(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))
++
++ $(call cmd,vmlinux__)
++ $(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
++
++ $(Q)$(if $($(quiet)cmd_sysmap), \
++ echo ' $($(quiet)cmd_sysmap) System.map' &&) \
++ $(cmd_sysmap) $@ System.map; \
++ if [ $$? -ne 0 ]; then \
++ rm -f $@; \
++ /bin/false; \
++ fi;
++ $(verify_kallsyms)
++endef
++
++
++ifdef CONFIG_KALLSYMS
++# Generate section listing all symbols and add it into vmlinux $(kallsyms.o)
++# It's a three stage process:
++# o .tmp_vmlinux1 has all symbols and sections, but __kallsyms is
++# empty
++# Running kallsyms on that gives us .tmp_kallsyms1.o with
++# the right size - vmlinux version (uname -v) is updated during this step
++# o .tmp_vmlinux2 now has a __kallsyms section of the right size,
++# but due to the added section, some addresses have shifted.
++# From here, we generate a correct .tmp_kallsyms2.o
++# o The correct .tmp_kallsyms2.o is linked into the final vmlinux.
++# o Verify that the System.map from vmlinux matches the map from
++# .tmp_vmlinux2, just in case we did not generate kallsyms correctly.
++# o If CONFIG_KALLSYMS_EXTRA_PASS is set, do an extra pass using
++# .tmp_vmlinux3 and .tmp_kallsyms3.o. This is only meant as a
++# temporary bypass to allow the kernel to be built while the
++# maintainers work out what went wrong with kallsyms.
++
++ifdef CONFIG_KALLSYMS_EXTRA_PASS
++last_kallsyms := 3
++else
++last_kallsyms := 2
++endif
++
++kallsyms.o := .tmp_kallsyms$(last_kallsyms).o
++
++define verify_kallsyms
++ $(Q)$(if $($(quiet)cmd_sysmap), \
++ echo ' $($(quiet)cmd_sysmap) .tmp_System.map' &&) \
++ $(cmd_sysmap) .tmp_vmlinux$(last_kallsyms) .tmp_System.map
++ $(Q)cmp -s System.map .tmp_System.map || \
++ (echo Inconsistent kallsyms data; \
++ echo Try setting CONFIG_KALLSYMS_EXTRA_PASS; \
++ rm .tmp_kallsyms* ; /bin/false )
++endef
++
++# Update vmlinux version before link
++# Use + in front of this rule to silent warning about make -j1
++# First command is ':' to allow us to use + in front of this rule
++cmd_ksym_ld = $(cmd_vmlinux__)
++define rule_ksym_ld
++ :
++ +$(call cmd,vmlinux_version)
++ $(call cmd,vmlinux__)
++ $(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
++endef
++
++# Generate .S file with all kernel symbols
++quiet_cmd_kallsyms = KSYM $@
++ cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) \
++ $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@
++
++.tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
++ $(call if_changed_dep,as_o_S)
++
++.tmp_kallsyms%.S: .tmp_vmlinux% $(KALLSYMS)
++ $(call cmd,kallsyms)
++
++# .tmp_vmlinux1 must be complete except kallsyms, so update vmlinux version
++.tmp_vmlinux1: $(vmlinux-lds) $(vmlinux-all) FORCE
++ $(call if_changed_rule,ksym_ld)
++
++.tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.o FORCE
++ $(call if_changed,vmlinux__)
++
++.tmp_vmlinux3: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms2.o FORCE
++ $(call if_changed,vmlinux__)
++
++# Needs to visit scripts/ before $(KALLSYMS) can be used.
++$(KALLSYMS): scripts ;
++
++# Generate some data for debugging strange kallsyms problems
++debug_kallsyms: .tmp_map$(last_kallsyms)
++
++.tmp_map%: .tmp_vmlinux% FORCE
++ ($(OBJDUMP) -h $< | $(AWK) '/^ +[0-9]/{print $$4 " 0 " $$2}'; $(NM) $<) | sort > $@
++
++.tmp_map3: .tmp_map2
++
++.tmp_map2: .tmp_map1
++
++endif # ifdef CONFIG_KALLSYMS
++
++# Do modpost on a prelinked vmlinux. The finally linked vmlinux has
++# relevant sections renamed as per the linker script.
++quiet_cmd_vmlinux-modpost = LD $@
++ cmd_vmlinux-modpost = $(LD) $(LDFLAGS) -r -o $@ \
++ $(vmlinux-init) --start-group $(vmlinux-main) --end-group \
++ $(filter-out $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
++define rule_vmlinux-modpost
++ :
++ +$(call cmd,vmlinux-modpost)
++ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
++ $(Q)echo 'cmd_$@ := $(cmd_vmlinux-modpost)' > $(dot-target).cmd
++endef
++
++# vmlinux image - including updated kernel symbols
++vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE
++ifdef CONFIG_HEADERS_CHECK
++ $(Q)$(MAKE) -f $(srctree)/Makefile headers_check
++endif
++ifdef CONFIG_SAMPLES
++ $(Q)$(MAKE) $(build)=samples
++endif
++ifdef CONFIG_BUILD_DOCSRC
++ $(Q)$(MAKE) $(build)=Documentation
++endif
++ $(call vmlinux-modpost)
++ $(call if_changed_rule,vmlinux__)
++ $(Q)rm -f .old_version
++
++# build vmlinux.o first to catch section mismatch errors early
++ifdef CONFIG_KALLSYMS
++.tmp_vmlinux1: vmlinux.o
++endif
++
++modpost-init := $(filter-out init/built-in.o, $(vmlinux-init))
++vmlinux.o: $(modpost-init) $(vmlinux-main) FORCE
++ $(call if_changed_rule,vmlinux-modpost)
++
++# The actual objects are generated when descending,
++# make sure no implicit rule kicks in
++$(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
++
++# Handle descending into subdirectories listed in $(vmlinux-dirs)
++# Preset locale variables to speed up the build process. Limit locale
++# tweaks to this spot to avoid wrong language settings when running
++# make menuconfig etc.
++# Error messages still appears in the original language
++
++PHONY += $(vmlinux-dirs)
++$(vmlinux-dirs): prepare scripts
++ $(Q)$(MAKE) $(build)=$@
++
++# Store (new) KERNELRELASE string in include/config/kernel.release
++include/config/kernel.release: include/config/auto.conf FORCE
++ $(Q)rm -f $@
++ $(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" > $@
++
++
++# Things we need to do before we recursively start building the kernel
++# or the modules are listed in "prepare".
++# A multi level approach is used. prepareN is processed before prepareN-1.
++# archprepare is used in arch Makefiles and when processed asm symlink,
++# version.h and scripts_basic is processed / created.
++
++# Listed in dependency order
++PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3
++
++# prepare3 is used to check if we are building in a separate output directory,
++# and if so do:
++# 1) Check that make has not been executed in the kernel src $(srctree)
++prepare3: include/config/kernel.release
++ifneq ($(KBUILD_SRC),)
++ @$(kecho) ' Using $(srctree) as source for kernel'
++ $(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \
++ echo " $(srctree) is not clean, please run 'make mrproper'";\
++ echo " in the '$(srctree)' directory.";\
++ /bin/false; \
++ fi;
++endif
++
++# prepare2 creates a makefile if using a separate output directory
++prepare2: prepare3 outputmakefile
++
++prepare1: prepare2 include/linux/version.h include/generated/utsrelease.h \
++ include/config/auto.conf
++ $(cmd_crmodverdir)
++
++archprepare: prepare1 scripts_basic
++
++prepare0: archprepare FORCE
++ $(Q)$(MAKE) $(build)=.
++ $(Q)$(MAKE) $(build)=. missing-syscalls
++
++# All the preparing..
++prepare: prepare0
++
++# Generate some files
++# ---------------------------------------------------------------------------
++
++# KERNELRELEASE can change from a few different places, meaning version.h
++# needs to be updated, so this check is forced on all builds
++
++uts_len := 64
++define filechk_utsrelease.h
++ if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt $(uts_len) ]; then \
++ echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \
++ exit 1; \
++ fi; \
++ (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\";)
++endef
++
++define filechk_version.h
++ (echo \#define LINUX_VERSION_CODE $(shell \
++ expr $(VERSION) \* 65536 + $(PATCHLEVEL) \* 256 + $(SUBLEVEL)); \
++ echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)
++endef
++
++include/linux/version.h: $(srctree)/Makefile FORCE
++ $(call filechk,version.h)
++
++include/generated/utsrelease.h: include/config/kernel.release FORCE
++ $(call filechk,utsrelease.h)
++
++PHONY += headerdep
++headerdep:
++ $(Q)find include/ -name '*.h' | xargs --max-args 1 scripts/headerdep.pl
++
++# ---------------------------------------------------------------------------
++
++PHONY += depend dep
++depend dep:
++ @echo '*** Warning: make $@ is unnecessary now.'
++
++# ---------------------------------------------------------------------------
++# Firmware install
++INSTALL_FW_PATH=$(INSTALL_MOD_PATH)/lib/firmware
++export INSTALL_FW_PATH
++
++PHONY += firmware_install
++firmware_install: FORCE
++ @mkdir -p $(objtree)/firmware
++ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_install
++
++# ---------------------------------------------------------------------------
++# Kernel headers
++
++#Default location for installed headers
++export INSTALL_HDR_PATH = $(objtree)/usr
++
++hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
++
++# If we do an all arch process set dst to asm-$(hdr-arch)
++hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm)
++
++PHONY += __headers
++__headers: include/linux/version.h scripts_basic FORCE
++ $(Q)$(MAKE) $(build)=scripts scripts/unifdef
++
++PHONY += headers_install_all
++headers_install_all:
++ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh install
++
++PHONY += headers_install
++headers_install: __headers
++ $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/asm/Kbuild),, \
++ $(error Headers not exportable for the $(SRCARCH) architecture))
++ $(Q)$(MAKE) $(hdr-inst)=include
++ $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/asm $(hdr-dst)
++
++PHONY += headers_check_all
++headers_check_all: headers_install_all
++ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh check
++
++PHONY += headers_check
++headers_check: headers_install
++ $(Q)$(MAKE) $(hdr-inst)=include HDRCHECK=1
++ $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/asm $(hdr-dst) HDRCHECK=1
++
++# ---------------------------------------------------------------------------
++# Modules
++
++ifdef CONFIG_MODULES
++
++# By default, build modules as well
++
++all: modules
++
++# Build modules
++#
++# A module can be listed more than once in obj-m resulting in
++# duplicate lines in modules.order files. Those are removed
++# using awk while concatenating to the final file.
++
++PHONY += modules
++modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
++ $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
++ @$(kecho) ' Building modules, stage 2.';
++ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
++ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modbuild
++
++modules.builtin: $(vmlinux-dirs:%=%/modules.builtin)
++ $(Q)$(AWK) '!x[$$0]++' $^ > $(objtree)/modules.builtin
++
++%/modules.builtin: include/config/auto.conf
++ $(Q)$(MAKE) $(modbuiltin)=$*
++
++
++# Target to prepare building external modules
++PHONY += modules_prepare
++modules_prepare: prepare scripts
++
++# Target to install modules
++PHONY += modules_install
++modules_install: _modinst_ _modinst_post
++
++PHONY += _modinst_
++_modinst_:
++ @if [ -z "`$(DEPMOD) -V 2>/dev/null | grep module-init-tools`" ]; then \
++ echo "Warning: you may need to install module-init-tools"; \
++ echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\
++ sleep 1; \
++ fi
++ @rm -rf $(MODLIB)/kernel
++ @rm -f $(MODLIB)/source
++ @mkdir -p $(MODLIB)/kernel
++ @ln -s $(srctree) $(MODLIB)/source
++ @if [ ! $(objtree) -ef $(MODLIB)/build ]; then \
++ rm -f $(MODLIB)/build ; \
++ ln -s $(objtree) $(MODLIB)/build ; \
++ fi
++ @cp -f $(objtree)/modules.order $(MODLIB)/
++ @cp -f $(objtree)/modules.builtin $(MODLIB)/
++ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
++
++# This depmod is only for convenience to give the initial
++# boot a modules.dep even before / is mounted read-write. However the
++# boot script depmod is the master version.
++PHONY += _modinst_post
++_modinst_post: _modinst_
++ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst
++ $(call cmd,depmod)
++
++else # CONFIG_MODULES
++
++# Modules not configured
++# ---------------------------------------------------------------------------
++
++modules modules_install: FORCE
++ @echo
++ @echo "The present kernel configuration has modules disabled."
++ @echo "Type 'make config' and enable loadable module support."
++ @echo "Then build a kernel with module support enabled."
++ @echo
++ @exit 1
++
++endif # CONFIG_MODULES
++
++###
++# Cleaning is done on three levels.
++# make clean Delete most generated files
++# Leave enough to build external modules
++# make mrproper Delete the current configuration, and all generated files
++# make distclean Remove editor backup files, patch leftover files and the like
++
++# Directories & files removed with 'make clean'
++CLEAN_DIRS += $(MODVERDIR)
++CLEAN_FILES += vmlinux System.map \
++ .tmp_kallsyms* .tmp_version .tmp_vmlinux* .tmp_System.map
++
++# Directories & files removed with 'make mrproper'
++MRPROPER_DIRS += include/config usr/include include/generated
++MRPROPER_FILES += .config .config.old .version .old_version \
++ include/linux/version.h \
++ Module.symvers tags TAGS cscope*
++
++# clean - Delete most, but leave enough to build external modules
++#
++clean: rm-dirs := $(CLEAN_DIRS)
++clean: rm-files := $(CLEAN_FILES)
++clean-dirs := $(addprefix _clean_,$(srctree) $(vmlinux-alldirs) Documentation)
++
++PHONY += $(clean-dirs) clean archclean
++$(clean-dirs):
++ $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
++
++clean: archclean $(clean-dirs)
++ $(call cmd,rmdirs)
++ $(call cmd,rmfiles)
++ @find . $(RCS_FIND_IGNORE) \
++ \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
++ -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
++ -o -name '*.symtypes' -o -name 'modules.order' \
++ -o -name modules.builtin -o -name '.tmp_*.o.*' \
++ -o -name '*.gcno' \) -type f -print | xargs rm -f
++
++# mrproper - Delete all generated files, including .config
++#
++mrproper: rm-dirs := $(wildcard $(MRPROPER_DIRS))
++mrproper: rm-files := $(wildcard $(MRPROPER_FILES))
++mrproper-dirs := $(addprefix _mrproper_,Documentation/DocBook scripts)
++
++PHONY += $(mrproper-dirs) mrproper archmrproper
++$(mrproper-dirs):
++ $(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@)
++
++mrproper: clean archmrproper $(mrproper-dirs)
++ $(call cmd,rmdirs)
++ $(call cmd,rmfiles)
++
++# distclean
++#
++PHONY += distclean
++
++distclean: mrproper
++ @find $(srctree) $(RCS_FIND_IGNORE) \
++ \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
++ -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
++ -o -name '.*.rej' -o -size 0 \
++ -o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
++ -type f -print | xargs rm -f
++
++
++# Packaging of the kernel to various formats
++# ---------------------------------------------------------------------------
++# rpm target kept for backward compatibility
++package-dir := $(srctree)/scripts/package
++
++%pkg: include/config/kernel.release FORCE
++ $(Q)$(MAKE) $(build)=$(package-dir) $@
++rpm: include/config/kernel.release FORCE
++ $(Q)$(MAKE) $(build)=$(package-dir) $@
++
++
++# Brief documentation of the typical targets used
++# ---------------------------------------------------------------------------
++
++boards := $(wildcard $(srctree)/arch/$(SRCARCH)/configs/*_defconfig)
++boards := $(notdir $(boards))
++board-dirs := $(dir $(wildcard $(srctree)/arch/$(SRCARCH)/configs/*/*_defconfig))
++board-dirs := $(sort $(notdir $(board-dirs:/=)))
++
++help:
++ @echo 'Cleaning targets:'
++ @echo ' clean - Remove most generated files but keep the config and'
++ @echo ' enough build support to build external modules'
++ @echo ' mrproper - Remove all generated files + config + various backup files'
++ @echo ' distclean - mrproper + remove editor backup and patch files'
++ @echo ''
++ @echo 'Configuration targets:'
++ @$(MAKE) -f $(srctree)/scripts/kconfig/Makefile help
++ @echo ''
++ @echo 'Other generic targets:'
++ @echo ' all - Build all targets marked with [*]'
++ @echo '* vmlinux - Build the bare kernel'
++ @echo '* modules - Build all modules'
++ @echo ' modules_install - Install all modules to INSTALL_MOD_PATH (default: /)'
++ @echo ' firmware_install- Install all firmware to INSTALL_FW_PATH'
++ @echo ' (default: $$(INSTALL_MOD_PATH)/lib/firmware)'
++ @echo ' dir/ - Build all files in dir and below'
++ @echo ' dir/file.[oisS] - Build specified target only'
++ @echo ' dir/file.lst - Build specified mixed source/assembly target only'
++ @echo ' (requires a recent binutils and recent build (System.map))'
++ @echo ' dir/file.ko - Build module including final link'
++ @echo ' modules_prepare - Set up for building external modules'
++ @echo ' tags/TAGS - Generate tags file for editors'
++ @echo ' cscope - Generate cscope index'
++ @echo ' kernelrelease - Output the release version string'
++ @echo ' kernelversion - Output the version stored in Makefile'
++ @echo ' headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
++ echo ' (default: $(INSTALL_HDR_PATH))'; \
++ echo ''
++ @echo 'Static analysers'
++ @echo ' checkstack - Generate a list of stack hogs'
++ @echo ' namespacecheck - Name space analysis on compiled kernel'
++ @echo ' versioncheck - Sanity check on version.h usage'
++ @echo ' includecheck - Check for duplicate included header files'
++ @echo ' export_report - List the usages of all exported symbols'
++ @echo ' headers_check - Sanity check on exported headers'
++ @echo ' headerdep - Detect inclusion cycles in headers'; \
++ echo ''
++ @echo 'Kernel packaging:'
++ @$(MAKE) $(build)=$(package-dir) help
++ @echo ''
++ @echo 'Documentation targets:'
++ @$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp
++ @echo ''
++ @echo 'Architecture specific targets ($(SRCARCH)):'
++ @$(if $(archhelp),$(archhelp),\
++ echo ' No architecture specific help defined for $(SRCARCH)')
++ @echo ''
++ @$(if $(boards), \
++ $(foreach b, $(boards), \
++ printf " %-24s - Build for %s\\n" $(b) $(subst _defconfig,,$(b));) \
++ echo '')
++ @$(if $(board-dirs), \
++ $(foreach b, $(board-dirs), \
++ printf " %-16s - Show %s-specific targets\\n" help-$(b) $(b);) \
++ printf " %-16s - Show all of the above\\n" help-boards; \
++ echo '')
++
++ @echo ' make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'
++ @echo ' make V=2 [targets] 2 => give reason for rebuild of target'
++ @echo ' make O=dir [targets] Locate all output files in "dir", including .config'
++ @echo ' make C=1 [targets] Check all c source with $$CHECK (sparse by default)'
++ @echo ' make C=2 [targets] Force check of all c source with $$CHECK'
++ @echo ''
++ @echo 'Execute "make" or "make all" to build all targets marked with [*] '
++ @echo 'For further info see the ./README file'
++
++
++help-board-dirs := $(addprefix help-,$(board-dirs))
++
++help-boards: $(help-board-dirs)
++
++boards-per-dir = $(notdir $(wildcard $(srctree)/arch/$(SRCARCH)/configs/$*/*_defconfig))
++
++$(help-board-dirs): help-%:
++ @echo 'Architecture specific targets ($(SRCARCH) $*):'
++ @$(if $(boards-per-dir), \
++ $(foreach b, $(boards-per-dir), \
++ printf " %-24s - Build for %s\\n" $*/$(b) $(subst _defconfig,,$(b));) \
++ echo '')
++
++
++# Documentation targets
++# ---------------------------------------------------------------------------
++%docs: scripts_basic FORCE
++ $(Q)$(MAKE) $(build)=Documentation/DocBook $@
++
++else # KBUILD_EXTMOD
++
++###
++# External module support.
++# When building external modules the kernel used as basis is considered
++# read-only, and no consistency checks are made and the make
++# system is not used on the basis kernel. If updates are required
++# in the basis kernel ordinary make commands (without M=...) must
++# be used.
++#
++# The following are the only valid targets when building external
++# modules.
++# make M=dir clean Delete all automatically generated files
++# make M=dir modules Make all modules in specified dir
++# make M=dir Same as 'make M=dir modules'
++# make M=dir modules_install
++# Install the modules built in the module directory
++# Assumes install directory is already created
++
++# We are always building modules
++KBUILD_MODULES := 1
++PHONY += crmodverdir
++crmodverdir:
++ $(cmd_crmodverdir)
++
++PHONY += $(objtree)/Module.symvers
++$(objtree)/Module.symvers:
++ @test -e $(objtree)/Module.symvers || ( \
++ echo; \
++ echo " WARNING: Symbol version dump $(objtree)/Module.symvers"; \
++ echo " is missing; modules will have no dependencies and modversions."; \
++ echo )
++
++module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD))
++PHONY += $(module-dirs) modules
++$(module-dirs): crmodverdir $(objtree)/Module.symvers
++ $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@)
++
++modules: $(module-dirs)
++ @$(kecho) ' Building modules, stage 2.';
++ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
++
++PHONY += modules_install
++modules_install: _emodinst_ _emodinst_post
++
++install-dir := $(if $(INSTALL_MOD_DIR),$(INSTALL_MOD_DIR),extra)
++PHONY += _emodinst_
++_emodinst_:
++ $(Q)mkdir -p $(MODLIB)/$(install-dir)
++ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
++
++PHONY += _emodinst_post
++_emodinst_post: _emodinst_
++ $(call cmd,depmod)
++
++clean-dirs := $(addprefix _clean_,$(KBUILD_EXTMOD))
++
++PHONY += $(clean-dirs) clean
++$(clean-dirs):
++ $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
++
++clean: rm-dirs := $(MODVERDIR)
++clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers \
++ $(KBUILD_EXTMOD)/modules.order \
++ $(KBUILD_EXTMOD)/modules.builtin
++clean: $(clean-dirs)
++ $(call cmd,rmdirs)
++ $(call cmd,rmfiles)
++ @find $(KBUILD_EXTMOD) $(RCS_FIND_IGNORE) \
++ \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
++ -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
++ -o -name '*.gcno' \) -type f -print | xargs rm -f
++
++help:
++ @echo ' Building external modules.'
++ @echo ' Syntax: make -C path/to/kernel/src M=$$PWD target'
++ @echo ''
++ @echo ' modules - default target, build the module(s)'
++ @echo ' modules_install - install the module'
++ @echo ' clean - remove generated files in module directory only'
++ @echo ''
++
++# Dummies...
++PHONY += prepare scripts
++prepare: ;
++scripts: ;
++endif # KBUILD_EXTMOD
++
++# Generate tags for editors
++# ---------------------------------------------------------------------------
++quiet_cmd_tags = GEN $@
++ cmd_tags = $(CONFIG_SHELL) $(srctree)/scripts/tags.sh $@
++
++tags TAGS cscope: FORCE
++ $(call cmd,tags)
++
++# Scripts to check various things for consistency
++# ---------------------------------------------------------------------------
++
++includecheck:
++ find * $(RCS_FIND_IGNORE) \
++ -name '*.[hcS]' -type f -print | sort \
++ | xargs $(PERL) -w $(srctree)/scripts/checkincludes.pl
++
++versioncheck:
++ find * $(RCS_FIND_IGNORE) \
++ -name '*.[hcS]' -type f -print | sort \
++ | xargs $(PERL) -w $(srctree)/scripts/checkversion.pl
++
++namespacecheck:
++ $(PERL) $(srctree)/scripts/namespace.pl
++
++export_report:
++ $(PERL) $(srctree)/scripts/export_report.pl
++
++endif #ifeq ($(config-targets),1)
++endif #ifeq ($(mixed-targets),1)
++
++PHONY += checkstack kernelrelease kernelversion
++
++# UML needs a little special treatment here. It wants to use the host
++# toolchain, so needs $(SUBARCH) passed to checkstack.pl. Everyone
++# else wants $(ARCH), including people doing cross-builds, which means
++# that $(SUBARCH) doesn't work here.
++ifeq ($(ARCH), um)
++CHECKSTACK_ARCH := $(SUBARCH)
++else
++CHECKSTACK_ARCH := $(ARCH)
++endif
++checkstack:
++ $(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
++ $(PERL) $(src)/scripts/checkstack.pl $(CHECKSTACK_ARCH)
++
++kernelrelease:
++ $(if $(wildcard include/config/kernel.release), $(Q)echo $(KERNELRELEASE), \
++ $(error kernelrelease not valid - run 'make prepare' to update it))
++kernelversion:
++ @echo $(KERNELVERSION)
++
++# Single targets
++# ---------------------------------------------------------------------------
++# Single targets are compatible with:
++# - build with mixed source and output
++# - build with separate output dir 'make O=...'
++# - external modules
++#
++# target-dir => where to store outputfile
++# build-dir => directory in kernel source tree to use
++
++ifeq ($(KBUILD_EXTMOD),)
++ build-dir = $(patsubst %/,%,$(dir $@))
++ target-dir = $(dir $@)
++else
++ zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@)))
++ build-dir = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash))
++ target-dir = $(if $(KBUILD_EXTMOD),$(dir $<),$(dir $@))
++endif
++
++%.s: %.c prepare scripts FORCE
++ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
++%.i: %.c prepare scripts FORCE
++ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
++%.o: %.c prepare scripts FORCE
++ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
++%.lst: %.c prepare scripts FORCE
++ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
++%.s: %.S prepare scripts FORCE
++ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
++%.o: %.S prepare scripts FORCE
++ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
++%.symtypes: %.c prepare scripts FORCE
++ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
++
++# Modules
++/: prepare scripts FORCE
++ $(cmd_crmodverdir)
++ $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
++ $(build)=$(build-dir)
++%/: prepare scripts FORCE
++ $(cmd_crmodverdir)
++ $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
++ $(build)=$(build-dir)
++%.ko: prepare scripts FORCE
++ $(cmd_crmodverdir)
++ $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
++ $(build)=$(build-dir) $(@:.ko=.o)
++ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
++
++# FIXME Should go into a make.lib or something
++# ===========================================================================
++
++quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN $(wildcard $(rm-dirs)))
++ cmd_rmdirs = rm -rf $(rm-dirs)
++
++quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files)))
++ cmd_rmfiles = rm -f $(rm-files)
++
++# Run depmod only if we have System.map and depmod is executable
++quiet_cmd_depmod = DEPMOD $(KERNELRELEASE)
++ cmd_depmod = \
++ if [ -r System.map -a -x $(DEPMOD) ]; then \
++ $(DEPMOD) -ae -F System.map \
++ $(if $(strip $(INSTALL_MOD_PATH)), -b $(INSTALL_MOD_PATH) ) \
++ $(KERNELRELEASE); \
++ fi
++
++# Create temporary dir for module support files
++# clean it up only when building all modules
++cmd_crmodverdir = $(Q)mkdir -p $(MODVERDIR) \
++ $(if $(KBUILD_MODULES),; rm -f $(MODVERDIR)/*)
++
++a_flags = -Wp,-MD,$(depfile) $(KBUILD_AFLAGS) $(AFLAGS_KERNEL) \
++ $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(KBUILD_CPPFLAGS) \
++ $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(basetarget).o)
++
++quiet_cmd_as_o_S = AS $@
++cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
++
++# read all saved command lines
++
++targets := $(wildcard $(sort $(targets)))
++cmd_files := $(wildcard .*.cmd $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
++
++ifneq ($(cmd_files),)
++ $(cmd_files): ; # Do not try to update included dependency files
++ include $(cmd_files)
++endif
++
++# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=dir
++# Usage:
++# $(Q)$(MAKE) $(clean)=dir
++clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
++
++endif # skip-makefile
++
++PHONY += FORCE
++FORCE:
++
++# Declare the contents of the .PHONY variable as phony. We keep that
++# information in a variable so we can use it in if_changed and friends.
++.PHONY: $(PHONY)
+diff -rupN linux-2.6.35.11/mm/backing-dev.c linux-2.6.35.11-ts7500/mm/backing-dev.c
+--- linux-2.6.35.11/mm/backing-dev.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/mm/backing-dev.c 2011-03-14 11:18:24.000000000 -0400
+@@ -661,6 +661,7 @@ int bdi_init(struct backing_dev_info *bd
+ {
+ int i, err;
+
++//printk("bdi_init(), Calling spin_lock_init()\n");
+ bdi->dev = NULL;
+
+ bdi->min_ratio = 0;
+@@ -672,6 +673,7 @@ int bdi_init(struct backing_dev_info *bd
+ INIT_LIST_HEAD(&bdi->wb_list);
+ INIT_LIST_HEAD(&bdi->work_list);
+
++//printk("Calling bdi_wb_init()\n");
+ bdi_wb_init(&bdi->wb, bdi);
+
+ for (i = 0; i < NR_BDI_STAT_ITEMS; i++) {
+@@ -680,6 +682,7 @@ int bdi_init(struct backing_dev_info *bd
+ goto err;
+ }
+
++//printk("Calling prop_local_init_percpu()\n");
+ bdi->dirty_exceeded = 0;
+ err = prop_local_init_percpu(&bdi->completions);
+
+diff -rupN linux-2.6.35.11/mm/backing-dev.c.orig linux-2.6.35.11-ts7500/mm/backing-dev.c.orig
+--- linux-2.6.35.11/mm/backing-dev.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/mm/backing-dev.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,798 @@
++
++#include <linux/wait.h>
++#include <linux/backing-dev.h>
++#include <linux/kthread.h>
++#include <linux/freezer.h>
++#include <linux/fs.h>
++#include <linux/pagemap.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/module.h>
++#include <linux/writeback.h>
++#include <linux/device.h>
++
++static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0);
++
++void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
++{
++}
++EXPORT_SYMBOL(default_unplug_io_fn);
++
++struct backing_dev_info default_backing_dev_info = {
++ .name = "default",
++ .ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE,
++ .state = 0,
++ .capabilities = BDI_CAP_MAP_COPY,
++ .unplug_io_fn = default_unplug_io_fn,
++};
++EXPORT_SYMBOL_GPL(default_backing_dev_info);
++
++struct backing_dev_info noop_backing_dev_info = {
++ .name = "noop",
++ .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK,
++};
++EXPORT_SYMBOL_GPL(noop_backing_dev_info);
++
++static struct class *bdi_class;
++
++/*
++ * bdi_lock protects updates to bdi_list and bdi_pending_list, as well as
++ * reader side protection for bdi_pending_list. bdi_list has RCU reader side
++ * locking.
++ */
++DEFINE_SPINLOCK(bdi_lock);
++LIST_HEAD(bdi_list);
++LIST_HEAD(bdi_pending_list);
++
++static struct task_struct *sync_supers_tsk;
++static struct timer_list sync_supers_timer;
++
++static int bdi_sync_supers(void *);
++static void sync_supers_timer_fn(unsigned long);
++
++static void bdi_add_default_flusher_task(struct backing_dev_info *bdi);
++
++#ifdef CONFIG_DEBUG_FS
++#include <linux/debugfs.h>
++#include <linux/seq_file.h>
++
++static struct dentry *bdi_debug_root;
++
++static void bdi_debug_init(void)
++{
++ bdi_debug_root = debugfs_create_dir("bdi", NULL);
++}
++
++static int bdi_debug_stats_show(struct seq_file *m, void *v)
++{
++ struct backing_dev_info *bdi = m->private;
++ struct bdi_writeback *wb;
++ unsigned long background_thresh;
++ unsigned long dirty_thresh;
++ unsigned long bdi_thresh;
++ unsigned long nr_dirty, nr_io, nr_more_io, nr_wb;
++ struct inode *inode;
++
++ /*
++ * inode lock is enough here, the bdi->wb_list is protected by
++ * RCU on the reader side
++ */
++ nr_wb = nr_dirty = nr_io = nr_more_io = 0;
++ spin_lock(&inode_lock);
++ list_for_each_entry(wb, &bdi->wb_list, list) {
++ nr_wb++;
++ list_for_each_entry(inode, &wb->b_dirty, i_list)
++ nr_dirty++;
++ list_for_each_entry(inode, &wb->b_io, i_list)
++ nr_io++;
++ list_for_each_entry(inode, &wb->b_more_io, i_list)
++ nr_more_io++;
++ }
++ spin_unlock(&inode_lock);
++
++ get_dirty_limits(&background_thresh, &dirty_thresh, &bdi_thresh, bdi);
++
++#define K(x) ((x) << (PAGE_SHIFT - 10))
++ seq_printf(m,
++ "BdiWriteback: %8lu kB\n"
++ "BdiReclaimable: %8lu kB\n"
++ "BdiDirtyThresh: %8lu kB\n"
++ "DirtyThresh: %8lu kB\n"
++ "BackgroundThresh: %8lu kB\n"
++ "WritebackThreads: %8lu\n"
++ "b_dirty: %8lu\n"
++ "b_io: %8lu\n"
++ "b_more_io: %8lu\n"
++ "bdi_list: %8u\n"
++ "state: %8lx\n"
++ "wb_list: %8u\n",
++ (unsigned long) K(bdi_stat(bdi, BDI_WRITEBACK)),
++ (unsigned long) K(bdi_stat(bdi, BDI_RECLAIMABLE)),
++ K(bdi_thresh), K(dirty_thresh),
++ K(background_thresh), nr_wb, nr_dirty, nr_io, nr_more_io,
++ !list_empty(&bdi->bdi_list), bdi->state,
++ !list_empty(&bdi->wb_list));
++#undef K
++
++ return 0;
++}
++
++static int bdi_debug_stats_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, bdi_debug_stats_show, inode->i_private);
++}
++
++static const struct file_operations bdi_debug_stats_fops = {
++ .open = bdi_debug_stats_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static void bdi_debug_register(struct backing_dev_info *bdi, const char *name)
++{
++ bdi->debug_dir = debugfs_create_dir(name, bdi_debug_root);
++ bdi->debug_stats = debugfs_create_file("stats", 0444, bdi->debug_dir,
++ bdi, &bdi_debug_stats_fops);
++}
++
++static void bdi_debug_unregister(struct backing_dev_info *bdi)
++{
++ debugfs_remove(bdi->debug_stats);
++ debugfs_remove(bdi->debug_dir);
++}
++#else
++static inline void bdi_debug_init(void)
++{
++}
++static inline void bdi_debug_register(struct backing_dev_info *bdi,
++ const char *name)
++{
++}
++static inline void bdi_debug_unregister(struct backing_dev_info *bdi)
++{
++}
++#endif
++
++static ssize_t read_ahead_kb_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct backing_dev_info *bdi = dev_get_drvdata(dev);
++ char *end;
++ unsigned long read_ahead_kb;
++ ssize_t ret = -EINVAL;
++
++ read_ahead_kb = simple_strtoul(buf, &end, 10);
++ if (*buf && (end[0] == '\0' || (end[0] == '\n' && end[1] == '\0'))) {
++ bdi->ra_pages = read_ahead_kb >> (PAGE_SHIFT - 10);
++ ret = count;
++ }
++ return ret;
++}
++
++#define K(pages) ((pages) << (PAGE_SHIFT - 10))
++
++#define BDI_SHOW(name, expr) \
++static ssize_t name##_show(struct device *dev, \
++ struct device_attribute *attr, char *page) \
++{ \
++ struct backing_dev_info *bdi = dev_get_drvdata(dev); \
++ \
++ return snprintf(page, PAGE_SIZE-1, "%lld\n", (long long)expr); \
++}
++
++BDI_SHOW(read_ahead_kb, K(bdi->ra_pages))
++
++static ssize_t min_ratio_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct backing_dev_info *bdi = dev_get_drvdata(dev);
++ char *end;
++ unsigned int ratio;
++ ssize_t ret = -EINVAL;
++
++ ratio = simple_strtoul(buf, &end, 10);
++ if (*buf && (end[0] == '\0' || (end[0] == '\n' && end[1] == '\0'))) {
++ ret = bdi_set_min_ratio(bdi, ratio);
++ if (!ret)
++ ret = count;
++ }
++ return ret;
++}
++BDI_SHOW(min_ratio, bdi->min_ratio)
++
++static ssize_t max_ratio_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct backing_dev_info *bdi = dev_get_drvdata(dev);
++ char *end;
++ unsigned int ratio;
++ ssize_t ret = -EINVAL;
++
++ ratio = simple_strtoul(buf, &end, 10);
++ if (*buf && (end[0] == '\0' || (end[0] == '\n' && end[1] == '\0'))) {
++ ret = bdi_set_max_ratio(bdi, ratio);
++ if (!ret)
++ ret = count;
++ }
++ return ret;
++}
++BDI_SHOW(max_ratio, bdi->max_ratio)
++
++#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store)
++
++static struct device_attribute bdi_dev_attrs[] = {
++ __ATTR_RW(read_ahead_kb),
++ __ATTR_RW(min_ratio),
++ __ATTR_RW(max_ratio),
++ __ATTR_NULL,
++};
++
++static __init int bdi_class_init(void)
++{
++ bdi_class = class_create(THIS_MODULE, "bdi");
++ if (IS_ERR(bdi_class))
++ return PTR_ERR(bdi_class);
++
++ bdi_class->dev_attrs = bdi_dev_attrs;
++ bdi_debug_init();
++ return 0;
++}
++postcore_initcall(bdi_class_init);
++
++static int __init default_bdi_init(void)
++{
++ int err;
++
++ sync_supers_tsk = kthread_run(bdi_sync_supers, NULL, "sync_supers");
++ BUG_ON(IS_ERR(sync_supers_tsk));
++
++ init_timer(&sync_supers_timer);
++ setup_timer(&sync_supers_timer, sync_supers_timer_fn, 0);
++ bdi_arm_supers_timer();
++
++ err = bdi_init(&default_backing_dev_info);
++ if (!err)
++ bdi_register(&default_backing_dev_info, NULL, "default");
++ err = bdi_init(&noop_backing_dev_info);
++
++ return err;
++}
++subsys_initcall(default_bdi_init);
++
++static void bdi_wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi)
++{
++ memset(wb, 0, sizeof(*wb));
++
++ wb->bdi = bdi;
++ wb->last_old_flush = jiffies;
++ INIT_LIST_HEAD(&wb->b_dirty);
++ INIT_LIST_HEAD(&wb->b_io);
++ INIT_LIST_HEAD(&wb->b_more_io);
++}
++
++static void bdi_task_init(struct backing_dev_info *bdi,
++ struct bdi_writeback *wb)
++{
++ struct task_struct *tsk = current;
++
++ spin_lock(&bdi->wb_lock);
++ list_add_tail_rcu(&wb->list, &bdi->wb_list);
++ spin_unlock(&bdi->wb_lock);
++
++ tsk->flags |= PF_FLUSHER | PF_SWAPWRITE;
++ set_freezable();
++
++ /*
++ * Our parent may run at a different priority, just set us to normal
++ */
++ set_user_nice(tsk, 0);
++}
++
++static int bdi_start_fn(void *ptr)
++{
++ struct bdi_writeback *wb = ptr;
++ struct backing_dev_info *bdi = wb->bdi;
++ int ret;
++
++ /*
++ * Add us to the active bdi_list
++ */
++ spin_lock_bh(&bdi_lock);
++ list_add_rcu(&bdi->bdi_list, &bdi_list);
++ spin_unlock_bh(&bdi_lock);
++
++ bdi_task_init(bdi, wb);
++
++ /*
++ * Clear pending bit and wakeup anybody waiting to tear us down
++ */
++ clear_bit(BDI_pending, &bdi->state);
++ smp_mb__after_clear_bit();
++ wake_up_bit(&bdi->state, BDI_pending);
++
++ ret = bdi_writeback_task(wb);
++
++ /*
++ * Remove us from the list
++ */
++ spin_lock(&bdi->wb_lock);
++ list_del_rcu(&wb->list);
++ spin_unlock(&bdi->wb_lock);
++
++ /*
++ * Flush any work that raced with us exiting. No new work
++ * will be added, since this bdi isn't discoverable anymore.
++ */
++ if (!list_empty(&bdi->work_list))
++ wb_do_writeback(wb, 1);
++
++ wb->task = NULL;
++ return ret;
++}
++
++int bdi_has_dirty_io(struct backing_dev_info *bdi)
++{
++ return wb_has_dirty_io(&bdi->wb);
++}
++
++static void bdi_flush_io(struct backing_dev_info *bdi)
++{
++ struct writeback_control wbc = {
++ .sync_mode = WB_SYNC_NONE,
++ .older_than_this = NULL,
++ .range_cyclic = 1,
++ .nr_to_write = 1024,
++ };
++
++ writeback_inodes_wb(&bdi->wb, &wbc);
++}
++
++/*
++ * kupdated() used to do this. We cannot do it from the bdi_forker_task()
++ * or we risk deadlocking on ->s_umount. The longer term solution would be
++ * to implement sync_supers_bdi() or similar and simply do it from the
++ * bdi writeback tasks individually.
++ */
++static int bdi_sync_supers(void *unused)
++{
++ set_user_nice(current, 0);
++
++ while (!kthread_should_stop()) {
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule();
++
++ /*
++ * Do this periodically, like kupdated() did before.
++ */
++ sync_supers();
++ }
++
++ return 0;
++}
++
++void bdi_arm_supers_timer(void)
++{
++ unsigned long next;
++
++ if (!dirty_writeback_interval)
++ return;
++
++ next = msecs_to_jiffies(dirty_writeback_interval * 10) + jiffies;
++ mod_timer(&sync_supers_timer, round_jiffies_up(next));
++}
++
++static void sync_supers_timer_fn(unsigned long unused)
++{
++ wake_up_process(sync_supers_tsk);
++ bdi_arm_supers_timer();
++}
++
++static int bdi_forker_task(void *ptr)
++{
++ struct bdi_writeback *me = ptr;
++
++ bdi_task_init(me->bdi, me);
++
++ for (;;) {
++ struct backing_dev_info *bdi, *tmp;
++ struct bdi_writeback *wb;
++
++ /*
++ * Temporary measure, we want to make sure we don't see
++ * dirty data on the default backing_dev_info
++ */
++ if (wb_has_dirty_io(me) || !list_empty(&me->bdi->work_list))
++ wb_do_writeback(me, 0);
++
++ spin_lock_bh(&bdi_lock);
++
++ /*
++ * Check if any existing bdi's have dirty data without
++ * a thread registered. If so, set that up.
++ */
++ list_for_each_entry_safe(bdi, tmp, &bdi_list, bdi_list) {
++ if (bdi->wb.task)
++ continue;
++ if (list_empty(&bdi->work_list) &&
++ !bdi_has_dirty_io(bdi))
++ continue;
++
++ bdi_add_default_flusher_task(bdi);
++ }
++
++ set_current_state(TASK_INTERRUPTIBLE);
++
++ if (list_empty(&bdi_pending_list)) {
++ unsigned long wait;
++
++ spin_unlock_bh(&bdi_lock);
++ wait = msecs_to_jiffies(dirty_writeback_interval * 10);
++ if (wait)
++ schedule_timeout(wait);
++ else
++ schedule();
++ try_to_freeze();
++ continue;
++ }
++
++ __set_current_state(TASK_RUNNING);
++
++ /*
++ * This is our real job - check for pending entries in
++ * bdi_pending_list, and create the tasks that got added
++ */
++ bdi = list_entry(bdi_pending_list.next, struct backing_dev_info,
++ bdi_list);
++ list_del_init(&bdi->bdi_list);
++ spin_unlock_bh(&bdi_lock);
++
++ wb = &bdi->wb;
++ wb->task = kthread_run(bdi_start_fn, wb, "flush-%s",
++ dev_name(bdi->dev));
++ /*
++ * If task creation fails, then readd the bdi to
++ * the pending list and force writeout of the bdi
++ * from this forker thread. That will free some memory
++ * and we can try again.
++ */
++ if (IS_ERR(wb->task)) {
++ wb->task = NULL;
++
++ /*
++ * Add this 'bdi' to the back, so we get
++ * a chance to flush other bdi's to free
++ * memory.
++ */
++ spin_lock_bh(&bdi_lock);
++ list_add_tail(&bdi->bdi_list, &bdi_pending_list);
++ spin_unlock_bh(&bdi_lock);
++
++ bdi_flush_io(bdi);
++ }
++ }
++
++ return 0;
++}
++
++static void bdi_add_to_pending(struct rcu_head *head)
++{
++ struct backing_dev_info *bdi;
++
++ bdi = container_of(head, struct backing_dev_info, rcu_head);
++ INIT_LIST_HEAD(&bdi->bdi_list);
++
++ spin_lock(&bdi_lock);
++ list_add_tail(&bdi->bdi_list, &bdi_pending_list);
++ spin_unlock(&bdi_lock);
++
++ /*
++ * We are now on the pending list, wake up bdi_forker_task()
++ * to finish the job and add us back to the active bdi_list
++ */
++ wake_up_process(default_backing_dev_info.wb.task);
++}
++
++/*
++ * Add the default flusher task that gets created for any bdi
++ * that has dirty data pending writeout
++ */
++void static bdi_add_default_flusher_task(struct backing_dev_info *bdi)
++{
++ if (!bdi_cap_writeback_dirty(bdi))
++ return;
++
++ if (WARN_ON(!test_bit(BDI_registered, &bdi->state))) {
++ printk(KERN_ERR "bdi %p/%s is not registered!\n",
++ bdi, bdi->name);
++ return;
++ }
++
++ /*
++ * Check with the helper whether to proceed adding a task. Will only
++ * abort if we two or more simultanous calls to
++ * bdi_add_default_flusher_task() occured, further additions will block
++ * waiting for previous additions to finish.
++ */
++ if (!test_and_set_bit(BDI_pending, &bdi->state)) {
++ list_del_rcu(&bdi->bdi_list);
++
++ /*
++ * We must wait for the current RCU period to end before
++ * moving to the pending list. So schedule that operation
++ * from an RCU callback.
++ */
++ call_rcu(&bdi->rcu_head, bdi_add_to_pending);
++ }
++}
++
++/*
++ * Remove bdi from bdi_list, and ensure that it is no longer visible
++ */
++static void bdi_remove_from_list(struct backing_dev_info *bdi)
++{
++ spin_lock_bh(&bdi_lock);
++ list_del_rcu(&bdi->bdi_list);
++ spin_unlock_bh(&bdi_lock);
++
++ synchronize_rcu();
++}
++
++int bdi_register(struct backing_dev_info *bdi, struct device *parent,
++ const char *fmt, ...)
++{
++ va_list args;
++ int ret = 0;
++ struct device *dev;
++
++ if (bdi->dev) /* The driver needs to use separate queues per device */
++ goto exit;
++
++ va_start(args, fmt);
++ dev = device_create_vargs(bdi_class, parent, MKDEV(0, 0), bdi, fmt, args);
++ va_end(args);
++ if (IS_ERR(dev)) {
++ ret = PTR_ERR(dev);
++ goto exit;
++ }
++
++ spin_lock_bh(&bdi_lock);
++ list_add_tail_rcu(&bdi->bdi_list, &bdi_list);
++ spin_unlock_bh(&bdi_lock);
++
++ bdi->dev = dev;
++
++ /*
++ * Just start the forker thread for our default backing_dev_info,
++ * and add other bdi's to the list. They will get a thread created
++ * on-demand when they need it.
++ */
++ if (bdi_cap_flush_forker(bdi)) {
++ struct bdi_writeback *wb = &bdi->wb;
++
++ wb->task = kthread_run(bdi_forker_task, wb, "bdi-%s",
++ dev_name(dev));
++ if (IS_ERR(wb->task)) {
++ wb->task = NULL;
++ ret = -ENOMEM;
++
++ bdi_remove_from_list(bdi);
++ goto exit;
++ }
++ }
++
++ bdi_debug_register(bdi, dev_name(dev));
++ set_bit(BDI_registered, &bdi->state);
++exit:
++ return ret;
++}
++EXPORT_SYMBOL(bdi_register);
++
++int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev)
++{
++ return bdi_register(bdi, NULL, "%u:%u", MAJOR(dev), MINOR(dev));
++}
++EXPORT_SYMBOL(bdi_register_dev);
++
++/*
++ * Remove bdi from the global list and shutdown any threads we have running
++ */
++static void bdi_wb_shutdown(struct backing_dev_info *bdi)
++{
++ struct bdi_writeback *wb;
++
++ if (!bdi_cap_writeback_dirty(bdi))
++ return;
++
++ /*
++ * If setup is pending, wait for that to complete first
++ */
++ wait_on_bit(&bdi->state, BDI_pending, bdi_sched_wait,
++ TASK_UNINTERRUPTIBLE);
++
++ /*
++ * Make sure nobody finds us on the bdi_list anymore
++ */
++ bdi_remove_from_list(bdi);
++
++ /*
++ * Finally, kill the kernel threads. We don't need to be RCU
++ * safe anymore, since the bdi is gone from visibility. Force
++ * unfreeze of the thread before calling kthread_stop(), otherwise
++ * it would never exet if it is currently stuck in the refrigerator.
++ */
++ list_for_each_entry(wb, &bdi->wb_list, list) {
++ thaw_process(wb->task);
++ kthread_stop(wb->task);
++ }
++}
++
++/*
++ * This bdi is going away now, make sure that no super_blocks point to it
++ */
++static void bdi_prune_sb(struct backing_dev_info *bdi)
++{
++ struct super_block *sb;
++
++ spin_lock(&sb_lock);
++ list_for_each_entry(sb, &super_blocks, s_list) {
++ if (sb->s_bdi == bdi)
++ sb->s_bdi = NULL;
++ }
++ spin_unlock(&sb_lock);
++}
++
++void bdi_unregister(struct backing_dev_info *bdi)
++{
++ if (bdi->dev) {
++ bdi_prune_sb(bdi);
++
++ if (!bdi_cap_flush_forker(bdi))
++ bdi_wb_shutdown(bdi);
++ bdi_debug_unregister(bdi);
++ device_unregister(bdi->dev);
++ bdi->dev = NULL;
++ }
++}
++EXPORT_SYMBOL(bdi_unregister);
++
++int bdi_init(struct backing_dev_info *bdi)
++{
++ int i, err;
++
++ bdi->dev = NULL;
++
++ bdi->min_ratio = 0;
++ bdi->max_ratio = 100;
++ bdi->max_prop_frac = PROP_FRAC_BASE;
++ spin_lock_init(&bdi->wb_lock);
++ INIT_RCU_HEAD(&bdi->rcu_head);
++ INIT_LIST_HEAD(&bdi->bdi_list);
++ INIT_LIST_HEAD(&bdi->wb_list);
++ INIT_LIST_HEAD(&bdi->work_list);
++
++ bdi_wb_init(&bdi->wb, bdi);
++
++ for (i = 0; i < NR_BDI_STAT_ITEMS; i++) {
++ err = percpu_counter_init(&bdi->bdi_stat[i], 0);
++ if (err)
++ goto err;
++ }
++
++ bdi->dirty_exceeded = 0;
++ err = prop_local_init_percpu(&bdi->completions);
++
++ if (err) {
++err:
++ while (i--)
++ percpu_counter_destroy(&bdi->bdi_stat[i]);
++ }
++
++ return err;
++}
++EXPORT_SYMBOL(bdi_init);
++
++void bdi_destroy(struct backing_dev_info *bdi)
++{
++ int i;
++
++ /*
++ * Splice our entries to the default_backing_dev_info, if this
++ * bdi disappears
++ */
++ if (bdi_has_dirty_io(bdi)) {
++ struct bdi_writeback *dst = &default_backing_dev_info.wb;
++
++ spin_lock(&inode_lock);
++ list_splice(&bdi->wb.b_dirty, &dst->b_dirty);
++ list_splice(&bdi->wb.b_io, &dst->b_io);
++ list_splice(&bdi->wb.b_more_io, &dst->b_more_io);
++ spin_unlock(&inode_lock);
++ }
++
++ bdi_unregister(bdi);
++
++ for (i = 0; i < NR_BDI_STAT_ITEMS; i++)
++ percpu_counter_destroy(&bdi->bdi_stat[i]);
++
++ prop_local_destroy_percpu(&bdi->completions);
++}
++EXPORT_SYMBOL(bdi_destroy);
++
++/*
++ * For use from filesystems to quickly init and register a bdi associated
++ * with dirty writeback
++ */
++int bdi_setup_and_register(struct backing_dev_info *bdi, char *name,
++ unsigned int cap)
++{
++ char tmp[32];
++ int err;
++
++ bdi->name = name;
++ bdi->capabilities = cap;
++ err = bdi_init(bdi);
++ if (err)
++ return err;
++
++ sprintf(tmp, "%.28s%s", name, "-%d");
++ err = bdi_register(bdi, NULL, tmp, atomic_long_inc_return(&bdi_seq));
++ if (err) {
++ bdi_destroy(bdi);
++ return err;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL(bdi_setup_and_register);
++
++static wait_queue_head_t congestion_wqh[2] = {
++ __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]),
++ __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1])
++ };
++
++void clear_bdi_congested(struct backing_dev_info *bdi, int sync)
++{
++ enum bdi_state bit;
++ wait_queue_head_t *wqh = &congestion_wqh[sync];
++
++ bit = sync ? BDI_sync_congested : BDI_async_congested;
++ clear_bit(bit, &bdi->state);
++ smp_mb__after_clear_bit();
++ if (waitqueue_active(wqh))
++ wake_up(wqh);
++}
++EXPORT_SYMBOL(clear_bdi_congested);
++
++void set_bdi_congested(struct backing_dev_info *bdi, int sync)
++{
++ enum bdi_state bit;
++
++ bit = sync ? BDI_sync_congested : BDI_async_congested;
++ set_bit(bit, &bdi->state);
++}
++EXPORT_SYMBOL(set_bdi_congested);
++
++/**
++ * congestion_wait - wait for a backing_dev to become uncongested
++ * @sync: SYNC or ASYNC IO
++ * @timeout: timeout in jiffies
++ *
++ * Waits for up to @timeout jiffies for a backing_dev (any backing_dev) to exit
++ * write congestion. If no backing_devs are congested then just wait for the
++ * next write to be completed.
++ */
++long congestion_wait(int sync, long timeout)
++{
++ long ret;
++ DEFINE_WAIT(wait);
++ wait_queue_head_t *wqh = &congestion_wqh[sync];
++
++ prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
++ ret = io_schedule_timeout(timeout);
++ finish_wait(wqh, &wait);
++ return ret;
++}
++EXPORT_SYMBOL(congestion_wait);
++
+diff -rupN linux-2.6.35.11/mm/shmem.c linux-2.6.35.11-ts7500/mm/shmem.c
+--- linux-2.6.35.11/mm/shmem.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/mm/shmem.c 2011-03-14 11:18:24.000000000 -0400
+@@ -2526,21 +2526,27 @@ static struct file_system_type tmpfs_fs_
+ int __init init_tmpfs(void)
+ {
+ int error;
++//printk("Calling bdi_init()\n");
++
+
+ error = bdi_init(&shmem_backing_dev_info);
+ if (error)
+ goto out4;
+
++//printk("Calling init_inodecache()\n");
+ error = init_inodecache();
+ if (error)
+ goto out3;
+
++//printk("Calling register_filesystem()\n");
+ error = register_filesystem(&tmpfs_fs_type);
+ if (error) {
+ printk(KERN_ERR "Could not register tmpfs\n");
+ goto out2;
+ }
+
++//printk("Calling vfs_kern_mount()\n");
++
+ shm_mnt = vfs_kern_mount(&tmpfs_fs_type, MS_NOUSER,
+ tmpfs_fs_type.name, NULL);
+ if (IS_ERR(shm_mnt)) {
+@@ -2548,6 +2554,9 @@ int __init init_tmpfs(void)
+ printk(KERN_ERR "Could not kern_mount tmpfs\n");
+ goto out1;
+ }
++ //printf("init_tmpfs() done OK\n");
++ printk("init_tmpfs() done OK\n");
++
+ return 0;
+
+ out1:
+@@ -2559,6 +2568,9 @@ out3:
+ out4:
+ shm_mnt = ERR_PTR(error);
+ return error;
++
++
++
+ }
+
+ #ifdef CONFIG_CGROUP_MEM_RES_CTLR
+@@ -2621,8 +2633,11 @@ static struct file_system_type tmpfs_fs_
+
+ int __init init_tmpfs(void)
+ {
++//printk("Calling register_filesystem()\n");
++
+ BUG_ON(register_filesystem(&tmpfs_fs_type) != 0);
+
++//printk("Calling kern_mount()\n");
+ shm_mnt = kern_mount(&tmpfs_fs_type);
+ BUG_ON(IS_ERR(shm_mnt));
+
+diff -rupN linux-2.6.35.11/mm/shmem.c.orig linux-2.6.35.11-ts7500/mm/shmem.c.orig
+--- linux-2.6.35.11/mm/shmem.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.11-ts7500/mm/shmem.c.orig 2011-02-06 14:04:07.000000000 -0500
+@@ -0,0 +1,2760 @@
++/*
++ * Resizable virtual memory filesystem for Linux.
++ *
++ * Copyright (C) 2000 Linus Torvalds.
++ * 2000 Transmeta Corp.
++ * 2000-2001 Christoph Rohland
++ * 2000-2001 SAP AG
++ * 2002 Red Hat Inc.
++ * Copyright (C) 2002-2005 Hugh Dickins.
++ * Copyright (C) 2002-2005 VERITAS Software Corporation.
++ * Copyright (C) 2004 Andi Kleen, SuSE Labs
++ *
++ * Extended attribute support for tmpfs:
++ * Copyright (c) 2004, Luke Kenneth Casson Leighton <lkcl at lkcl.net>
++ * Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris at redhat.com>
++ *
++ * tiny-shmem:
++ * Copyright (c) 2004, 2008 Matt Mackall <mpm at selenic.com>
++ *
++ * This file is released under the GPL.
++ */
++
++#include <linux/fs.h>
++#include <linux/init.h>
++#include <linux/vfs.h>
++#include <linux/mount.h>
++#include <linux/pagemap.h>
++#include <linux/file.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/swap.h>
++
++static struct vfsmount *shm_mnt;
++
++#ifdef CONFIG_SHMEM
++/*
++ * This virtual memory filesystem is heavily based on the ramfs. It
++ * extends ramfs by the ability to use swap and honor resource limits
++ * which makes it a completely usable filesystem.
++ */
++
++#include <linux/xattr.h>
++#include <linux/exportfs.h>
++#include <linux/posix_acl.h>
++#include <linux/generic_acl.h>
++#include <linux/mman.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/backing-dev.h>
++#include <linux/shmem_fs.h>
++#include <linux/writeback.h>
++#include <linux/blkdev.h>
++#include <linux/security.h>
++#include <linux/swapops.h>
++#include <linux/mempolicy.h>
++#include <linux/namei.h>
++#include <linux/ctype.h>
++#include <linux/migrate.h>
++#include <linux/highmem.h>
++#include <linux/seq_file.h>
++#include <linux/magic.h>
++
++#include <asm/uaccess.h>
++#include <asm/div64.h>
++#include <asm/pgtable.h>
++
++/*
++ * The maximum size of a shmem/tmpfs file is limited by the maximum size of
++ * its triple-indirect swap vector - see illustration at shmem_swp_entry().
++ *
++ * With 4kB page size, maximum file size is just over 2TB on a 32-bit kernel,
++ * but one eighth of that on a 64-bit kernel. With 8kB page size, maximum
++ * file size is just over 4TB on a 64-bit kernel, but 16TB on a 32-bit kernel,
++ * MAX_LFS_FILESIZE being then more restrictive than swap vector layout.
++ *
++ * We use / and * instead of shifts in the definitions below, so that the swap
++ * vector can be tested with small even values (e.g. 20) for ENTRIES_PER_PAGE.
++ */
++#define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long))
++#define ENTRIES_PER_PAGEPAGE ((unsigned long long)ENTRIES_PER_PAGE*ENTRIES_PER_PAGE)
++
++#define SHMSWP_MAX_INDEX (SHMEM_NR_DIRECT + (ENTRIES_PER_PAGEPAGE/2) * (ENTRIES_PER_PAGE+1))
++#define SHMSWP_MAX_BYTES (SHMSWP_MAX_INDEX << PAGE_CACHE_SHIFT)
++
++#define SHMEM_MAX_BYTES min_t(unsigned long long, SHMSWP_MAX_BYTES, MAX_LFS_FILESIZE)
++#define SHMEM_MAX_INDEX ((unsigned long)((SHMEM_MAX_BYTES+1) >> PAGE_CACHE_SHIFT))
++
++#define BLOCKS_PER_PAGE (PAGE_CACHE_SIZE/512)
++#define VM_ACCT(size) (PAGE_CACHE_ALIGN(size) >> PAGE_SHIFT)
++
++/* info->flags needs VM_flags to handle pagein/truncate races efficiently */
++#define SHMEM_PAGEIN VM_READ
++#define SHMEM_TRUNCATE VM_WRITE
++
++/* Definition to limit shmem_truncate's steps between cond_rescheds */
++#define LATENCY_LIMIT 64
++
++/* Pretend that each entry is of this size in directory's i_size */
++#define BOGO_DIRENT_SIZE 20
++
++/* Flag allocation requirements to shmem_getpage and shmem_swp_alloc */
++enum sgp_type {
++ SGP_READ, /* don't exceed i_size, don't allocate page */
++ SGP_CACHE, /* don't exceed i_size, may allocate page */
++ SGP_DIRTY, /* like SGP_CACHE, but set new page dirty */
++ SGP_WRITE, /* may exceed i_size, may allocate page */
++};
++
++#ifdef CONFIG_TMPFS
++static unsigned long shmem_default_max_blocks(void)
++{
++ return totalram_pages / 2;
++}
++
++static unsigned long shmem_default_max_inodes(void)
++{
++ return min(totalram_pages - totalhigh_pages, totalram_pages / 2);
++}
++#endif
++
++static int shmem_getpage(struct inode *inode, unsigned long idx,
++ struct page **pagep, enum sgp_type sgp, int *type);
++
++static inline struct page *shmem_dir_alloc(gfp_t gfp_mask)
++{
++ /*
++ * The above definition of ENTRIES_PER_PAGE, and the use of
++ * BLOCKS_PER_PAGE on indirect pages, assume PAGE_CACHE_SIZE:
++ * might be reconsidered if it ever diverges from PAGE_SIZE.
++ *
++ * Mobility flags are masked out as swap vectors cannot move
++ */
++ return alloc_pages((gfp_mask & ~GFP_MOVABLE_MASK) | __GFP_ZERO,
++ PAGE_CACHE_SHIFT-PAGE_SHIFT);
++}
++
++static inline void shmem_dir_free(struct page *page)
++{
++ __free_pages(page, PAGE_CACHE_SHIFT-PAGE_SHIFT);
++}
++
++static struct page **shmem_dir_map(struct page *page)
++{
++ return (struct page **)kmap_atomic(page, KM_USER0);
++}
++
++static inline void shmem_dir_unmap(struct page **dir)
++{
++ kunmap_atomic(dir, KM_USER0);
++}
++
++static swp_entry_t *shmem_swp_map(struct page *page)
++{
++ return (swp_entry_t *)kmap_atomic(page, KM_USER1);
++}
++
++static inline void shmem_swp_balance_unmap(void)
++{
++ /*
++ * When passing a pointer to an i_direct entry, to code which
++ * also handles indirect entries and so will shmem_swp_unmap,
++ * we must arrange for the preempt count to remain in balance.
++ * What kmap_atomic of a lowmem page does depends on config
++ * and architecture, so pretend to kmap_atomic some lowmem page.
++ */
++ (void) kmap_atomic(ZERO_PAGE(0), KM_USER1);
++}
++
++static inline void shmem_swp_unmap(swp_entry_t *entry)
++{
++ kunmap_atomic(entry, KM_USER1);
++}
++
++static inline struct shmem_sb_info *SHMEM_SB(struct super_block *sb)
++{
++ return sb->s_fs_info;
++}
++
++/*
++ * shmem_file_setup pre-accounts the whole fixed size of a VM object,
++ * for shared memory and for shared anonymous (/dev/zero) mappings
++ * (unless MAP_NORESERVE and sysctl_overcommit_memory <= 1),
++ * consistent with the pre-accounting of private mappings ...
++ */
++static inline int shmem_acct_size(unsigned long flags, loff_t size)
++{
++ return (flags & VM_NORESERVE) ?
++ 0 : security_vm_enough_memory_kern(VM_ACCT(size));
++}
++
++static inline void shmem_unacct_size(unsigned long flags, loff_t size)
++{
++ if (!(flags & VM_NORESERVE))
++ vm_unacct_memory(VM_ACCT(size));
++}
++
++/*
++ * ... whereas tmpfs objects are accounted incrementally as
++ * pages are allocated, in order to allow huge sparse files.
++ * shmem_getpage reports shmem_acct_block failure as -ENOSPC not -ENOMEM,
++ * so that a failure on a sparse tmpfs mapping will give SIGBUS not OOM.
++ */
++static inline int shmem_acct_block(unsigned long flags)
++{
++ return (flags & VM_NORESERVE) ?
++ security_vm_enough_memory_kern(VM_ACCT(PAGE_CACHE_SIZE)) : 0;
++}
++
++static inline void shmem_unacct_blocks(unsigned long flags, long pages)
++{
++ if (flags & VM_NORESERVE)
++ vm_unacct_memory(pages * VM_ACCT(PAGE_CACHE_SIZE));
++}
++
++static const struct super_operations shmem_ops;
++static const struct address_space_operations shmem_aops;
++static const struct file_operations shmem_file_operations;
++static const struct inode_operations shmem_inode_operations;
++static const struct inode_operations shmem_dir_inode_operations;
++static const struct inode_operations shmem_special_inode_operations;
++static const struct vm_operations_struct shmem_vm_ops;
++
++static struct backing_dev_info shmem_backing_dev_info __read_mostly = {
++ .ra_pages = 0, /* No readahead */
++ .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK | BDI_CAP_SWAP_BACKED,
++ .unplug_io_fn = default_unplug_io_fn,
++};
++
++static LIST_HEAD(shmem_swaplist);
++static DEFINE_MUTEX(shmem_swaplist_mutex);
++
++static void shmem_free_blocks(struct inode *inode, long pages)
++{
++ struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
++ if (sbinfo->max_blocks) {
++ spin_lock(&sbinfo->stat_lock);
++ sbinfo->free_blocks += pages;
++ inode->i_blocks -= pages*BLOCKS_PER_PAGE;
++ spin_unlock(&sbinfo->stat_lock);
++ }
++}
++
++static int shmem_reserve_inode(struct super_block *sb)
++{
++ struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
++ if (sbinfo->max_inodes) {
++ spin_lock(&sbinfo->stat_lock);
++ if (!sbinfo->free_inodes) {
++ spin_unlock(&sbinfo->stat_lock);
++ return -ENOSPC;
++ }
++ sbinfo->free_inodes--;
++ spin_unlock(&sbinfo->stat_lock);
++ }
++ return 0;
++}
++
++static void shmem_free_inode(struct super_block *sb)
++{
++ struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
++ if (sbinfo->max_inodes) {
++ spin_lock(&sbinfo->stat_lock);
++ sbinfo->free_inodes++;
++ spin_unlock(&sbinfo->stat_lock);
++ }
++}
++
++/**
++ * shmem_recalc_inode - recalculate the size of an inode
++ * @inode: inode to recalc
++ *
++ * We have to calculate the free blocks since the mm can drop
++ * undirtied hole pages behind our back.
++ *
++ * But normally info->alloced == inode->i_mapping->nrpages + info->swapped
++ * So mm freed is info->alloced - (inode->i_mapping->nrpages + info->swapped)
++ *
++ * It has to be called with the spinlock held.
++ */
++static void shmem_recalc_inode(struct inode *inode)
++{
++ struct shmem_inode_info *info = SHMEM_I(inode);
++ long freed;
++
++ freed = info->alloced - info->swapped - inode->i_mapping->nrpages;
++ if (freed > 0) {
++ info->alloced -= freed;
++ shmem_unacct_blocks(info->flags, freed);
++ shmem_free_blocks(inode, freed);
++ }
++}
++
++/**
++ * shmem_swp_entry - find the swap vector position in the info structure
++ * @info: info structure for the inode
++ * @index: index of the page to find
++ * @page: optional page to add to the structure. Has to be preset to
++ * all zeros
++ *
++ * If there is no space allocated yet it will return NULL when
++ * page is NULL, else it will use the page for the needed block,
++ * setting it to NULL on return to indicate that it has been used.
++ *
++ * The swap vector is organized the following way:
++ *
++ * There are SHMEM_NR_DIRECT entries directly stored in the
++ * shmem_inode_info structure. So small files do not need an addional
++ * allocation.
++ *
++ * For pages with index > SHMEM_NR_DIRECT there is the pointer
++ * i_indirect which points to a page which holds in the first half
++ * doubly indirect blocks, in the second half triple indirect blocks:
++ *
++ * For an artificial ENTRIES_PER_PAGE = 4 this would lead to the
++ * following layout (for SHMEM_NR_DIRECT == 16):
++ *
++ * i_indirect -> dir --> 16-19
++ * | +-> 20-23
++ * |
++ * +-->dir2 --> 24-27
++ * | +-> 28-31
++ * | +-> 32-35
++ * | +-> 36-39
++ * |
++ * +-->dir3 --> 40-43
++ * +-> 44-47
++ * +-> 48-51
++ * +-> 52-55
++ */
++static swp_entry_t *shmem_swp_entry(struct shmem_inode_info *info, unsigned long index, struct page **page)
++{
++ unsigned long offset;
++ struct page **dir;
++ struct page *subdir;
++
++ if (index < SHMEM_NR_DIRECT) {
++ shmem_swp_balance_unmap();
++ return info->i_direct+index;
++ }
++ if (!info->i_indirect) {
++ if (page) {
++ info->i_indirect = *page;
++ *page = NULL;
++ }
++ return NULL; /* need another page */
++ }
++
++ index -= SHMEM_NR_DIRECT;
++ offset = index % ENTRIES_PER_PAGE;
++ index /= ENTRIES_PER_PAGE;
++ dir = shmem_dir_map(info->i_indirect);
++
++ if (index >= ENTRIES_PER_PAGE/2) {
++ index -= ENTRIES_PER_PAGE/2;
++ dir += ENTRIES_PER_PAGE/2 + index/ENTRIES_PER_PAGE;
++ index %= ENTRIES_PER_PAGE;
++ subdir = *dir;
++ if (!subdir) {
++ if (page) {
++ *dir = *page;
++ *page = NULL;
++ }
++ shmem_dir_unmap(dir);
++ return NULL; /* need another page */
++ }
++ shmem_dir_unmap(dir);
++ dir = shmem_dir_map(subdir);
++ }
++
++ dir += index;
++ subdir = *dir;
++ if (!subdir) {
++ if (!page || !(subdir = *page)) {
++ shmem_dir_unmap(dir);
++ return NULL; /* need a page */
++ }
++ *dir = subdir;
++ *page = NULL;
++ }
++ shmem_dir_unmap(dir);
++ return shmem_swp_map(subdir) + offset;
++}
++
++static void shmem_swp_set(struct shmem_inode_info *info, swp_entry_t *entry, unsigned long value)
++{
++ long incdec = value? 1: -1;
++
++ entry->val = value;
++ info->swapped += incdec;
++ if ((unsigned long)(entry - info->i_direct) >= SHMEM_NR_DIRECT) {
++ struct page *page = kmap_atomic_to_page(entry);
++ set_page_private(page, page_private(page) + incdec);
++ }
++}
++
++/**
++ * shmem_swp_alloc - get the position of the swap entry for the page.
++ * @info: info structure for the inode
++ * @index: index of the page to find
++ * @sgp: check and recheck i_size? skip allocation?
++ *
++ * If the entry does not exist, allocate it.
++ */
++static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info, unsigned long index, enum sgp_type sgp)
++{
++ struct inode *inode = &info->vfs_inode;
++ struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
++ struct page *page = NULL;
++ swp_entry_t *entry;
++
++ if (sgp != SGP_WRITE &&
++ ((loff_t) index << PAGE_CACHE_SHIFT) >= i_size_read(inode))
++ return ERR_PTR(-EINVAL);
++
++ while (!(entry = shmem_swp_entry(info, index, &page))) {
++ if (sgp == SGP_READ)
++ return shmem_swp_map(ZERO_PAGE(0));
++ /*
++ * Test free_blocks against 1 not 0, since we have 1 data
++ * page (and perhaps indirect index pages) yet to allocate:
++ * a waste to allocate index if we cannot allocate data.
++ */
++ if (sbinfo->max_blocks) {
++ spin_lock(&sbinfo->stat_lock);
++ if (sbinfo->free_blocks <= 1) {
++ spin_unlock(&sbinfo->stat_lock);
++ return ERR_PTR(-ENOSPC);
++ }
++ sbinfo->free_blocks--;
++ inode->i_blocks += BLOCKS_PER_PAGE;
++ spin_unlock(&sbinfo->stat_lock);
++ }
++
++ spin_unlock(&info->lock);
++ page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping));
++ spin_lock(&info->lock);
++
++ if (!page) {
++ shmem_free_blocks(inode, 1);
++ return ERR_PTR(-ENOMEM);
++ }
++ if (sgp != SGP_WRITE &&
++ ((loff_t) index << PAGE_CACHE_SHIFT) >= i_size_read(inode)) {
++ entry = ERR_PTR(-EINVAL);
++ break;
++ }
++ if (info->next_index <= index)
++ info->next_index = index + 1;
++ }
++ if (page) {
++ /* another task gave its page, or truncated the file */
++ shmem_free_blocks(inode, 1);
++ shmem_dir_free(page);
++ }
++ if (info->next_index <= index && !IS_ERR(entry))
++ info->next_index = index + 1;
++ return entry;
++}
++
++/**
++ * shmem_free_swp - free some swap entries in a directory
++ * @dir: pointer to the directory
++ * @edir: pointer after last entry of the directory
++ * @punch_lock: pointer to spinlock when needed for the holepunch case
++ */
++static int shmem_free_swp(swp_entry_t *dir, swp_entry_t *edir,
++ spinlock_t *punch_lock)
++{
++ spinlock_t *punch_unlock = NULL;
++ swp_entry_t *ptr;
++ int freed = 0;
++
++ for (ptr = dir; ptr < edir; ptr++) {
++ if (ptr->val) {
++ if (unlikely(punch_lock)) {
++ punch_unlock = punch_lock;
++ punch_lock = NULL;
++ spin_lock(punch_unlock);
++ if (!ptr->val)
++ continue;
++ }
++ free_swap_and_cache(*ptr);
++ *ptr = (swp_entry_t){0};
++ freed++;
++ }
++ }
++ if (punch_unlock)
++ spin_unlock(punch_unlock);
++ return freed;
++}
++
++static int shmem_map_and_free_swp(struct page *subdir, int offset,
++ int limit, struct page ***dir, spinlock_t *punch_lock)
++{
++ swp_entry_t *ptr;
++ int freed = 0;
++
++ ptr = shmem_swp_map(subdir);
++ for (; offset < limit; offset += LATENCY_LIMIT) {
++ int size = limit - offset;
++ if (size > LATENCY_LIMIT)
++ size = LATENCY_LIMIT;
++ freed += shmem_free_swp(ptr+offset, ptr+offset+size,
++ punch_lock);
++ if (need_resched()) {
++ shmem_swp_unmap(ptr);
++ if (*dir) {
++ shmem_dir_unmap(*dir);
++ *dir = NULL;
++ }
++ cond_resched();
++ ptr = shmem_swp_map(subdir);
++ }
++ }
++ shmem_swp_unmap(ptr);
++ return freed;
++}
++
++static void shmem_free_pages(struct list_head *next)
++{
++ struct page *page;
++ int freed = 0;
++
++ do {
++ page = container_of(next, struct page, lru);
++ next = next->next;
++ shmem_dir_free(page);
++ freed++;
++ if (freed >= LATENCY_LIMIT) {
++ cond_resched();
++ freed = 0;
++ }
++ } while (next);
++}
++
++static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end)
++{
++ struct shmem_inode_info *info = SHMEM_I(inode);
++ unsigned long idx;
++ unsigned long size;
++ unsigned long limit;
++ unsigned long stage;
++ unsigned long diroff;
++ struct page **dir;
++ struct page *topdir;
++ struct page *middir;
++ struct page *subdir;
++ swp_entry_t *ptr;
++ LIST_HEAD(pages_to_free);
++ long nr_pages_to_free = 0;
++ long nr_swaps_freed = 0;
++ int offset;
++ int freed;
++ int punch_hole;
++ spinlock_t *needs_lock;
++ spinlock_t *punch_lock;
++ unsigned long upper_limit;
++
++ inode->i_ctime = inode->i_mtime = CURRENT_TIME;
++ idx = (start + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
++ if (idx >= info->next_index)
++ return;
++
++ spin_lock(&info->lock);
++ info->flags |= SHMEM_TRUNCATE;
++ if (likely(end == (loff_t) -1)) {
++ limit = info->next_index;
++ upper_limit = SHMEM_MAX_INDEX;
++ info->next_index = idx;
++ needs_lock = NULL;
++ punch_hole = 0;
++ } else {
++ if (end + 1 >= inode->i_size) { /* we may free a little more */
++ limit = (inode->i_size + PAGE_CACHE_SIZE - 1) >>
++ PAGE_CACHE_SHIFT;
++ upper_limit = SHMEM_MAX_INDEX;
++ } else {
++ limit = (end + 1) >> PAGE_CACHE_SHIFT;
++ upper_limit = limit;
++ }
++ needs_lock = &info->lock;
++ punch_hole = 1;
++ }
++
++ topdir = info->i_indirect;
++ if (topdir && idx <= SHMEM_NR_DIRECT && !punch_hole) {
++ info->i_indirect = NULL;
++ nr_pages_to_free++;
++ list_add(&topdir->lru, &pages_to_free);
++ }
++ spin_unlock(&info->lock);
++
++ if (info->swapped && idx < SHMEM_NR_DIRECT) {
++ ptr = info->i_direct;
++ size = limit;
++ if (size > SHMEM_NR_DIRECT)
++ size = SHMEM_NR_DIRECT;
++ nr_swaps_freed = shmem_free_swp(ptr+idx, ptr+size, needs_lock);
++ }
++
++ /*
++ * If there are no indirect blocks or we are punching a hole
++ * below indirect blocks, nothing to be done.
++ */
++ if (!topdir || limit <= SHMEM_NR_DIRECT)
++ goto done2;
++
++ /*
++ * The truncation case has already dropped info->lock, and we're safe
++ * because i_size and next_index have already been lowered, preventing
++ * access beyond. But in the punch_hole case, we still need to take
++ * the lock when updating the swap directory, because there might be
++ * racing accesses by shmem_getpage(SGP_CACHE), shmem_unuse_inode or
++ * shmem_writepage. However, whenever we find we can remove a whole
++ * directory page (not at the misaligned start or end of the range),
++ * we first NULLify its pointer in the level above, and then have no
++ * need to take the lock when updating its contents: needs_lock and
++ * punch_lock (either pointing to info->lock or NULL) manage this.
++ */
++
++ upper_limit -= SHMEM_NR_DIRECT;
++ limit -= SHMEM_NR_DIRECT;
++ idx = (idx > SHMEM_NR_DIRECT)? (idx - SHMEM_NR_DIRECT): 0;
++ offset = idx % ENTRIES_PER_PAGE;
++ idx -= offset;
++
++ dir = shmem_dir_map(topdir);
++ stage = ENTRIES_PER_PAGEPAGE/2;
++ if (idx < ENTRIES_PER_PAGEPAGE/2) {
++ middir = topdir;
++ diroff = idx/ENTRIES_PER_PAGE;
++ } else {
++ dir += ENTRIES_PER_PAGE/2;
++ dir += (idx - ENTRIES_PER_PAGEPAGE/2)/ENTRIES_PER_PAGEPAGE;
++ while (stage <= idx)
++ stage += ENTRIES_PER_PAGEPAGE;
++ middir = *dir;
++ if (*dir) {
++ diroff = ((idx - ENTRIES_PER_PAGEPAGE/2) %
++ ENTRIES_PER_PAGEPAGE) / ENTRIES_PER_PAGE;
++ if (!diroff && !offset && upper_limit >= stage) {
++ if (needs_lock) {
++ spin_lock(needs_lock);
++ *dir = NULL;
++ spin_unlock(needs_lock);
++ needs_lock = NULL;
++ } else
++ *dir = NULL;
++ nr_pages_to_free++;
++ list_add(&middir->lru, &pages_to_free);
++ }
++ shmem_dir_unmap(dir);
++ dir = shmem_dir_map(middir);
++ } else {
++ diroff = 0;
++ offset = 0;
++ idx = stage;
++ }
++ }
++
++ for (; idx < limit; idx += ENTRIES_PER_PAGE, diroff++) {
++ if (unlikely(idx == stage)) {
++ shmem_dir_unmap(dir);
++ dir = shmem_dir_map(topdir) +
++ ENTRIES_PER_PAGE/2 + idx/ENTRIES_PER_PAGEPAGE;
++ while (!*dir) {
++ dir++;
++ idx += ENTRIES_PER_PAGEPAGE;
++ if (idx >= limit)
++ goto done1;
++ }
++ stage = idx + ENTRIES_PER_PAGEPAGE;
++ middir = *dir;
++ if (punch_hole)
++ needs_lock = &info->lock;
++ if (upper_limit >= stage) {
++ if (needs_lock) {
++ spin_lock(needs_lock);
++ *dir = NULL;
++ spin_unlock(needs_lock);
++ needs_lock = NULL;
++ } else
++ *dir = NULL;
++ nr_pages_to_free++;
++ list_add(&middir->lru, &pages_to_free);
++ }
++ shmem_dir_unmap(dir);
++ cond_resched();
++ dir = shmem_dir_map(middir);
++ diroff = 0;
++ }
++ punch_lock = needs_lock;
++ subdir = dir[diroff];
++ if (subdir && !offset && upper_limit-idx >= ENTRIES_PER_PAGE) {
++ if (needs_lock) {
++ spin_lock(needs_lock);
++ dir[diroff] = NULL;
++ spin_unlock(needs_lock);
++ punch_lock = NULL;
++ } else
++ dir[diroff] = NULL;
++ nr_pages_to_free++;
++ list_add(&subdir->lru, &pages_to_free);
++ }
++ if (subdir && page_private(subdir) /* has swap entries */) {
++ size = limit - idx;
++ if (size > ENTRIES_PER_PAGE)
++ size = ENTRIES_PER_PAGE;
++ freed = shmem_map_and_free_swp(subdir,
++ offset, size, &dir, punch_lock);
++ if (!dir)
++ dir = shmem_dir_map(middir);
++ nr_swaps_freed += freed;
++ if (offset || punch_lock) {
++ spin_lock(&info->lock);
++ set_page_private(subdir,
++ page_private(subdir) - freed);
++ spin_unlock(&info->lock);
++ } else
++ BUG_ON(page_private(subdir) != freed);
++ }
++ offset = 0;
++ }
++done1:
++ shmem_dir_unmap(dir);
++done2:
++ if (inode->i_mapping->nrpages && (info->flags & SHMEM_PAGEIN)) {
++ /*
++ * Call truncate_inode_pages again: racing shmem_unuse_inode
++ * may have swizzled a page in from swap since
++ * truncate_pagecache or generic_delete_inode did it, before we
++ * lowered next_index. Also, though shmem_getpage checks
++ * i_size before adding to cache, no recheck after: so fix the
++ * narrow window there too.
++ *
++ * Recalling truncate_inode_pages_range and unmap_mapping_range
++ * every time for punch_hole (which never got a chance to clear
++ * SHMEM_PAGEIN at the start of vmtruncate_range) is expensive,
++ * yet hardly ever necessary: try to optimize them out later.
++ */
++ truncate_inode_pages_range(inode->i_mapping, start, end);
++ if (punch_hole)
++ unmap_mapping_range(inode->i_mapping, start,
++ end - start, 1);
++ }
++
++ spin_lock(&info->lock);
++ info->flags &= ~SHMEM_TRUNCATE;
++ info->swapped -= nr_swaps_freed;
++ if (nr_pages_to_free)
++ shmem_free_blocks(inode, nr_pages_to_free);
++ shmem_recalc_inode(inode);
++ spin_unlock(&info->lock);
++
++ /*
++ * Empty swap vector directory pages to be freed?
++ */
++ if (!list_empty(&pages_to_free)) {
++ pages_to_free.prev->next = NULL;
++ shmem_free_pages(pages_to_free.next);
++ }
++}
++
++static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
++{
++ struct inode *inode = dentry->d_inode;
++ loff_t newsize = attr->ia_size;
++ int error;
++
++ if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)
++ && newsize != inode->i_size) {
++ struct page *page = NULL;
++
++ if (newsize < inode->i_size) {
++ /*
++ * If truncating down to a partial page, then
++ * if that page is already allocated, hold it
++ * in memory until the truncation is over, so
++ * truncate_partial_page cannnot miss it were
++ * it assigned to swap.
++ */
++ if (newsize & (PAGE_CACHE_SIZE-1)) {
++ (void) shmem_getpage(inode,
++ newsize >> PAGE_CACHE_SHIFT,
++ &page, SGP_READ, NULL);
++ if (page)
++ unlock_page(page);
++ }
++ /*
++ * Reset SHMEM_PAGEIN flag so that shmem_truncate can
++ * detect if any pages might have been added to cache
++ * after truncate_inode_pages. But we needn't bother
++ * if it's being fully truncated to zero-length: the
++ * nrpages check is efficient enough in that case.
++ */
++ if (newsize) {
++ struct shmem_inode_info *info = SHMEM_I(inode);
++ spin_lock(&info->lock);
++ info->flags &= ~SHMEM_PAGEIN;
++ spin_unlock(&info->lock);
++ }
++ }
++
++ error = simple_setsize(inode, newsize);
++ if (page)
++ page_cache_release(page);
++ if (error)
++ return error;
++ shmem_truncate_range(inode, newsize, (loff_t)-1);
++ }
++
++ error = inode_change_ok(inode, attr);
++ if (!error)
++ generic_setattr(inode, attr);
++#ifdef CONFIG_TMPFS_POSIX_ACL
++ if (!error && (attr->ia_valid & ATTR_MODE))
++ error = generic_acl_chmod(inode);
++#endif
++ return error;
++}
++
++static void shmem_delete_inode(struct inode *inode)
++{
++ struct shmem_inode_info *info = SHMEM_I(inode);
++
++ if (inode->i_mapping->a_ops == &shmem_aops) {
++ truncate_inode_pages(inode->i_mapping, 0);
++ shmem_unacct_size(info->flags, inode->i_size);
++ inode->i_size = 0;
++ shmem_truncate_range(inode, 0, (loff_t)-1);
++ if (!list_empty(&info->swaplist)) {
++ mutex_lock(&shmem_swaplist_mutex);
++ list_del_init(&info->swaplist);
++ mutex_unlock(&shmem_swaplist_mutex);
++ }
++ }
++ BUG_ON(inode->i_blocks);
++ shmem_free_inode(inode->i_sb);
++ clear_inode(inode);
++}
++
++static inline int shmem_find_swp(swp_entry_t entry, swp_entry_t *dir, swp_entry_t *edir)
++{
++ swp_entry_t *ptr;
++
++ for (ptr = dir; ptr < edir; ptr++) {
++ if (ptr->val == entry.val)
++ return ptr - dir;
++ }
++ return -1;
++}
++
++static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, struct page *page)
++{
++ struct inode *inode;
++ unsigned long idx;
++ unsigned long size;
++ unsigned long limit;
++ unsigned long stage;
++ struct page **dir;
++ struct page *subdir;
++ swp_entry_t *ptr;
++ int offset;
++ int error;
++
++ idx = 0;
++ ptr = info->i_direct;
++ spin_lock(&info->lock);
++ if (!info->swapped) {
++ list_del_init(&info->swaplist);
++ goto lost2;
++ }
++ limit = info->next_index;
++ size = limit;
++ if (size > SHMEM_NR_DIRECT)
++ size = SHMEM_NR_DIRECT;
++ offset = shmem_find_swp(entry, ptr, ptr+size);
++ if (offset >= 0)
++ goto found;
++ if (!info->i_indirect)
++ goto lost2;
++
++ dir = shmem_dir_map(info->i_indirect);
++ stage = SHMEM_NR_DIRECT + ENTRIES_PER_PAGEPAGE/2;
++
++ for (idx = SHMEM_NR_DIRECT; idx < limit; idx += ENTRIES_PER_PAGE, dir++) {
++ if (unlikely(idx == stage)) {
++ shmem_dir_unmap(dir-1);
++ if (cond_resched_lock(&info->lock)) {
++ /* check it has not been truncated */
++ if (limit > info->next_index) {
++ limit = info->next_index;
++ if (idx >= limit)
++ goto lost2;
++ }
++ }
++ dir = shmem_dir_map(info->i_indirect) +
++ ENTRIES_PER_PAGE/2 + idx/ENTRIES_PER_PAGEPAGE;
++ while (!*dir) {
++ dir++;
++ idx += ENTRIES_PER_PAGEPAGE;
++ if (idx >= limit)
++ goto lost1;
++ }
++ stage = idx + ENTRIES_PER_PAGEPAGE;
++ subdir = *dir;
++ shmem_dir_unmap(dir);
++ dir = shmem_dir_map(subdir);
++ }
++ subdir = *dir;
++ if (subdir && page_private(subdir)) {
++ ptr = shmem_swp_map(subdir);
++ size = limit - idx;
++ if (size > ENTRIES_PER_PAGE)
++ size = ENTRIES_PER_PAGE;
++ offset = shmem_find_swp(entry, ptr, ptr+size);
++ shmem_swp_unmap(ptr);
++ if (offset >= 0) {
++ shmem_dir_unmap(dir);
++ goto found;
++ }
++ }
++ }
++lost1:
++ shmem_dir_unmap(dir-1);
++lost2:
++ spin_unlock(&info->lock);
++ return 0;
++found:
++ idx += offset;
++ inode = igrab(&info->vfs_inode);
++ spin_unlock(&info->lock);
++
++ /*
++ * Move _head_ to start search for next from here.
++ * But be careful: shmem_delete_inode checks list_empty without taking
++ * mutex, and there's an instant in list_move_tail when info->swaplist
++ * would appear empty, if it were the only one on shmem_swaplist. We
++ * could avoid doing it if inode NULL; or use this minor optimization.
++ */
++ if (shmem_swaplist.next != &info->swaplist)
++ list_move_tail(&shmem_swaplist, &info->swaplist);
++ mutex_unlock(&shmem_swaplist_mutex);
++
++ error = 1;
++ if (!inode)
++ goto out;
++ /*
++ * Charge page using GFP_KERNEL while we can wait.
++ * Charged back to the user(not to caller) when swap account is used.
++ * add_to_page_cache() will be called with GFP_NOWAIT.
++ */
++ error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL);
++ if (error)
++ goto out;
++ error = radix_tree_preload(GFP_KERNEL);
++ if (error) {
++ mem_cgroup_uncharge_cache_page(page);
++ goto out;
++ }
++ error = 1;
++
++ spin_lock(&info->lock);
++ ptr = shmem_swp_entry(info, idx, NULL);
++ if (ptr && ptr->val == entry.val) {
++ error = add_to_page_cache_locked(page, inode->i_mapping,
++ idx, GFP_NOWAIT);
++ /* does mem_cgroup_uncharge_cache_page on error */
++ } else /* we must compensate for our precharge above */
++ mem_cgroup_uncharge_cache_page(page);
++
++ if (error == -EEXIST) {
++ struct page *filepage = find_get_page(inode->i_mapping, idx);
++ error = 1;
++ if (filepage) {
++ /*
++ * There might be a more uptodate page coming down
++ * from a stacked writepage: forget our swappage if so.
++ */
++ if (PageUptodate(filepage))
++ error = 0;
++ page_cache_release(filepage);
++ }
++ }
++ if (!error) {
++ delete_from_swap_cache(page);
++ set_page_dirty(page);
++ info->flags |= SHMEM_PAGEIN;
++ shmem_swp_set(info, ptr, 0);
++ swap_free(entry);
++ error = 1; /* not an error, but entry was found */
++ }
++ if (ptr)
++ shmem_swp_unmap(ptr);
++ spin_unlock(&info->lock);
++ radix_tree_preload_end();
++out:
++ unlock_page(page);
++ page_cache_release(page);
++ iput(inode); /* allows for NULL */
++ return error;
++}
++
++/*
++ * shmem_unuse() search for an eventually swapped out shmem page.
++ */
++int shmem_unuse(swp_entry_t entry, struct page *page)
++{
++ struct list_head *p, *next;
++ struct shmem_inode_info *info;
++ int found = 0;
++
++ mutex_lock(&shmem_swaplist_mutex);
++ list_for_each_safe(p, next, &shmem_swaplist) {
++ info = list_entry(p, struct shmem_inode_info, swaplist);
++ found = shmem_unuse_inode(info, entry, page);
++ cond_resched();
++ if (found)
++ goto out;
++ }
++ mutex_unlock(&shmem_swaplist_mutex);
++ /*
++ * Can some race bring us here? We've been holding page lock,
++ * so I think not; but would rather try again later than BUG()
++ */
++ unlock_page(page);
++ page_cache_release(page);
++out:
++ return (found < 0) ? found : 0;
++}
++
++/*
++ * Move the page from the page cache to the swap cache.
++ */
++static int shmem_writepage(struct page *page, struct writeback_control *wbc)
++{
++ struct shmem_inode_info *info;
++ swp_entry_t *entry, swap;
++ struct address_space *mapping;
++ unsigned long index;
++ struct inode *inode;
++
++ BUG_ON(!PageLocked(page));
++ mapping = page->mapping;
++ index = page->index;
++ inode = mapping->host;
++ info = SHMEM_I(inode);
++ if (info->flags & VM_LOCKED)
++ goto redirty;
++ if (!total_swap_pages)
++ goto redirty;
++
++ /*
++ * shmem_backing_dev_info's capabilities prevent regular writeback or
++ * sync from ever calling shmem_writepage; but a stacking filesystem
++ * may use the ->writepage of its underlying filesystem, in which case
++ * tmpfs should write out to swap only in response to memory pressure,
++ * and not for the writeback threads or sync. However, in those cases,
++ * we do still want to check if there's a redundant swappage to be
++ * discarded.
++ */
++ if (wbc->for_reclaim)
++ swap = get_swap_page();
++ else
++ swap.val = 0;
++
++ spin_lock(&info->lock);
++ if (index >= info->next_index) {
++ BUG_ON(!(info->flags & SHMEM_TRUNCATE));
++ goto unlock;
++ }
++ entry = shmem_swp_entry(info, index, NULL);
++ if (entry->val) {
++ /*
++ * The more uptodate page coming down from a stacked
++ * writepage should replace our old swappage.
++ */
++ free_swap_and_cache(*entry);
++ shmem_swp_set(info, entry, 0);
++ }
++ shmem_recalc_inode(inode);
++
++ if (swap.val && add_to_swap_cache(page, swap, GFP_ATOMIC) == 0) {
++ remove_from_page_cache(page);
++ shmem_swp_set(info, entry, swap.val);
++ shmem_swp_unmap(entry);
++ if (list_empty(&info->swaplist))
++ inode = igrab(inode);
++ else
++ inode = NULL;
++ spin_unlock(&info->lock);
++ swap_shmem_alloc(swap);
++ BUG_ON(page_mapped(page));
++ page_cache_release(page); /* pagecache ref */
++ swap_writepage(page, wbc);
++ if (inode) {
++ mutex_lock(&shmem_swaplist_mutex);
++ /* move instead of add in case we're racing */
++ list_move_tail(&info->swaplist, &shmem_swaplist);
++ mutex_unlock(&shmem_swaplist_mutex);
++ iput(inode);
++ }
++ return 0;
++ }
++
++ shmem_swp_unmap(entry);
++unlock:
++ spin_unlock(&info->lock);
++ /*
++ * add_to_swap_cache() doesn't return -EEXIST, so we can safely
++ * clear SWAP_HAS_CACHE flag.
++ */
++ swapcache_free(swap, NULL);
++redirty:
++ set_page_dirty(page);
++ if (wbc->for_reclaim)
++ return AOP_WRITEPAGE_ACTIVATE; /* Return with page locked */
++ unlock_page(page);
++ return 0;
++}
++
++#ifdef CONFIG_NUMA
++#ifdef CONFIG_TMPFS
++static void shmem_show_mpol(struct seq_file *seq, struct mempolicy *mpol)
++{
++ char buffer[64];
++
++ if (!mpol || mpol->mode == MPOL_DEFAULT)
++ return; /* show nothing */
++
++ mpol_to_str(buffer, sizeof(buffer), mpol, 1);
++
++ seq_printf(seq, ",mpol=%s", buffer);
++}
++
++static struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo)
++{
++ struct mempolicy *mpol = NULL;
++ if (sbinfo->mpol) {
++ spin_lock(&sbinfo->stat_lock); /* prevent replace/use races */
++ mpol = sbinfo->mpol;
++ mpol_get(mpol);
++ spin_unlock(&sbinfo->stat_lock);
++ }
++ return mpol;
++}
++#endif /* CONFIG_TMPFS */
++
++static struct page *shmem_swapin(swp_entry_t entry, gfp_t gfp,
++ struct shmem_inode_info *info, unsigned long idx)
++{
++ struct mempolicy mpol, *spol;
++ struct vm_area_struct pvma;
++ struct page *page;
++
++ spol = mpol_cond_copy(&mpol,
++ mpol_shared_policy_lookup(&info->policy, idx));
++
++ /* Create a pseudo vma that just contains the policy */
++ pvma.vm_start = 0;
++ pvma.vm_pgoff = idx;
++ pvma.vm_ops = NULL;
++ pvma.vm_policy = spol;
++ page = swapin_readahead(entry, gfp, &pvma, 0);
++ return page;
++}
++
++static struct page *shmem_alloc_page(gfp_t gfp,
++ struct shmem_inode_info *info, unsigned long idx)
++{
++ struct vm_area_struct pvma;
++
++ /* Create a pseudo vma that just contains the policy */
++ pvma.vm_start = 0;
++ pvma.vm_pgoff = idx;
++ pvma.vm_ops = NULL;
++ pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, idx);
++
++ /*
++ * alloc_page_vma() will drop the shared policy reference
++ */
++ return alloc_page_vma(gfp, &pvma, 0);
++}
++#else /* !CONFIG_NUMA */
++#ifdef CONFIG_TMPFS
++static inline void shmem_show_mpol(struct seq_file *seq, struct mempolicy *p)
++{
++}
++#endif /* CONFIG_TMPFS */
++
++static inline struct page *shmem_swapin(swp_entry_t entry, gfp_t gfp,
++ struct shmem_inode_info *info, unsigned long idx)
++{
++ return swapin_readahead(entry, gfp, NULL, 0);
++}
++
++static inline struct page *shmem_alloc_page(gfp_t gfp,
++ struct shmem_inode_info *info, unsigned long idx)
++{
++ return alloc_page(gfp);
++}
++#endif /* CONFIG_NUMA */
++
++#if !defined(CONFIG_NUMA) || !defined(CONFIG_TMPFS)
++static inline struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo)
++{
++ return NULL;
++}
++#endif
++
++/*
++ * shmem_getpage - either get the page from swap or allocate a new one
++ *
++ * If we allocate a new one we do not mark it dirty. That's up to the
++ * vm. If we swap it in we mark it dirty since we also free the swap
++ * entry since a page cannot live in both the swap and page cache
++ */
++static int shmem_getpage(struct inode *inode, unsigned long idx,
++ struct page **pagep, enum sgp_type sgp, int *type)
++{
++ struct address_space *mapping = inode->i_mapping;
++ struct shmem_inode_info *info = SHMEM_I(inode);
++ struct shmem_sb_info *sbinfo;
++ struct page *filepage = *pagep;
++ struct page *swappage;
++ swp_entry_t *entry;
++ swp_entry_t swap;
++ gfp_t gfp;
++ int error;
++
++ if (idx >= SHMEM_MAX_INDEX)
++ return -EFBIG;
++
++ if (type)
++ *type = 0;
++
++ /*
++ * Normally, filepage is NULL on entry, and either found
++ * uptodate immediately, or allocated and zeroed, or read
++ * in under swappage, which is then assigned to filepage.
++ * But shmem_readpage (required for splice) passes in a locked
++ * filepage, which may be found not uptodate by other callers
++ * too, and may need to be copied from the swappage read in.
++ */
++repeat:
++ if (!filepage)
++ filepage = find_lock_page(mapping, idx);
++ if (filepage && PageUptodate(filepage))
++ goto done;
++ error = 0;
++ gfp = mapping_gfp_mask(mapping);
++ if (!filepage) {
++ /*
++ * Try to preload while we can wait, to not make a habit of
++ * draining atomic reserves; but don't latch on to this cpu.
++ */
++ error = radix_tree_preload(gfp & ~__GFP_HIGHMEM);
++ if (error)
++ goto failed;
++ radix_tree_preload_end();
++ }
++
++ spin_lock(&info->lock);
++ shmem_recalc_inode(inode);
++ entry = shmem_swp_alloc(info, idx, sgp);
++ if (IS_ERR(entry)) {
++ spin_unlock(&info->lock);
++ error = PTR_ERR(entry);
++ goto failed;
++ }
++ swap = *entry;
++
++ if (swap.val) {
++ /* Look it up and read it in.. */
++ swappage = lookup_swap_cache(swap);
++ if (!swappage) {
++ shmem_swp_unmap(entry);
++ /* here we actually do the io */
++ if (type && !(*type & VM_FAULT_MAJOR)) {
++ __count_vm_event(PGMAJFAULT);
++ *type |= VM_FAULT_MAJOR;
++ }
++ spin_unlock(&info->lock);
++ swappage = shmem_swapin(swap, gfp, info, idx);
++ if (!swappage) {
++ spin_lock(&info->lock);
++ entry = shmem_swp_alloc(info, idx, sgp);
++ if (IS_ERR(entry))
++ error = PTR_ERR(entry);
++ else {
++ if (entry->val == swap.val)
++ error = -ENOMEM;
++ shmem_swp_unmap(entry);
++ }
++ spin_unlock(&info->lock);
++ if (error)
++ goto failed;
++ goto repeat;
++ }
++ wait_on_page_locked(swappage);
++ page_cache_release(swappage);
++ goto repeat;
++ }
++
++ /* We have to do this with page locked to prevent races */
++ if (!trylock_page(swappage)) {
++ shmem_swp_unmap(entry);
++ spin_unlock(&info->lock);
++ wait_on_page_locked(swappage);
++ page_cache_release(swappage);
++ goto repeat;
++ }
++ if (PageWriteback(swappage)) {
++ shmem_swp_unmap(entry);
++ spin_unlock(&info->lock);
++ wait_on_page_writeback(swappage);
++ unlock_page(swappage);
++ page_cache_release(swappage);
++ goto repeat;
++ }
++ if (!PageUptodate(swappage)) {
++ shmem_swp_unmap(entry);
++ spin_unlock(&info->lock);
++ unlock_page(swappage);
++ page_cache_release(swappage);
++ error = -EIO;
++ goto failed;
++ }
++
++ if (filepage) {
++ shmem_swp_set(info, entry, 0);
++ shmem_swp_unmap(entry);
++ delete_from_swap_cache(swappage);
++ spin_unlock(&info->lock);
++ copy_highpage(filepage, swappage);
++ unlock_page(swappage);
++ page_cache_release(swappage);
++ flush_dcache_page(filepage);
++ SetPageUptodate(filepage);
++ set_page_dirty(filepage);
++ swap_free(swap);
++ } else if (!(error = add_to_page_cache_locked(swappage, mapping,
++ idx, GFP_NOWAIT))) {
++ info->flags |= SHMEM_PAGEIN;
++ shmem_swp_set(info, entry, 0);
++ shmem_swp_unmap(entry);
++ delete_from_swap_cache(swappage);
++ spin_unlock(&info->lock);
++ filepage = swappage;
++ set_page_dirty(filepage);
++ swap_free(swap);
++ } else {
++ shmem_swp_unmap(entry);
++ spin_unlock(&info->lock);
++ if (error == -ENOMEM) {
++ /*
++ * reclaim from proper memory cgroup and
++ * call memcg's OOM if needed.
++ */
++ error = mem_cgroup_shmem_charge_fallback(
++ swappage,
++ current->mm,
++ gfp);
++ if (error) {
++ unlock_page(swappage);
++ page_cache_release(swappage);
++ goto failed;
++ }
++ }
++ unlock_page(swappage);
++ page_cache_release(swappage);
++ goto repeat;
++ }
++ } else if (sgp == SGP_READ && !filepage) {
++ shmem_swp_unmap(entry);
++ filepage = find_get_page(mapping, idx);
++ if (filepage &&
++ (!PageUptodate(filepage) || !trylock_page(filepage))) {
++ spin_unlock(&info->lock);
++ wait_on_page_locked(filepage);
++ page_cache_release(filepage);
++ filepage = NULL;
++ goto repeat;
++ }
++ spin_unlock(&info->lock);
++ } else {
++ shmem_swp_unmap(entry);
++ sbinfo = SHMEM_SB(inode->i_sb);
++ if (sbinfo->max_blocks) {
++ spin_lock(&sbinfo->stat_lock);
++ if (sbinfo->free_blocks == 0 ||
++ shmem_acct_block(info->flags)) {
++ spin_unlock(&sbinfo->stat_lock);
++ spin_unlock(&info->lock);
++ error = -ENOSPC;
++ goto failed;
++ }
++ sbinfo->free_blocks--;
++ inode->i_blocks += BLOCKS_PER_PAGE;
++ spin_unlock(&sbinfo->stat_lock);
++ } else if (shmem_acct_block(info->flags)) {
++ spin_unlock(&info->lock);
++ error = -ENOSPC;
++ goto failed;
++ }
++
++ if (!filepage) {
++ int ret;
++
++ spin_unlock(&info->lock);
++ filepage = shmem_alloc_page(gfp, info, idx);
++ if (!filepage) {
++ shmem_unacct_blocks(info->flags, 1);
++ shmem_free_blocks(inode, 1);
++ error = -ENOMEM;
++ goto failed;
++ }
++ SetPageSwapBacked(filepage);
++
++ /* Precharge page while we can wait, compensate after */
++ error = mem_cgroup_cache_charge(filepage, current->mm,
++ GFP_KERNEL);
++ if (error) {
++ page_cache_release(filepage);
++ shmem_unacct_blocks(info->flags, 1);
++ shmem_free_blocks(inode, 1);
++ filepage = NULL;
++ goto failed;
++ }
++
++ spin_lock(&info->lock);
++ entry = shmem_swp_alloc(info, idx, sgp);
++ if (IS_ERR(entry))
++ error = PTR_ERR(entry);
++ else {
++ swap = *entry;
++ shmem_swp_unmap(entry);
++ }
++ ret = error || swap.val;
++ if (ret)
++ mem_cgroup_uncharge_cache_page(filepage);
++ else
++ ret = add_to_page_cache_lru(filepage, mapping,
++ idx, GFP_NOWAIT);
++ /*
++ * At add_to_page_cache_lru() failure, uncharge will
++ * be done automatically.
++ */
++ if (ret) {
++ spin_unlock(&info->lock);
++ page_cache_release(filepage);
++ shmem_unacct_blocks(info->flags, 1);
++ shmem_free_blocks(inode, 1);
++ filepage = NULL;
++ if (error)
++ goto failed;
++ goto repeat;
++ }
++ info->flags |= SHMEM_PAGEIN;
++ }
++
++ info->alloced++;
++ spin_unlock(&info->lock);
++ clear_highpage(filepage);
++ flush_dcache_page(filepage);
++ SetPageUptodate(filepage);
++ if (sgp == SGP_DIRTY)
++ set_page_dirty(filepage);
++ }
++done:
++ *pagep = filepage;
++ return 0;
++
++failed:
++ if (*pagep != filepage) {
++ unlock_page(filepage);
++ page_cache_release(filepage);
++ }
++ return error;
++}
++
++static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
++{
++ struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
++ int error;
++ int ret;
++
++ if (((loff_t)vmf->pgoff << PAGE_CACHE_SHIFT) >= i_size_read(inode))
++ return VM_FAULT_SIGBUS;
++
++ error = shmem_getpage(inode, vmf->pgoff, &vmf->page, SGP_CACHE, &ret);
++ if (error)
++ return ((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS);
++
++ return ret | VM_FAULT_LOCKED;
++}
++
++#ifdef CONFIG_NUMA
++static int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
++{
++ struct inode *i = vma->vm_file->f_path.dentry->d_inode;
++ return mpol_set_shared_policy(&SHMEM_I(i)->policy, vma, new);
++}
++
++static struct mempolicy *shmem_get_policy(struct vm_area_struct *vma,
++ unsigned long addr)
++{
++ struct inode *i = vma->vm_file->f_path.dentry->d_inode;
++ unsigned long idx;
++
++ idx = ((addr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
++ return mpol_shared_policy_lookup(&SHMEM_I(i)->policy, idx);
++}
++#endif
++
++int shmem_lock(struct file *file, int lock, struct user_struct *user)
++{
++ struct inode *inode = file->f_path.dentry->d_inode;
++ struct shmem_inode_info *info = SHMEM_I(inode);
++ int retval = -ENOMEM;
++
++ spin_lock(&info->lock);
++ if (lock && !(info->flags & VM_LOCKED)) {
++ if (!user_shm_lock(inode->i_size, user))
++ goto out_nomem;
++ info->flags |= VM_LOCKED;
++ mapping_set_unevictable(file->f_mapping);
++ }
++ if (!lock && (info->flags & VM_LOCKED) && user) {
++ user_shm_unlock(inode->i_size, user);
++ info->flags &= ~VM_LOCKED;
++ mapping_clear_unevictable(file->f_mapping);
++ scan_mapping_unevictable_pages(file->f_mapping);
++ }
++ retval = 0;
++
++out_nomem:
++ spin_unlock(&info->lock);
++ return retval;
++}
++
++static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ file_accessed(file);
++ vma->vm_ops = &shmem_vm_ops;
++ vma->vm_flags |= VM_CAN_NONLINEAR;
++ return 0;
++}
++
++static struct inode *shmem_get_inode(struct super_block *sb, const struct inode *dir,
++ int mode, dev_t dev, unsigned long flags)
++{
++ struct inode *inode;
++ struct shmem_inode_info *info;
++ struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
++
++ if (shmem_reserve_inode(sb))
++ return NULL;
++
++ inode = new_inode(sb);
++ if (inode) {
++ inode_init_owner(inode, dir, mode);
++ inode->i_blocks = 0;
++ inode->i_mapping->backing_dev_info = &shmem_backing_dev_info;
++ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
++ inode->i_generation = get_seconds();
++ info = SHMEM_I(inode);
++ memset(info, 0, (char *)inode - (char *)info);
++ spin_lock_init(&info->lock);
++ info->flags = flags & VM_NORESERVE;
++ INIT_LIST_HEAD(&info->swaplist);
++ cache_no_acl(inode);
++
++ switch (mode & S_IFMT) {
++ default:
++ inode->i_op = &shmem_special_inode_operations;
++ init_special_inode(inode, mode, dev);
++ break;
++ case S_IFREG:
++ inode->i_mapping->a_ops = &shmem_aops;
++ inode->i_op = &shmem_inode_operations;
++ inode->i_fop = &shmem_file_operations;
++ mpol_shared_policy_init(&info->policy,
++ shmem_get_sbmpol(sbinfo));
++ break;
++ case S_IFDIR:
++ inc_nlink(inode);
++ /* Some things misbehave if size == 0 on a directory */
++ inode->i_size = 2 * BOGO_DIRENT_SIZE;
++ inode->i_op = &shmem_dir_inode_operations;
++ inode->i_fop = &simple_dir_operations;
++ break;
++ case S_IFLNK:
++ /*
++ * Must not load anything in the rbtree,
++ * mpol_free_shared_policy will not be called.
++ */
++ mpol_shared_policy_init(&info->policy, NULL);
++ break;
++ }
++ } else
++ shmem_free_inode(sb);
++ return inode;
++}
++
++#ifdef CONFIG_TMPFS
++static const struct inode_operations shmem_symlink_inode_operations;
++static const struct inode_operations shmem_symlink_inline_operations;
++
++/*
++ * Normally tmpfs avoids the use of shmem_readpage and shmem_write_begin;
++ * but providing them allows a tmpfs file to be used for splice, sendfile, and
++ * below the loop driver, in the generic fashion that many filesystems support.
++ */
++static int shmem_readpage(struct file *file, struct page *page)
++{
++ struct inode *inode = page->mapping->host;
++ int error = shmem_getpage(inode, page->index, &page, SGP_CACHE, NULL);
++ unlock_page(page);
++ return error;
++}
++
++static int
++shmem_write_begin(struct file *file, struct address_space *mapping,
++ loff_t pos, unsigned len, unsigned flags,
++ struct page **pagep, void **fsdata)
++{
++ struct inode *inode = mapping->host;
++ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
++ *pagep = NULL;
++ return shmem_getpage(inode, index, pagep, SGP_WRITE, NULL);
++}
++
++static int
++shmem_write_end(struct file *file, struct address_space *mapping,
++ loff_t pos, unsigned len, unsigned copied,
++ struct page *page, void *fsdata)
++{
++ struct inode *inode = mapping->host;
++
++ if (pos + copied > inode->i_size)
++ i_size_write(inode, pos + copied);
++
++ set_page_dirty(page);
++ unlock_page(page);
++ page_cache_release(page);
++
++ return copied;
++}
++
++static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc, read_actor_t actor)
++{
++ struct inode *inode = filp->f_path.dentry->d_inode;
++ struct address_space *mapping = inode->i_mapping;
++ unsigned long index, offset;
++ enum sgp_type sgp = SGP_READ;
++
++ /*
++ * Might this read be for a stacking filesystem? Then when reading
++ * holes of a sparse file, we actually need to allocate those pages,
++ * and even mark them dirty, so it cannot exceed the max_blocks limit.
++ */
++ if (segment_eq(get_fs(), KERNEL_DS))
++ sgp = SGP_DIRTY;
++
++ index = *ppos >> PAGE_CACHE_SHIFT;
++ offset = *ppos & ~PAGE_CACHE_MASK;
++
++ for (;;) {
++ struct page *page = NULL;
++ unsigned long end_index, nr, ret;
++ loff_t i_size = i_size_read(inode);
++
++ end_index = i_size >> PAGE_CACHE_SHIFT;
++ if (index > end_index)
++ break;
++ if (index == end_index) {
++ nr = i_size & ~PAGE_CACHE_MASK;
++ if (nr <= offset)
++ break;
++ }
++
++ desc->error = shmem_getpage(inode, index, &page, sgp, NULL);
++ if (desc->error) {
++ if (desc->error == -EINVAL)
++ desc->error = 0;
++ break;
++ }
++ if (page)
++ unlock_page(page);
++
++ /*
++ * We must evaluate after, since reads (unlike writes)
++ * are called without i_mutex protection against truncate
++ */
++ nr = PAGE_CACHE_SIZE;
++ i_size = i_size_read(inode);
++ end_index = i_size >> PAGE_CACHE_SHIFT;
++ if (index == end_index) {
++ nr = i_size & ~PAGE_CACHE_MASK;
++ if (nr <= offset) {
++ if (page)
++ page_cache_release(page);
++ break;
++ }
++ }
++ nr -= offset;
++
++ if (page) {
++ /*
++ * If users can be writing to this page using arbitrary
++ * virtual addresses, take care about potential aliasing
++ * before reading the page on the kernel side.
++ */
++ if (mapping_writably_mapped(mapping))
++ flush_dcache_page(page);
++ /*
++ * Mark the page accessed if we read the beginning.
++ */
++ if (!offset)
++ mark_page_accessed(page);
++ } else {
++ page = ZERO_PAGE(0);
++ page_cache_get(page);
++ }
++
++ /*
++ * Ok, we have the page, and it's up-to-date, so
++ * now we can copy it to user space...
++ *
++ * The actor routine returns how many bytes were actually used..
++ * NOTE! This may not be the same as how much of a user buffer
++ * we filled up (we may be padding etc), so we can only update
++ * "pos" here (the actor routine has to update the user buffer
++ * pointers and the remaining count).
++ */
++ ret = actor(desc, page, offset, nr);
++ offset += ret;
++ index += offset >> PAGE_CACHE_SHIFT;
++ offset &= ~PAGE_CACHE_MASK;
++
++ page_cache_release(page);
++ if (ret != nr || !desc->count)
++ break;
++
++ cond_resched();
++ }
++
++ *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
++ file_accessed(filp);
++}
++
++static ssize_t shmem_file_aio_read(struct kiocb *iocb,
++ const struct iovec *iov, unsigned long nr_segs, loff_t pos)
++{
++ struct file *filp = iocb->ki_filp;
++ ssize_t retval;
++ unsigned long seg;
++ size_t count;
++ loff_t *ppos = &iocb->ki_pos;
++
++ retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);
++ if (retval)
++ return retval;
++
++ for (seg = 0; seg < nr_segs; seg++) {
++ read_descriptor_t desc;
++
++ desc.written = 0;
++ desc.arg.buf = iov[seg].iov_base;
++ desc.count = iov[seg].iov_len;
++ if (desc.count == 0)
++ continue;
++ desc.error = 0;
++ do_shmem_file_read(filp, ppos, &desc, file_read_actor);
++ retval += desc.written;
++ if (desc.error) {
++ retval = retval ?: desc.error;
++ break;
++ }
++ if (desc.count > 0)
++ break;
++ }
++ return retval;
++}
++
++static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
++{
++ struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb);
++
++ buf->f_type = TMPFS_MAGIC;
++ buf->f_bsize = PAGE_CACHE_SIZE;
++ buf->f_namelen = NAME_MAX;
++ spin_lock(&sbinfo->stat_lock);
++ if (sbinfo->max_blocks) {
++ buf->f_blocks = sbinfo->max_blocks;
++ buf->f_bavail = buf->f_bfree = sbinfo->free_blocks;
++ }
++ if (sbinfo->max_inodes) {
++ buf->f_files = sbinfo->max_inodes;
++ buf->f_ffree = sbinfo->free_inodes;
++ }
++ /* else leave those fields 0 like simple_statfs */
++ spin_unlock(&sbinfo->stat_lock);
++ return 0;
++}
++
++/*
++ * File creation. Allocate an inode, and we're done..
++ */
++static int
++shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
++{
++ struct inode *inode;
++ int error = -ENOSPC;
++
++ inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE);
++ if (inode) {
++ error = security_inode_init_security(inode, dir, NULL, NULL,
++ NULL);
++ if (error) {
++ if (error != -EOPNOTSUPP) {
++ iput(inode);
++ return error;
++ }
++ }
++#ifdef CONFIG_TMPFS_POSIX_ACL
++ error = generic_acl_init(inode, dir);
++ if (error) {
++ iput(inode);
++ return error;
++ }
++#else
++ error = 0;
++#endif
++ dir->i_size += BOGO_DIRENT_SIZE;
++ dir->i_ctime = dir->i_mtime = CURRENT_TIME;
++ d_instantiate(dentry, inode);
++ dget(dentry); /* Extra count - pin the dentry in core */
++ }
++ return error;
++}
++
++static int shmem_mkdir(struct inode *dir, struct dentry *dentry, int mode)
++{
++ int error;
++
++ if ((error = shmem_mknod(dir, dentry, mode | S_IFDIR, 0)))
++ return error;
++ inc_nlink(dir);
++ return 0;
++}
++
++static int shmem_create(struct inode *dir, struct dentry *dentry, int mode,
++ struct nameidata *nd)
++{
++ return shmem_mknod(dir, dentry, mode | S_IFREG, 0);
++}
++
++/*
++ * Link a file..
++ */
++static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
++{
++ struct inode *inode = old_dentry->d_inode;
++ int ret;
++
++ /*
++ * No ordinary (disk based) filesystem counts links as inodes;
++ * but each new link needs a new dentry, pinning lowmem, and
++ * tmpfs dentries cannot be pruned until they are unlinked.
++ */
++ ret = shmem_reserve_inode(inode->i_sb);
++ if (ret)
++ goto out;
++
++ dir->i_size += BOGO_DIRENT_SIZE;
++ inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
++ inc_nlink(inode);
++ atomic_inc(&inode->i_count); /* New dentry reference */
++ dget(dentry); /* Extra pinning count for the created dentry */
++ d_instantiate(dentry, inode);
++out:
++ return ret;
++}
++
++static int shmem_unlink(struct inode *dir, struct dentry *dentry)
++{
++ struct inode *inode = dentry->d_inode;
++
++ if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode))
++ shmem_free_inode(inode->i_sb);
++
++ dir->i_size -= BOGO_DIRENT_SIZE;
++ inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
++ drop_nlink(inode);
++ dput(dentry); /* Undo the count from "create" - this does all the work */
++ return 0;
++}
++
++static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
++{
++ if (!simple_empty(dentry))
++ return -ENOTEMPTY;
++
++ drop_nlink(dentry->d_inode);
++ drop_nlink(dir);
++ return shmem_unlink(dir, dentry);
++}
++
++/*
++ * The VFS layer already does all the dentry stuff for rename,
++ * we just have to decrement the usage count for the target if
++ * it exists so that the VFS layer correctly free's it when it
++ * gets overwritten.
++ */
++static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
++{
++ struct inode *inode = old_dentry->d_inode;
++ int they_are_dirs = S_ISDIR(inode->i_mode);
++
++ if (!simple_empty(new_dentry))
++ return -ENOTEMPTY;
++
++ if (new_dentry->d_inode) {
++ (void) shmem_unlink(new_dir, new_dentry);
++ if (they_are_dirs)
++ drop_nlink(old_dir);
++ } else if (they_are_dirs) {
++ drop_nlink(old_dir);
++ inc_nlink(new_dir);
++ }
++
++ old_dir->i_size -= BOGO_DIRENT_SIZE;
++ new_dir->i_size += BOGO_DIRENT_SIZE;
++ old_dir->i_ctime = old_dir->i_mtime =
++ new_dir->i_ctime = new_dir->i_mtime =
++ inode->i_ctime = CURRENT_TIME;
++ return 0;
++}
++
++static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
++{
++ int error;
++ int len;
++ struct inode *inode;
++ struct page *page = NULL;
++ char *kaddr;
++ struct shmem_inode_info *info;
++
++ len = strlen(symname) + 1;
++ if (len > PAGE_CACHE_SIZE)
++ return -ENAMETOOLONG;
++
++ inode = shmem_get_inode(dir->i_sb, dir, S_IFLNK|S_IRWXUGO, 0, VM_NORESERVE);
++ if (!inode)
++ return -ENOSPC;
++
++ error = security_inode_init_security(inode, dir, NULL, NULL,
++ NULL);
++ if (error) {
++ if (error != -EOPNOTSUPP) {
++ iput(inode);
++ return error;
++ }
++ error = 0;
++ }
++
++ info = SHMEM_I(inode);
++ inode->i_size = len-1;
++ if (len <= (char *)inode - (char *)info) {
++ /* do it inline */
++ memcpy(info, symname, len);
++ inode->i_op = &shmem_symlink_inline_operations;
++ } else {
++ error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL);
++ if (error) {
++ iput(inode);
++ return error;
++ }
++ inode->i_mapping->a_ops = &shmem_aops;
++ inode->i_op = &shmem_symlink_inode_operations;
++ kaddr = kmap_atomic(page, KM_USER0);
++ memcpy(kaddr, symname, len);
++ kunmap_atomic(kaddr, KM_USER0);
++ set_page_dirty(page);
++ unlock_page(page);
++ page_cache_release(page);
++ }
++ dir->i_size += BOGO_DIRENT_SIZE;
++ dir->i_ctime = dir->i_mtime = CURRENT_TIME;
++ d_instantiate(dentry, inode);
++ dget(dentry);
++ return 0;
++}
++
++static void *shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd)
++{
++ nd_set_link(nd, (char *)SHMEM_I(dentry->d_inode));
++ return NULL;
++}
++
++static void *shmem_follow_link(struct dentry *dentry, struct nameidata *nd)
++{
++ struct page *page = NULL;
++ int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL);
++ nd_set_link(nd, res ? ERR_PTR(res) : kmap(page));
++ if (page)
++ unlock_page(page);
++ return page;
++}
++
++static void shmem_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
++{
++ if (!IS_ERR(nd_get_link(nd))) {
++ struct page *page = cookie;
++ kunmap(page);
++ mark_page_accessed(page);
++ page_cache_release(page);
++ }
++}
++
++static const struct inode_operations shmem_symlink_inline_operations = {
++ .readlink = generic_readlink,
++ .follow_link = shmem_follow_link_inline,
++};
++
++static const struct inode_operations shmem_symlink_inode_operations = {
++ .readlink = generic_readlink,
++ .follow_link = shmem_follow_link,
++ .put_link = shmem_put_link,
++};
++
++#ifdef CONFIG_TMPFS_POSIX_ACL
++/*
++ * Superblocks without xattr inode operations will get security.* xattr
++ * support from the VFS "for free". As soon as we have any other xattrs
++ * like ACLs, we also need to implement the security.* handlers at
++ * filesystem level, though.
++ */
++
++static size_t shmem_xattr_security_list(struct dentry *dentry, char *list,
++ size_t list_len, const char *name,
++ size_t name_len, int handler_flags)
++{
++ return security_inode_listsecurity(dentry->d_inode, list, list_len);
++}
++
++static int shmem_xattr_security_get(struct dentry *dentry, const char *name,
++ void *buffer, size_t size, int handler_flags)
++{
++ if (strcmp(name, "") == 0)
++ return -EINVAL;
++ return xattr_getsecurity(dentry->d_inode, name, buffer, size);
++}
++
++static int shmem_xattr_security_set(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags, int handler_flags)
++{
++ if (strcmp(name, "") == 0)
++ return -EINVAL;
++ return security_inode_setsecurity(dentry->d_inode, name, value,
++ size, flags);
++}
++
++static const struct xattr_handler shmem_xattr_security_handler = {
++ .prefix = XATTR_SECURITY_PREFIX,
++ .list = shmem_xattr_security_list,
++ .get = shmem_xattr_security_get,
++ .set = shmem_xattr_security_set,
++};
++
++static const struct xattr_handler *shmem_xattr_handlers[] = {
++ &generic_acl_access_handler,
++ &generic_acl_default_handler,
++ &shmem_xattr_security_handler,
++ NULL
++};
++#endif
++
++static struct dentry *shmem_get_parent(struct dentry *child)
++{
++ return ERR_PTR(-ESTALE);
++}
++
++static int shmem_match(struct inode *ino, void *vfh)
++{
++ __u32 *fh = vfh;
++ __u64 inum = fh[2];
++ inum = (inum << 32) | fh[1];
++ return ino->i_ino == inum && fh[0] == ino->i_generation;
++}
++
++static struct dentry *shmem_fh_to_dentry(struct super_block *sb,
++ struct fid *fid, int fh_len, int fh_type)
++{
++ struct inode *inode;
++ struct dentry *dentry = NULL;
++ u64 inum = fid->raw[2];
++ inum = (inum << 32) | fid->raw[1];
++
++ if (fh_len < 3)
++ return NULL;
++
++ inode = ilookup5(sb, (unsigned long)(inum + fid->raw[0]),
++ shmem_match, fid->raw);
++ if (inode) {
++ dentry = d_find_alias(inode);
++ iput(inode);
++ }
++
++ return dentry;
++}
++
++static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
++ int connectable)
++{
++ struct inode *inode = dentry->d_inode;
++
++ if (*len < 3)
++ return 255;
++
++ if (hlist_unhashed(&inode->i_hash)) {
++ /* Unfortunately insert_inode_hash is not idempotent,
++ * so as we hash inodes here rather than at creation
++ * time, we need a lock to ensure we only try
++ * to do it once
++ */
++ static DEFINE_SPINLOCK(lock);
++ spin_lock(&lock);
++ if (hlist_unhashed(&inode->i_hash))
++ __insert_inode_hash(inode,
++ inode->i_ino + inode->i_generation);
++ spin_unlock(&lock);
++ }
++
++ fh[0] = inode->i_generation;
++ fh[1] = inode->i_ino;
++ fh[2] = ((__u64)inode->i_ino) >> 32;
++
++ *len = 3;
++ return 1;
++}
++
++static const struct export_operations shmem_export_ops = {
++ .get_parent = shmem_get_parent,
++ .encode_fh = shmem_encode_fh,
++ .fh_to_dentry = shmem_fh_to_dentry,
++};
++
++static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo,
++ bool remount)
++{
++ char *this_char, *value, *rest;
++
++ while (options != NULL) {
++ this_char = options;
++ for (;;) {
++ /*
++ * NUL-terminate this option: unfortunately,
++ * mount options form a comma-separated list,
++ * but mpol's nodelist may also contain commas.
++ */
++ options = strchr(options, ',');
++ if (options == NULL)
++ break;
++ options++;
++ if (!isdigit(*options)) {
++ options[-1] = '\0';
++ break;
++ }
++ }
++ if (!*this_char)
++ continue;
++ if ((value = strchr(this_char,'=')) != NULL) {
++ *value++ = 0;
++ } else {
++ printk(KERN_ERR
++ "tmpfs: No value for mount option '%s'\n",
++ this_char);
++ return 1;
++ }
++
++ if (!strcmp(this_char,"size")) {
++ unsigned long long size;
++ size = memparse(value,&rest);
++ if (*rest == '%') {
++ size <<= PAGE_SHIFT;
++ size *= totalram_pages;
++ do_div(size, 100);
++ rest++;
++ }
++ if (*rest)
++ goto bad_val;
++ sbinfo->max_blocks =
++ DIV_ROUND_UP(size, PAGE_CACHE_SIZE);
++ } else if (!strcmp(this_char,"nr_blocks")) {
++ sbinfo->max_blocks = memparse(value, &rest);
++ if (*rest)
++ goto bad_val;
++ } else if (!strcmp(this_char,"nr_inodes")) {
++ sbinfo->max_inodes = memparse(value, &rest);
++ if (*rest)
++ goto bad_val;
++ } else if (!strcmp(this_char,"mode")) {
++ if (remount)
++ continue;
++ sbinfo->mode = simple_strtoul(value, &rest, 8) & 07777;
++ if (*rest)
++ goto bad_val;
++ } else if (!strcmp(this_char,"uid")) {
++ if (remount)
++ continue;
++ sbinfo->uid = simple_strtoul(value, &rest, 0);
++ if (*rest)
++ goto bad_val;
++ } else if (!strcmp(this_char,"gid")) {
++ if (remount)
++ continue;
++ sbinfo->gid = simple_strtoul(value, &rest, 0);
++ if (*rest)
++ goto bad_val;
++ } else if (!strcmp(this_char,"mpol")) {
++ if (mpol_parse_str(value, &sbinfo->mpol, 1))
++ goto bad_val;
++ } else {
++ printk(KERN_ERR "tmpfs: Bad mount option %s\n",
++ this_char);
++ return 1;
++ }
++ }
++ return 0;
++
++bad_val:
++ printk(KERN_ERR "tmpfs: Bad value '%s' for mount option '%s'\n",
++ value, this_char);
++ return 1;
++
++}
++
++static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
++{
++ struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
++ struct shmem_sb_info config = *sbinfo;
++ unsigned long blocks;
++ unsigned long inodes;
++ int error = -EINVAL;
++
++ if (shmem_parse_options(data, &config, true))
++ return error;
++
++ spin_lock(&sbinfo->stat_lock);
++ blocks = sbinfo->max_blocks - sbinfo->free_blocks;
++ inodes = sbinfo->max_inodes - sbinfo->free_inodes;
++ if (config.max_blocks < blocks)
++ goto out;
++ if (config.max_inodes < inodes)
++ goto out;
++ /*
++ * Those tests also disallow limited->unlimited while any are in
++ * use, so i_blocks will always be zero when max_blocks is zero;
++ * but we must separately disallow unlimited->limited, because
++ * in that case we have no record of how much is already in use.
++ */
++ if (config.max_blocks && !sbinfo->max_blocks)
++ goto out;
++ if (config.max_inodes && !sbinfo->max_inodes)
++ goto out;
++
++ error = 0;
++ sbinfo->max_blocks = config.max_blocks;
++ sbinfo->free_blocks = config.max_blocks - blocks;
++ sbinfo->max_inodes = config.max_inodes;
++ sbinfo->free_inodes = config.max_inodes - inodes;
++
++ mpol_put(sbinfo->mpol);
++ sbinfo->mpol = config.mpol; /* transfers initial ref */
++out:
++ spin_unlock(&sbinfo->stat_lock);
++ return error;
++}
++
++static int shmem_show_options(struct seq_file *seq, struct vfsmount *vfs)
++{
++ struct shmem_sb_info *sbinfo = SHMEM_SB(vfs->mnt_sb);
++
++ if (sbinfo->max_blocks != shmem_default_max_blocks())
++ seq_printf(seq, ",size=%luk",
++ sbinfo->max_blocks << (PAGE_CACHE_SHIFT - 10));
++ if (sbinfo->max_inodes != shmem_default_max_inodes())
++ seq_printf(seq, ",nr_inodes=%lu", sbinfo->max_inodes);
++ if (sbinfo->mode != (S_IRWXUGO | S_ISVTX))
++ seq_printf(seq, ",mode=%03o", sbinfo->mode);
++ if (sbinfo->uid != 0)
++ seq_printf(seq, ",uid=%u", sbinfo->uid);
++ if (sbinfo->gid != 0)
++ seq_printf(seq, ",gid=%u", sbinfo->gid);
++ shmem_show_mpol(seq, sbinfo->mpol);
++ return 0;
++}
++#endif /* CONFIG_TMPFS */
++
++static void shmem_put_super(struct super_block *sb)
++{
++ kfree(sb->s_fs_info);
++ sb->s_fs_info = NULL;
++}
++
++int shmem_fill_super(struct super_block *sb, void *data, int silent)
++{
++ struct inode *inode;
++ struct dentry *root;
++ struct shmem_sb_info *sbinfo;
++ int err = -ENOMEM;
++
++ /* Round up to L1_CACHE_BYTES to resist false sharing */
++ sbinfo = kzalloc(max((int)sizeof(struct shmem_sb_info),
++ L1_CACHE_BYTES), GFP_KERNEL);
++ if (!sbinfo)
++ return -ENOMEM;
++
++ sbinfo->mode = S_IRWXUGO | S_ISVTX;
++ sbinfo->uid = current_fsuid();
++ sbinfo->gid = current_fsgid();
++ sb->s_fs_info = sbinfo;
++
++#ifdef CONFIG_TMPFS
++ /*
++ * Per default we only allow half of the physical ram per
++ * tmpfs instance, limiting inodes to one per page of lowmem;
++ * but the internal instance is left unlimited.
++ */
++ if (!(sb->s_flags & MS_NOUSER)) {
++ sbinfo->max_blocks = shmem_default_max_blocks();
++ sbinfo->max_inodes = shmem_default_max_inodes();
++ if (shmem_parse_options(data, sbinfo, false)) {
++ err = -EINVAL;
++ goto failed;
++ }
++ }
++ sb->s_export_op = &shmem_export_ops;
++#else
++ sb->s_flags |= MS_NOUSER;
++#endif
++
++ spin_lock_init(&sbinfo->stat_lock);
++ sbinfo->free_blocks = sbinfo->max_blocks;
++ sbinfo->free_inodes = sbinfo->max_inodes;
++
++ sb->s_maxbytes = SHMEM_MAX_BYTES;
++ sb->s_blocksize = PAGE_CACHE_SIZE;
++ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
++ sb->s_magic = TMPFS_MAGIC;
++ sb->s_op = &shmem_ops;
++ sb->s_time_gran = 1;
++#ifdef CONFIG_TMPFS_POSIX_ACL
++ sb->s_xattr = shmem_xattr_handlers;
++ sb->s_flags |= MS_POSIXACL;
++#endif
++
++ inode = shmem_get_inode(sb, NULL, S_IFDIR | sbinfo->mode, 0, VM_NORESERVE);
++ if (!inode)
++ goto failed;
++ inode->i_uid = sbinfo->uid;
++ inode->i_gid = sbinfo->gid;
++ root = d_alloc_root(inode);
++ if (!root)
++ goto failed_iput;
++ sb->s_root = root;
++ return 0;
++
++failed_iput:
++ iput(inode);
++failed:
++ shmem_put_super(sb);
++ return err;
++}
++
++static struct kmem_cache *shmem_inode_cachep;
++
++static struct inode *shmem_alloc_inode(struct super_block *sb)
++{
++ struct shmem_inode_info *p;
++ p = (struct shmem_inode_info *)kmem_cache_alloc(shmem_inode_cachep, GFP_KERNEL);
++ if (!p)
++ return NULL;
++ return &p->vfs_inode;
++}
++
++static void shmem_destroy_inode(struct inode *inode)
++{
++ if ((inode->i_mode & S_IFMT) == S_IFREG) {
++ /* only struct inode is valid if it's an inline symlink */
++ mpol_free_shared_policy(&SHMEM_I(inode)->policy);
++ }
++ kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
++}
++
++static void init_once(void *foo)
++{
++ struct shmem_inode_info *p = (struct shmem_inode_info *) foo;
++
++ inode_init_once(&p->vfs_inode);
++}
++
++static int init_inodecache(void)
++{
++ shmem_inode_cachep = kmem_cache_create("shmem_inode_cache",
++ sizeof(struct shmem_inode_info),
++ 0, SLAB_PANIC, init_once);
++ return 0;
++}
++
++static void destroy_inodecache(void)
++{
++ kmem_cache_destroy(shmem_inode_cachep);
++}
++
++static const struct address_space_operations shmem_aops = {
++ .writepage = shmem_writepage,
++ .set_page_dirty = __set_page_dirty_no_writeback,
++#ifdef CONFIG_TMPFS
++ .readpage = shmem_readpage,
++ .write_begin = shmem_write_begin,
++ .write_end = shmem_write_end,
++#endif
++ .migratepage = migrate_page,
++ .error_remove_page = generic_error_remove_page,
++};
++
++static const struct file_operations shmem_file_operations = {
++ .mmap = shmem_mmap,
++#ifdef CONFIG_TMPFS
++ .llseek = generic_file_llseek,
++ .read = do_sync_read,
++ .write = do_sync_write,
++ .aio_read = shmem_file_aio_read,
++ .aio_write = generic_file_aio_write,
++ .fsync = noop_fsync,
++ .splice_read = generic_file_splice_read,
++ .splice_write = generic_file_splice_write,
++#endif
++};
++
++static const struct inode_operations shmem_inode_operations = {
++ .setattr = shmem_notify_change,
++ .truncate_range = shmem_truncate_range,
++#ifdef CONFIG_TMPFS_POSIX_ACL
++ .setxattr = generic_setxattr,
++ .getxattr = generic_getxattr,
++ .listxattr = generic_listxattr,
++ .removexattr = generic_removexattr,
++ .check_acl = generic_check_acl,
++#endif
++
++};
++
++static const struct inode_operations shmem_dir_inode_operations = {
++#ifdef CONFIG_TMPFS
++ .create = shmem_create,
++ .lookup = simple_lookup,
++ .link = shmem_link,
++ .unlink = shmem_unlink,
++ .symlink = shmem_symlink,
++ .mkdir = shmem_mkdir,
++ .rmdir = shmem_rmdir,
++ .mknod = shmem_mknod,
++ .rename = shmem_rename,
++#endif
++#ifdef CONFIG_TMPFS_POSIX_ACL
++ .setattr = shmem_notify_change,
++ .setxattr = generic_setxattr,
++ .getxattr = generic_getxattr,
++ .listxattr = generic_listxattr,
++ .removexattr = generic_removexattr,
++ .check_acl = generic_check_acl,
++#endif
++};
++
++static const struct inode_operations shmem_special_inode_operations = {
++#ifdef CONFIG_TMPFS_POSIX_ACL
++ .setattr = shmem_notify_change,
++ .setxattr = generic_setxattr,
++ .getxattr = generic_getxattr,
++ .listxattr = generic_listxattr,
++ .removexattr = generic_removexattr,
++ .check_acl = generic_check_acl,
++#endif
++};
++
++static const struct super_operations shmem_ops = {
++ .alloc_inode = shmem_alloc_inode,
++ .destroy_inode = shmem_destroy_inode,
++#ifdef CONFIG_TMPFS
++ .statfs = shmem_statfs,
++ .remount_fs = shmem_remount_fs,
++ .show_options = shmem_show_options,
++#endif
++ .delete_inode = shmem_delete_inode,
++ .drop_inode = generic_delete_inode,
++ .put_super = shmem_put_super,
++};
++
++static const struct vm_operations_struct shmem_vm_ops = {
++ .fault = shmem_fault,
++#ifdef CONFIG_NUMA
++ .set_policy = shmem_set_policy,
++ .get_policy = shmem_get_policy,
++#endif
++};
++
++
++static int shmem_get_sb(struct file_system_type *fs_type,
++ int flags, const char *dev_name, void *data, struct vfsmount *mnt)
++{
++ return get_sb_nodev(fs_type, flags, data, shmem_fill_super, mnt);
++}
++
++static struct file_system_type tmpfs_fs_type = {
++ .owner = THIS_MODULE,
++ .name = "tmpfs",
++ .get_sb = shmem_get_sb,
++ .kill_sb = kill_litter_super,
++};
++
++int __init init_tmpfs(void)
++{
++ int error;
++
++ error = bdi_init(&shmem_backing_dev_info);
++ if (error)
++ goto out4;
++
++ error = init_inodecache();
++ if (error)
++ goto out3;
++
++ error = register_filesystem(&tmpfs_fs_type);
++ if (error) {
++ printk(KERN_ERR "Could not register tmpfs\n");
++ goto out2;
++ }
++
++ shm_mnt = vfs_kern_mount(&tmpfs_fs_type, MS_NOUSER,
++ tmpfs_fs_type.name, NULL);
++ if (IS_ERR(shm_mnt)) {
++ error = PTR_ERR(shm_mnt);
++ printk(KERN_ERR "Could not kern_mount tmpfs\n");
++ goto out1;
++ }
++ return 0;
++
++out1:
++ unregister_filesystem(&tmpfs_fs_type);
++out2:
++ destroy_inodecache();
++out3:
++ bdi_destroy(&shmem_backing_dev_info);
++out4:
++ shm_mnt = ERR_PTR(error);
++ return error;
++}
++
++#ifdef CONFIG_CGROUP_MEM_RES_CTLR
++/**
++ * mem_cgroup_get_shmem_target - find a page or entry assigned to the shmem file
++ * @inode: the inode to be searched
++ * @pgoff: the offset to be searched
++ * @pagep: the pointer for the found page to be stored
++ * @ent: the pointer for the found swap entry to be stored
++ *
++ * If a page is found, refcount of it is incremented. Callers should handle
++ * these refcount.
++ */
++void mem_cgroup_get_shmem_target(struct inode *inode, pgoff_t pgoff,
++ struct page **pagep, swp_entry_t *ent)
++{
++ swp_entry_t entry = { .val = 0 }, *ptr;
++ struct page *page = NULL;
++ struct shmem_inode_info *info = SHMEM_I(inode);
++
++ if ((pgoff << PAGE_CACHE_SHIFT) >= i_size_read(inode))
++ goto out;
++
++ spin_lock(&info->lock);
++ ptr = shmem_swp_entry(info, pgoff, NULL);
++#ifdef CONFIG_SWAP
++ if (ptr && ptr->val) {
++ entry.val = ptr->val;
++ page = find_get_page(&swapper_space, entry.val);
++ } else
++#endif
++ page = find_get_page(inode->i_mapping, pgoff);
++ if (ptr)
++ shmem_swp_unmap(ptr);
++ spin_unlock(&info->lock);
++out:
++ *pagep = page;
++ *ent = entry;
++}
++#endif
++
++#else /* !CONFIG_SHMEM */
++
++/*
++ * tiny-shmem: simple shmemfs and tmpfs using ramfs code
++ *
++ * This is intended for small system where the benefits of the full
++ * shmem code (swap-backed and resource-limited) are outweighed by
++ * their complexity. On systems without swap this code should be
++ * effectively equivalent, but much lighter weight.
++ */
++
++#include <linux/ramfs.h>
++
++static struct file_system_type tmpfs_fs_type = {
++ .name = "tmpfs",
++ .get_sb = ramfs_get_sb,
++ .kill_sb = kill_litter_super,
++};
++
++int __init init_tmpfs(void)
++{
++ BUG_ON(register_filesystem(&tmpfs_fs_type) != 0);
++
++ shm_mnt = kern_mount(&tmpfs_fs_type);
++ BUG_ON(IS_ERR(shm_mnt));
++
++ return 0;
++}
++
++int shmem_unuse(swp_entry_t entry, struct page *page)
++{
++ return 0;
++}
++
++int shmem_lock(struct file *file, int lock, struct user_struct *user)
++{
++ return 0;
++}
++
++#ifdef CONFIG_CGROUP_MEM_RES_CTLR
++/**
++ * mem_cgroup_get_shmem_target - find a page or entry assigned to the shmem file
++ * @inode: the inode to be searched
++ * @pgoff: the offset to be searched
++ * @pagep: the pointer for the found page to be stored
++ * @ent: the pointer for the found swap entry to be stored
++ *
++ * If a page is found, refcount of it is incremented. Callers should handle
++ * these refcount.
++ */
++void mem_cgroup_get_shmem_target(struct inode *inode, pgoff_t pgoff,
++ struct page **pagep, swp_entry_t *ent)
++{
++ struct page *page = NULL;
++
++ if ((pgoff << PAGE_CACHE_SHIFT) >= i_size_read(inode))
++ goto out;
++ page = find_get_page(inode->i_mapping, pgoff);
++out:
++ *pagep = page;
++ *ent = (swp_entry_t){ .val = 0 };
++}
++#endif
++
++#define shmem_vm_ops generic_file_vm_ops
++#define shmem_file_operations ramfs_file_operations
++#define shmem_get_inode(sb, dir, mode, dev, flags) ramfs_get_inode(sb, dir, mode, dev)
++#define shmem_acct_size(flags, size) 0
++#define shmem_unacct_size(flags, size) do {} while (0)
++#define SHMEM_MAX_BYTES MAX_LFS_FILESIZE
++
++#endif /* CONFIG_SHMEM */
++
++/* common code */
++
++/**
++ * shmem_file_setup - get an unlinked file living in tmpfs
++ * @name: name for dentry (to be seen in /proc/<pid>/maps
++ * @size: size to be set for the file
++ * @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
++ */
++struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags)
++{
++ int error;
++ struct file *file;
++ struct inode *inode;
++ struct path path;
++ struct dentry *root;
++ struct qstr this;
++
++ if (IS_ERR(shm_mnt))
++ return (void *)shm_mnt;
++
++ if (size < 0 || size > SHMEM_MAX_BYTES)
++ return ERR_PTR(-EINVAL);
++
++ if (shmem_acct_size(flags, size))
++ return ERR_PTR(-ENOMEM);
++
++ error = -ENOMEM;
++ this.name = name;
++ this.len = strlen(name);
++ this.hash = 0; /* will go */
++ root = shm_mnt->mnt_root;
++ path.dentry = d_alloc(root, &this);
++ if (!path.dentry)
++ goto put_memory;
++ path.mnt = mntget(shm_mnt);
++
++ error = -ENOSPC;
++ inode = shmem_get_inode(root->d_sb, NULL, S_IFREG | S_IRWXUGO, 0, flags);
++ if (!inode)
++ goto put_dentry;
++
++ d_instantiate(path.dentry, inode);
++ inode->i_size = size;
++ inode->i_nlink = 0; /* It is unlinked */
++#ifndef CONFIG_MMU
++ error = ramfs_nommu_expand_for_mapping(inode, size);
++ if (error)
++ goto put_dentry;
++#endif
++
++ error = -ENFILE;
++ file = alloc_file(&path, FMODE_WRITE | FMODE_READ,
++ &shmem_file_operations);
++ if (!file)
++ goto put_dentry;
++
++ return file;
++
++put_dentry:
++ path_put(&path);
++put_memory:
++ shmem_unacct_size(flags, size);
++ return ERR_PTR(error);
++}
++EXPORT_SYMBOL_GPL(shmem_file_setup);
++
++/**
++ * shmem_zero_setup - setup a shared anonymous mapping
++ * @vma: the vma to be mmapped is prepared by do_mmap_pgoff
++ */
++int shmem_zero_setup(struct vm_area_struct *vma)
++{
++ struct file *file;
++ loff_t size = vma->vm_end - vma->vm_start;
++
++ file = shmem_file_setup("dev/zero", size, vma->vm_flags);
++ if (IS_ERR(file))
++ return PTR_ERR(file);
++
++ if (vma->vm_file)
++ fput(vma->vm_file);
++ vma->vm_file = file;
++ vma->vm_ops = &shmem_vm_ops;
++ return 0;
++}
+diff -rupN linux-2.6.35.11/mm/swap.c linux-2.6.35.11-ts7500/mm/swap.c
+--- linux-2.6.35.11/mm/swap.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/mm/swap.c 2011-03-14 11:18:24.000000000 -0400
+@@ -500,6 +500,8 @@ void __init swap_setup(void)
+ {
+ unsigned long megs = totalram_pages >> (20 - PAGE_SHIFT);
+
++ //printk("swap_setup(), calling bdi_init()\n");
++
+ #ifdef CONFIG_SWAP
+ bdi_init(swapper_space.backing_dev_info);
+ #endif
+diff -rupN linux-2.6.35.11/net/bridge/Kconfig linux-2.6.35.11-ts7500/net/bridge/Kconfig
+--- linux-2.6.35.11/net/bridge/Kconfig 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/net/bridge/Kconfig 2011-03-14 11:18:24.000000000 -0400
+@@ -32,6 +32,17 @@ config BRIDGE
+
+ If unsure, say N.
+
++if BRIDGE
++config BRIDGE_ID_POLICY_MINIMUM
++ bool "Bridge ID select policy - minimum"
++ default n
++ help
++ The policy to choose bridge ID. If you say Y, the bridge would choose
++ the minimum bridge port ID as it's ID. This feature will affect PCI
++ fastpath function of Star's STR9100 series.
++
++endif
++
+ config BRIDGE_IGMP_SNOOPING
+ bool "IGMP/MLD snooping"
+ depends on BRIDGE
+diff -rupN linux-2.6.35.11/net/core/net_namespace.c linux-2.6.35.11-ts7500/net/core/net_namespace.c
+--- linux-2.6.35.11/net/core/net_namespace.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/net/core/net_namespace.c 2011-03-14 11:18:24.000000000 -0400
+@@ -346,6 +346,7 @@ static int __init net_ns_init(void)
+ struct net_generic *ng;
+
+ #ifdef CONFIG_NET_NS
++ printk(KERN_INFO "net_namespace: %zd bytes\n", sizeof(struct net));
+ net_cachep = kmem_cache_create("net_namespace", sizeof(struct net),
+ SMP_CACHE_BYTES,
+ SLAB_PANIC, NULL);
+diff -rupN linux-2.6.35.11/security/min_addr.c linux-2.6.35.11-ts7500/security/min_addr.c
+--- linux-2.6.35.11/security/min_addr.c 2011-02-06 14:04:07.000000000 -0500
++++ linux-2.6.35.11-ts7500/security/min_addr.c 2011-03-14 11:18:24.000000000 -0400
+@@ -14,6 +14,7 @@ unsigned long dac_mmap_min_addr = CONFIG
+ */
+ static void update_mmap_min_addr(void)
+ {
++
+ #ifdef CONFIG_LSM_MMAP_MIN_ADDR
+ if (dac_mmap_min_addr > CONFIG_LSM_MMAP_MIN_ADDR)
+ mmap_min_addr = dac_mmap_min_addr;
+@@ -22,6 +23,7 @@ static void update_mmap_min_addr(void)
+ #else
+ mmap_min_addr = dac_mmap_min_addr;
+ #endif
++
+ }
+
+ /*
+@@ -45,8 +47,9 @@ int mmap_min_addr_handler(struct ctl_tab
+
+ static int __init init_mmap_min_addr(void)
+ {
++
+ update_mmap_min_addr();
+-
++
+ return 0;
+ }
+ pure_initcall(init_mmap_min_addr);
diff --git a/recipes/linux/linux-ts75xx-2.6.35/ts75xx/unionfs-2.5.8_for_2.6.35.11.patch b/recipes/linux/linux-ts75xx-2.6.35/ts75xx/unionfs-2.5.8_for_2.6.35.11.patch
new file mode 100644
index 0000000..4ea03ac
--- /dev/null
+++ b/recipes/linux/linux-ts75xx-2.6.35/ts75xx/unionfs-2.5.8_for_2.6.35.11.patch
@@ -0,0 +1,11286 @@
+diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
+index 4303614..5ade4a8 100644
+--- a/Documentation/filesystems/00-INDEX
++++ b/Documentation/filesystems/00-INDEX
+@@ -112,6 +112,8 @@ udf.txt
+ - info and mount options for the UDF filesystem.
+ ufs.txt
+ - info on the ufs filesystem.
++unionfs/
++ - info on the unionfs filesystem
+ vfat.txt
+ - info on using the VFAT filesystem used in Windows NT and Windows 95
+ vfs.txt
+diff --git a/Documentation/filesystems/unionfs/00-INDEX b/Documentation/filesystems/unionfs/00-INDEX
+new file mode 100644
+index 0000000..96fdf67
+--- /dev/null
++++ b/Documentation/filesystems/unionfs/00-INDEX
+@@ -0,0 +1,10 @@
++00-INDEX
++ - this file.
++concepts.txt
++ - A brief introduction of concepts.
++issues.txt
++ - A summary of known issues with unionfs.
++rename.txt
++ - Information regarding rename operations.
++usage.txt
++ - Usage information and examples.
+diff --git a/Documentation/filesystems/unionfs/concepts.txt b/Documentation/filesystems/unionfs/concepts.txt
+new file mode 100644
+index 0000000..b853788
+--- /dev/null
++++ b/Documentation/filesystems/unionfs/concepts.txt
+@@ -0,0 +1,287 @@
++Unionfs 2.x CONCEPTS:
++=====================
++
++This file describes the concepts needed by a namespace unification file
++system.
++
++
++Branch Priority:
++================
++
++Each branch is assigned a unique priority - starting from 0 (highest
++priority). No two branches can have the same priority.
++
++
++Branch Mode:
++============
++
++Each branch is assigned a mode - read-write or read-only. This allows
++directories on media mounted read-write to be used in a read-only manner.
++
++
++Whiteouts:
++==========
++
++A whiteout removes a file name from the namespace. Whiteouts are needed when
++one attempts to remove a file on a read-only branch.
++
++Suppose we have a two-branch union, where branch 0 is read-write and branch
++1 is read-only. And a file 'foo' on branch 1:
++
++./b0/
++./b1/
++./b1/foo
++
++The unified view would simply be:
++
++./union/
++./union/foo
++
++Since 'foo' is stored on a read-only branch, it cannot be removed. A
++whiteout is used to remove the name 'foo' from the unified namespace. Again,
++since branch 1 is read-only, the whiteout cannot be created there. So, we
++try on a higher priority (lower numerically) branch and create the whiteout
++there.
++
++./b0/
++./b0/.wh.foo
++./b1/
++./b1/foo
++
++Later, when Unionfs traverses branches (due to lookup or readdir), it
++eliminate 'foo' from the namespace (as well as the whiteout itself.)
++
++
++Opaque Directories:
++===================
++
++Assume we have a unionfs mount comprising of two branches. Branch 0 is
++empty; branch 1 has the directory /a and file /a/f. Let's say we mount a
++union of branch 0 as read-write and branch 1 as read-only. Now, let's say
++we try to perform the following operation in the union:
++
++ rm -fr a
++
++Because branch 1 is not writable, we cannot physically remove the file /a/f
++or the directory /a. So instead, we will create a whiteout in branch 0
++named /.wh.a, masking out the name "a" from branch 1. Next, let's say we
++try to create a directory named "a" as follows:
++
++ mkdir a
++
++Because we have a whiteout for "a" already, Unionfs behaves as if "a"
++doesn't exist, and thus will delete the whiteout and replace it with an
++actual directory named "a".
++
++The problem now is that if you try to "ls" in the union, Unionfs will
++perform is normal directory name unification, for *all* directories named
++"a" in all branches. This will cause the file /a/f from branch 1 to
++re-appear in the union's namespace, which violates Unix semantics.
++
++To avoid this problem, we have a different form of whiteouts for
++directories, called "opaque directories" (same as BSD Union Mount does).
++Whenever we replace a whiteout with a directory, that directory is marked as
++opaque. In Unionfs 2.x, it means that we create a file named
++/a/.wh.__dir_opaque in branch 0, after having created directory /a there.
++When unionfs notices that a directory is opaque, it stops all namespace
++operations (including merging readdir contents) at that opaque directory.
++This prevents re-exposing names from masked out directories.
++
++
++Duplicate Elimination:
++======================
++
++It is possible for files on different branches to have the same name.
++Unionfs then has to select which instance of the file to show to the user.
++Given the fact that each branch has a priority associated with it, the
++simplest solution is to take the instance from the highest priority
++(numerically lowest value) and "hide" the others.
++
++
++Unlinking:
++=========
++
++Unlink operation on non-directory instances is optimized to remove the
++maximum possible objects in case multiple underlying branches have the same
++file name. The unlink operation will first try to delete file instances
++from highest priority branch and then move further to delete from remaining
++branches in order of their decreasing priority. Consider a case (F..D..F),
++where F is a file and D is a directory of the same name; here, some
++intermediate branch could have an empty directory instance with the same
++name, so this operation also tries to delete this directory instance and
++proceed further to delete from next possible lower priority branch. The
++unionfs unlink operation will smoothly delete the files with same name from
++all possible underlying branches. In case if some error occurs, it creates
++whiteout in highest priority branch that will hide file instance in rest of
++the branches. An error could occur either if an unlink operations in any of
++the underlying branch failed or if a branch has no write permission.
++
++This unlinking policy is known as "delete all" and it has the benefit of
++overall reducing the number of inodes used by duplicate files, and further
++reducing the total number of inodes consumed by whiteouts. The cost is of
++extra processing, but testing shows this extra processing is well worth the
++savings.
++
++
++Copyup:
++=======
++
++When a change is made to the contents of a file's data or meta-data, they
++have to be stored somewhere. The best way is to create a copy of the
++original file on a branch that is writable, and then redirect the write
++though to this copy. The copy must be made on a higher priority branch so
++that lookup and readdir return this newer "version" of the file rather than
++the original (see duplicate elimination).
++
++An entire unionfs mount can be read-only or read-write. If it's read-only,
++then none of the branches will be written to, even if some of the branches
++are physically writeable. If the unionfs mount is read-write, then the
++leftmost (highest priority) branch must be writeable (for copyup to take
++place); the remaining branches can be any mix of read-write and read-only.
++
++In a writeable mount, unionfs will create new files/dir in the leftmost
++branch. If one tries to modify a file in a read-only branch/media, unionfs
++will copyup the file to the leftmost branch and modify it there. If you try
++to modify a file from a writeable branch which is not the leftmost branch,
++then unionfs will modify it in that branch; this is useful if you, say,
++unify differnet packages (e.g., apache, sendmail, ftpd, etc.) and you want
++changes to specific package files to remain logically in the directory where
++they came from.
++
++Cache Coherency:
++================
++
++Unionfs users often want to be able to modify files and directories directly
++on the lower branches, and have those changes be visible at the Unionfs
++level. This means that data (e.g., pages) and meta-data (dentries, inodes,
++open files, etc.) have to be synchronized between the upper and lower
++layers. In other words, the newest changes from a layer below have to be
++propagated to the Unionfs layer above. If the two layers are not in sync, a
++cache incoherency ensues, which could lead to application failures and even
++oopses. The Linux kernel, however, has a rather limited set of mechanisms
++to ensure this inter-layer cache coherency---so Unionfs has to do most of
++the hard work on its own.
++
++Maintaining Invariants:
++
++The way Unionfs ensures cache coherency is as follows. At each entry point
++to a Unionfs file system method, we call a utility function to validate the
++primary objects of this method. Generally, we call unionfs_file_revalidate
++on open files, and __unionfs_d_revalidate_chain on dentries (which also
++validates inodes). These utility functions check to see whether the upper
++Unionfs object is in sync with any of the lower objects that it represents.
++The checks we perform include whether the Unionfs superblock has a newer
++generation number, or if any of the lower objects mtime's or ctime's are
++newer. (Note: generation numbers change when branch-management commands are
++issued, so in a way, maintaining cache coherency is also very important for
++branch-management.) If indeed we determine that any Unionfs object is no
++longer in sync with its lower counterparts, then we rebuild that object
++similarly to how we do so for branch-management.
++
++While rebuilding Unionfs's objects, we also purge any page mappings and
++truncate inode pages (see fs/unionfs/dentry.c:purge_inode_data). This is to
++ensure that Unionfs will re-get the newer data from the lower branches. We
++perform this purging only if the Unionfs operation in question is a reading
++operation; if Unionfs is performing a data writing operation (e.g., ->write,
++->commit_write, etc.) then we do NOT flush the lower mappings/pages: this is
++because (1) a self-deadlock could occur and (2) the upper Unionfs pages are
++considered more authoritative anyway, as they are newer and will overwrite
++any lower pages.
++
++Unionfs maintains the following important invariant regarding mtime's,
++ctime's, and atime's: the upper inode object's times are the max() of all of
++the lower ones. For non-directory objects, there's only one object below,
++so the mapping is simple; for directory objects, there could me multiple
++lower objects and we have to sync up with the newest one of all the lower
++ones. This invariant is important to maintain, especially for directories
++(besides, we need this to be POSIX compliant). A union could comprise
++multiple writable branches, each of which could change. If we don't reflect
++the newest possible mtime/ctime, some applications could fail. For example,
++NFSv2/v3 exports check for newer directory mtimes on the server to determine
++if the client-side attribute cache should be purged.
++
++To maintain these important invariants, of course, Unionfs carefully
++synchronizes upper and lower times in various places. For example, if we
++copy-up a file to a top-level branch, the parent directory where the file
++was copied up to will now have a new mtime: so after a successful copy-up,
++we sync up with the new top-level branch's parent directory mtime.
++
++Implementation:
++
++This cache-coherency implementation is efficient because it defers any
++synchronizing between the upper and lower layers until absolutely needed.
++Consider the example a common situation where users perform a lot of lower
++changes, such as untarring a whole package. While these take place,
++typically the user doesn't access the files via Unionfs; only after the
++lower changes are done, does the user try to access the lower files. With
++our cache-coherency implementation, the entirety of the changes to the lower
++branches will not result in a single CPU cycle spent at the Unionfs level
++until the user invokes a system call that goes through Unionfs.
++
++We have considered two alternate cache-coherency designs. (1) Using the
++dentry/inode notify functionality to register interest in finding out about
++any lower changes. This is a somewhat limited and also a heavy-handed
++approach which could result in many notifications to the Unionfs layer upon
++each small change at the lower layer (imagine a file being modified multiple
++times in rapid succession). (2) Rewriting the VFS to support explicit
++callbacks from lower objects to upper objects. We began exploring such an
++implementation, but found it to be very complicated--it would have resulted
++in massive VFS/MM changes which are unlikely to be accepted by the LKML
++community. We therefore believe that our current cache-coherency design and
++implementation represent the best approach at this time.
++
++Limitations:
++
++Our implementation works in that as long as a user process will have caused
++Unionfs to be called, directly or indirectly, even to just do
++->d_revalidate; then we will have purged the current Unionfs data and the
++process will see the new data. For example, a process that continually
++re-reads the same file's data will see the NEW data as soon as the lower
++file had changed, upon the next read(2) syscall (even if the file is still
++open!) However, this doesn't work when the process re-reads the open file's
++data via mmap(2) (unless the user unmaps/closes the file and remaps/reopens
++it). Once we respond to ->readpage(s), then the kernel maps the page into
++the process's address space and there doesn't appear to be a way to force
++the kernel to invalidate those pages/mappings, and force the process to
++re-issue ->readpage. If there's a way to invalidate active mappings and
++force a ->readpage, let us know please (invalidate_inode_pages2 doesn't do
++the trick).
++
++Our current Unionfs code has to perform many file-revalidation calls. It
++would be really nice if the VFS would export an optional file system hook
++->file_revalidate (similarly to dentry->d_revalidate) that will be called
++before each VFS op that has a "struct file" in it.
++
++Certain file systems have micro-second granularity (or better) for inode
++times, and asynchronous actions could cause those times to change with some
++small delay. In such cases, Unionfs may see a changed inode time that only
++differs by a tiny fraction of a second: such a change may be a false
++positive indication that the lower object has changed, whereas if unionfs
++waits a little longer, that false indication will not be seen. (These false
++positives are harmless, because they would at most cause unionfs to
++re-validate an object that may need no revalidation, and print a debugging
++message that clutters the console/logs.) Therefore, to minimize the chances
++of these situations, we delay the detection of changed times by a small
++factor of a few seconds, called UNIONFS_MIN_CC_TIME (which defaults to 3
++seconds, as does NFS). This means that we will detect the change, only a
++couple of seconds later, if indeed the time change persists in the lower
++file object. This delayed detection has an added performance benefit: we
++reduce the number of times that unionfs has to revalidate objects, in case
++there's a lot of concurrent activity on both the upper and lower objects,
++for the same file(s). Lastly, this delayed time attribute detection is
++similar to how NFS clients operate (e.g., acregmin).
++
++Finally, there is no way currently in Linux to prevent lower directories
++from being moved around (i.e., topology changes); there's no way to prevent
++modifications to directory sub-trees of whole file systems which are mounted
++read-write. It is therefore possible for in-flight operations in unionfs to
++take place, while a lower directory is being moved around. Therefore, if
++you try to, say, create a new file in a directory through unionfs, while the
++directory is being moved around directly, then the new file may get created
++in the new location where that directory was moved to. This is a somewhat
++similar behaviour in NFS: an NFS client could be creating a new file while
++th NFS server is moving th directory around; the file will get successfully
++created in the new location. (The one exception in unionfs is that if the
++branch is marked read-only by unionfs, then a copyup will take place.)
++
++For more information, see <http://unionfs.filesystems.org/>.
+diff --git a/Documentation/filesystems/unionfs/issues.txt b/Documentation/filesystems/unionfs/issues.txt
+new file mode 100644
+index 0000000..f4b7e7e
+--- /dev/null
++++ b/Documentation/filesystems/unionfs/issues.txt
+@@ -0,0 +1,28 @@
++KNOWN Unionfs 2.x ISSUES:
++=========================
++
++1. Unionfs should not use lookup_one_len() on the underlying f/s as it
++ confuses NFSv4. Currently, unionfs_lookup() passes lookup intents to the
++ lower file-system, this eliminates part of the problem. The remaining
++ calls to lookup_one_len may need to be changed to pass an intent. We are
++ currently introducing VFS changes to fs/namei.c's do_path_lookup() to
++ allow proper file lookup and opening in stackable file systems.
++
++2. Lockdep (a debugging feature) isn't aware of stacking, and so it
++ incorrectly complains about locking problems. The problem boils down to
++ this: Lockdep considers all objects of a certain type to be in the same
++ class, for example, all inodes. Lockdep doesn't like to see a lock held
++ on two inodes within the same task, and warns that it could lead to a
++ deadlock. However, stackable file systems do precisely that: they lock
++ an upper object, and then a lower object, in a strict order to avoid
++ locking problems; in addition, Unionfs, as a fan-out file system, may
++ have to lock several lower inodes. We are currently looking into Lockdep
++ to see how to make it aware of stackable file systems. For now, we
++ temporarily disable lockdep when calling vfs methods on lower objects,
++ but only for those places where lockdep complained. While this solution
++ may seem unclean, it is not without precedent: other places in the kernel
++ also do similar temporary disabling, of course after carefully having
++ checked that it is the right thing to do. Anyway, you get any warnings
++ from Lockdep, please report them to the Unionfs maintainers.
++
++For more information, see <http://unionfs.filesystems.org/>.
+diff --git a/Documentation/filesystems/unionfs/rename.txt b/Documentation/filesystems/unionfs/rename.txt
+new file mode 100644
+index 0000000..e20bb82
+--- /dev/null
++++ b/Documentation/filesystems/unionfs/rename.txt
+@@ -0,0 +1,31 @@
++Rename is a complex beast. The following table shows which rename(2) operations
++should succeed and which should fail.
++
++o: success
++E: error (either unionfs or vfs)
++X: EXDEV
++
++none = file does not exist
++file = file is a file
++dir = file is a empty directory
++child= file is a non-empty directory
++wh = file is a directory containing only whiteouts; this makes it logically
++ empty
++
++ none file dir child wh
++file o o E E E
++dir o E o E o
++child X E X E X
++wh o E o E o
++
++
++Renaming directories:
++=====================
++
++Whenever a empty (either physically or logically) directory is being renamed,
++the following sequence of events should take place:
++
++1) Remove whiteouts from both source and destination directory
++2) Rename source to destination
++3) Make destination opaque to prevent anything under it from showing up
++
+diff --git a/Documentation/filesystems/unionfs/usage.txt b/Documentation/filesystems/unionfs/usage.txt
+new file mode 100644
+index 0000000..1adde69
+--- /dev/null
++++ b/Documentation/filesystems/unionfs/usage.txt
+@@ -0,0 +1,134 @@
++Unionfs is a stackable unification file system, which can appear to merge
++the contents of several directories (branches), while keeping their physical
++content separate. Unionfs is useful for unified source tree management,
++merged contents of split CD-ROM, merged separate software package
++directories, data grids, and more. Unionfs allows any mix of read-only and
++read-write branches, as well as insertion and deletion of branches anywhere
++in the fan-out. To maintain Unix semantics, Unionfs handles elimination of
++duplicates, partial-error conditions, and more.
++
++GENERAL SYNTAX
++==============
++
++# mount -t unionfs -o <OPTIONS>,<BRANCH-OPTIONS> none MOUNTPOINT
++
++OPTIONS can be any legal combination of:
++
++- ro # mount file system read-only
++- rw # mount file system read-write
++- remount # remount the file system (see Branch Management below)
++- incgen # increment generation no. (see Cache Consistency below)
++
++BRANCH-OPTIONS can be either (1) a list of branches given to the "dirs="
++option, or (2) a list of individual branch manipulation commands, combined
++with the "remount" option, and is further described in the "Branch
++Management" section below.
++
++The syntax for the "dirs=" mount option is:
++
++ dirs=branch[=ro|=rw][:...]
++
++The "dirs=" option takes a colon-delimited list of directories to compose
++the union, with an optional branch mode for each of those directories.
++Directories that come earlier (specified first, on the left) in the list
++have a higher precedence than those which come later. Additionally,
++read-only or read-write permissions of the branch can be specified by
++appending =ro or =rw (default) to each directory. See the Copyup section in
++concepts.txt, for a description of Unionfs's behavior when mixing read-only
++and read-write branches and mounts.
++
++Syntax:
++
++ dirs=/branch1[=ro|=rw]:/branch2[=ro|=rw]:...:/branchN[=ro|=rw]
++
++Example:
++
++ dirs=/writable_branch=rw:/read-only_branch=ro
++
++
++BRANCH MANAGEMENT
++=================
++
++Once you mount your union for the first time, using the "dirs=" option, you
++can then change the union's overall mode or reconfigure the branches, using
++the remount option, as follows.
++
++To downgrade a union from read-write to read-only:
++
++# mount -t unionfs -o remount,ro none MOUNTPOINT
++
++To upgrade a union from read-only to read-write:
++
++# mount -t unionfs -o remount,rw none MOUNTPOINT
++
++To delete a branch /foo, regardless where it is in the current union:
++
++# mount -t unionfs -o remount,del=/foo none MOUNTPOINT
++
++To insert (add) a branch /foo before /bar:
++
++# mount -t unionfs -o remount,add=/bar:/foo none MOUNTPOINT
++
++To insert (add) a branch /foo (with the "rw" mode flag) before /bar:
++
++# mount -t unionfs -o remount,add=/bar:/foo=rw none MOUNTPOINT
++
++To insert (add) a branch /foo (in "rw" mode) at the very beginning (i.e., a
++new highest-priority branch), you can use the above syntax, or use a short
++hand version as follows:
++
++# mount -t unionfs -o remount,add=/foo none MOUNTPOINT
++
++To append a branch to the very end (new lowest-priority branch):
++
++# mount -t unionfs -o remount,add=:/foo none MOUNTPOINT
++
++To append a branch to the very end (new lowest-priority branch), in
++read-only mode:
++
++# mount -t unionfs -o remount,add=:/foo=ro none MOUNTPOINT
++
++Finally, to change the mode of one existing branch, say /foo, from read-only
++to read-write, and change /bar from read-write to read-only:
++
++# mount -t unionfs -o remount,mode=/foo=rw,mode=/bar=ro none MOUNTPOINT
++
++Note: in Unionfs 2.x, you cannot set the leftmost branch to readonly because
++then Unionfs won't have any writable place for copyups to take place.
++Moreover, the VFS can get confused when it tries to modify something in a
++file system mounted read-write, but isn't permitted to write to it.
++Instead, you should set the whole union as readonly, as described above.
++If, however, you must set the leftmost branch as readonly, perhaps so you
++can get a snapshot of it at a point in time, then you should insert a new
++writable top-level branch, and mark the one you want as readonly. This can
++be accomplished as follows, assuming that /foo is your current leftmost
++branch:
++
++# mount -t tmpfs -o size=NNN /new
++# mount -t unionfs -o remount,add=/new,mode=/foo=ro none MOUNTPOINT
++<do what you want safely in /foo>
++# mount -t unionfs -o remount,del=/new,mode=/foo=rw none MOUNTPOINT
++<check if there's anything in /new you want to preserve>
++# umount /new
++
++CACHE CONSISTENCY
++=================
++
++If you modify any file on any of the lower branches directly, while there is
++a Unionfs 2.x mounted above any of those branches, you should tell Unionfs
++to purge its caches and re-get the objects. To do that, you have to
++increment the generation number of the superblock using the following
++command:
++
++# mount -t unionfs -o remount,incgen none MOUNTPOINT
++
++Note that the older way of incrementing the generation number using an
++ioctl, is no longer supported in Unionfs 2.0 and newer. Ioctls in general
++are not encouraged. Plus, an ioctl is per-file concept, whereas the
++generation number is a per-file-system concept. Worse, such an ioctl
++requires an open file, which then has to be invalidated by the very nature
++of the generation number increase (read: the old generation increase ioctl
++was pretty racy).
++
++
++For more information, see <http://unionfs.filesystems.org/>.
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 02f75fc..8c5efe7 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -5766,6 +5766,14 @@ F: Documentation/cdrom/
+ F: drivers/cdrom/cdrom.c
+ F: include/linux/cdrom.h
+
++UNIONFS
++P: Erez Zadok
++M: ezk at cs.sunysb.edu
++L: unionfs at filesystems.org
++W: http://unionfs.filesystems.org/
++T: git git.kernel.org/pub/scm/linux/kernel/git/ezk/unionfs.git
++S: Maintained
++
+ UNSORTED BLOCK IMAGES (UBI)
+ M: Artem Bityutskiy <dedekind1 at gmail.com>
+ W: http://www.linux-mtd.infradead.org/
+diff --git a/fs/Kconfig b/fs/Kconfig
+index 5f85b59..7b4501b 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -169,6 +169,7 @@ if MISC_FILESYSTEMS
+ source "fs/adfs/Kconfig"
+ source "fs/affs/Kconfig"
+ source "fs/ecryptfs/Kconfig"
++source "fs/unionfs/Kconfig"
+ source "fs/hfs/Kconfig"
+ source "fs/hfsplus/Kconfig"
+ source "fs/befs/Kconfig"
+diff --git a/fs/Makefile b/fs/Makefile
+index e6ec1d3..787332e 100644
+--- a/fs/Makefile
++++ b/fs/Makefile
+@@ -84,6 +84,7 @@ obj-$(CONFIG_ISO9660_FS) += isofs/
+ obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+
+ obj-$(CONFIG_HFS_FS) += hfs/
+ obj-$(CONFIG_ECRYPT_FS) += ecryptfs/
++obj-$(CONFIG_UNION_FS) += unionfs/
+ obj-$(CONFIG_VXFS_FS) += freevxfs/
+ obj-$(CONFIG_NFS_FS) += nfs/
+ obj-$(CONFIG_EXPORTFS) += exportfs/
+diff --git a/fs/namei.c b/fs/namei.c
+index 868d0cb..b5e09e1 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -386,6 +386,7 @@ void release_open_intent(struct nameidata *nd)
+ else
+ fput(nd->intent.open.file);
+ }
++EXPORT_SYMBOL_GPL(release_open_intent);
+
+ static inline struct dentry *
+ do_revalidate(struct dentry *dentry, struct nameidata *nd)
+diff --git a/fs/splice.c b/fs/splice.c
+index efdbfec..1ff6bca 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -1104,8 +1104,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
+ /*
+ * Attempt to initiate a splice from pipe to file.
+ */
+-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+- loff_t *ppos, size_t len, unsigned int flags)
++long vfs_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags)
+ {
+ ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
+ loff_t *, size_t, unsigned int);
+@@ -1128,13 +1128,14 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+
+ return splice_write(pipe, out, ppos, len, flags);
+ }
++EXPORT_SYMBOL_GPL(vfs_splice_from);
+
+ /*
+ * Attempt to initiate a splice from a file to a pipe.
+ */
+-static long do_splice_to(struct file *in, loff_t *ppos,
+- struct pipe_inode_info *pipe, size_t len,
+- unsigned int flags)
++long vfs_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags)
+ {
+ ssize_t (*splice_read)(struct file *, loff_t *,
+ struct pipe_inode_info *, size_t, unsigned int);
+@@ -1154,6 +1155,7 @@ static long do_splice_to(struct file *in, loff_t *ppos,
+
+ return splice_read(in, ppos, pipe, len, flags);
+ }
++EXPORT_SYMBOL_GPL(vfs_splice_to);
+
+ /**
+ * splice_direct_to_actor - splices data directly between two non-pipes
+@@ -1223,7 +1225,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
+ size_t read_len;
+ loff_t pos = sd->pos, prev_pos = pos;
+
+- ret = do_splice_to(in, &pos, pipe, len, flags);
++ ret = vfs_splice_to(in, &pos, pipe, len, flags);
+ if (unlikely(ret <= 0))
+ goto out_release;
+
+@@ -1282,8 +1284,8 @@ static int direct_splice_actor(struct pipe_inode_info *pipe,
+ {
+ struct file *file = sd->u.file;
+
+- return do_splice_from(pipe, file, &file->f_pos, sd->total_len,
+- sd->flags);
++ return vfs_splice_from(pipe, file, &file->f_pos, sd->total_len,
++ sd->flags);
+ }
+
+ /**
+@@ -1380,7 +1382,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
+ } else
+ off = &out->f_pos;
+
+- ret = do_splice_from(ipipe, out, off, len, flags);
++ ret = vfs_splice_from(ipipe, out, off, len, flags);
+
+ if (off_out && copy_to_user(off_out, off, sizeof(loff_t)))
+ ret = -EFAULT;
+@@ -1400,7 +1402,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
+ } else
+ off = &in->f_pos;
+
+- ret = do_splice_to(in, off, opipe, len, flags);
++ ret = vfs_splice_to(in, off, opipe, len, flags);
+
+ if (off_in && copy_to_user(off_in, off, sizeof(loff_t)))
+ ret = -EFAULT;
+diff --git a/fs/stack.c b/fs/stack.c
+index 4a6f7f4..7eeef12 100644
+--- a/fs/stack.c
++++ b/fs/stack.c
+@@ -1,8 +1,20 @@
++/*
++ * Copyright (c) 2006-2009 Erez Zadok
++ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2006-2009 Stony Brook University
++ * Copyright (c) 2006-2009 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
+ #include <linux/module.h>
+ #include <linux/fs.h>
+ #include <linux/fs_stack.h>
+
+-/* does _NOT_ require i_mutex to be held.
++/*
++ * does _NOT_ require i_mutex to be held.
+ *
+ * This function cannot be inlined since i_size_{read,write} is rather
+ * heavy-weight on 32-bit systems
+diff --git a/fs/unionfs/Kconfig b/fs/unionfs/Kconfig
+new file mode 100644
+index 0000000..f3c1ac4
+--- /dev/null
++++ b/fs/unionfs/Kconfig
+@@ -0,0 +1,24 @@
++config UNION_FS
++ tristate "Union file system (EXPERIMENTAL)"
++ depends on EXPERIMENTAL
++ help
++ Unionfs is a stackable unification file system, which appears to
++ merge the contents of several directories (branches), while keeping
++ their physical content separate.
++
++ See <http://unionfs.filesystems.org> for details
++
++config UNION_FS_XATTR
++ bool "Unionfs extended attributes"
++ depends on UNION_FS
++ help
++ Extended attributes are name:value pairs associated with inodes by
++ the kernel or by users (see the attr(5) manual page).
++
++ If unsure, say N.
++
++config UNION_FS_DEBUG
++ bool "Debug Unionfs"
++ depends on UNION_FS
++ help
++ If you say Y here, you can turn on debugging output from Unionfs.
+diff --git a/fs/unionfs/Makefile b/fs/unionfs/Makefile
+new file mode 100644
+index 0000000..7f8c980
+--- /dev/null
++++ b/fs/unionfs/Makefile
+@@ -0,0 +1,17 @@
++UNIONFS_VERSION="2.5.8 (for 2.6.35.9)"
++
++EXTRA_CFLAGS += -DUNIONFS_VERSION=\"$(UNIONFS_VERSION)\"
++
++obj-$(CONFIG_UNION_FS) += unionfs.o
++
++unionfs-y := subr.o dentry.o file.o inode.o main.o super.o \
++ rdstate.o copyup.o dirhelper.o rename.o unlink.o \
++ lookup.o commonfops.o dirfops.o sioq.o mmap.o whiteout.o
++
++unionfs-$(CONFIG_UNION_FS_XATTR) += xattr.o
++
++unionfs-$(CONFIG_UNION_FS_DEBUG) += debug.o
++
++ifeq ($(CONFIG_UNION_FS_DEBUG),y)
++EXTRA_CFLAGS += -DDEBUG
++endif
+diff --git a/fs/unionfs/commonfops.c b/fs/unionfs/commonfops.c
+new file mode 100644
+index 0000000..740c4ad
+--- /dev/null
++++ b/fs/unionfs/commonfops.c
+@@ -0,0 +1,896 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++/*
++ * 1) Copyup the file
++ * 2) Rename the file to '.unionfs<original inode#><counter>' - obviously
++ * stolen from NFS's silly rename
++ */
++static int copyup_deleted_file(struct file *file, struct dentry *dentry,
++ struct dentry *parent, int bstart, int bindex)
++{
++ static unsigned int counter;
++ const int i_inosize = sizeof(dentry->d_inode->i_ino) * 2;
++ const int countersize = sizeof(counter) * 2;
++ const int nlen = sizeof(".unionfs") + i_inosize + countersize - 1;
++ char name[nlen + 1];
++ int err;
++ struct dentry *tmp_dentry = NULL;
++ struct dentry *lower_dentry;
++ struct dentry *lower_dir_dentry = NULL;
++
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bstart);
++
++ sprintf(name, ".unionfs%*.*lx",
++ i_inosize, i_inosize, lower_dentry->d_inode->i_ino);
++
++ /*
++ * Loop, looking for an unused temp name to copyup to.
++ *
++ * It's somewhat silly that we look for a free temp tmp name in the
++ * source branch (bstart) instead of the dest branch (bindex), where
++ * the final name will be created. We _will_ catch it if somehow
++ * the name exists in the dest branch, but it'd be nice to catch it
++ * sooner than later.
++ */
++retry:
++ tmp_dentry = NULL;
++ do {
++ char *suffix = name + nlen - countersize;
++
++ dput(tmp_dentry);
++ counter++;
++ sprintf(suffix, "%*.*x", countersize, countersize, counter);
++
++ pr_debug("unionfs: trying to rename %s to %s\n",
++ dentry->d_name.name, name);
++
++ tmp_dentry = lookup_lck_len(name, lower_dentry->d_parent,
++ nlen);
++ if (IS_ERR(tmp_dentry)) {
++ err = PTR_ERR(tmp_dentry);
++ goto out;
++ }
++ } while (tmp_dentry->d_inode != NULL); /* need negative dentry */
++ dput(tmp_dentry);
++
++ err = copyup_named_file(parent->d_inode, file, name, bstart, bindex,
++ i_size_read(file->f_path.dentry->d_inode));
++ if (err) {
++ if (unlikely(err == -EEXIST))
++ goto retry;
++ goto out;
++ }
++
++ /* bring it to the same state as an unlinked file */
++ lower_dentry = unionfs_lower_dentry_idx(dentry, dbstart(dentry));
++ if (!unionfs_lower_inode_idx(dentry->d_inode, bindex)) {
++ atomic_inc(&lower_dentry->d_inode->i_count);
++ unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
++ lower_dentry->d_inode);
++ }
++ lower_dir_dentry = lock_parent(lower_dentry);
++ err = vfs_unlink(lower_dir_dentry->d_inode, lower_dentry);
++ unlock_dir(lower_dir_dentry);
++
++out:
++ if (!err)
++ unionfs_check_dentry(dentry);
++ return err;
++}
++
++/*
++ * put all references held by upper struct file and free lower file pointer
++ * array
++ */
++static void cleanup_file(struct file *file)
++{
++ int bindex, bstart, bend;
++ struct file **lower_files;
++ struct file *lower_file;
++ struct super_block *sb = file->f_path.dentry->d_sb;
++
++ lower_files = UNIONFS_F(file)->lower_files;
++ bstart = fbstart(file);
++ bend = fbend(file);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ int i; /* holds (possibly) updated branch index */
++ int old_bid;
++
++ lower_file = unionfs_lower_file_idx(file, bindex);
++ if (!lower_file)
++ continue;
++
++ /*
++ * Find new index of matching branch with an open
++ * file, since branches could have been added or
++ * deleted causing the one with open files to shift.
++ */
++ old_bid = UNIONFS_F(file)->saved_branch_ids[bindex];
++ i = branch_id_to_idx(sb, old_bid);
++ if (unlikely(i < 0)) {
++ printk(KERN_ERR "unionfs: no superblock for "
++ "file %p\n", file);
++ continue;
++ }
++
++ /* decrement count of open files */
++ branchput(sb, i);
++ /*
++ * fput will perform an mntput for us on the correct branch.
++ * Although we're using the file's old branch configuration,
++ * bindex, which is the old index, correctly points to the
++ * right branch in the file's branch list. In other words,
++ * we're going to mntput the correct branch even if branches
++ * have been added/removed.
++ */
++ fput(lower_file);
++ UNIONFS_F(file)->lower_files[bindex] = NULL;
++ UNIONFS_F(file)->saved_branch_ids[bindex] = -1;
++ }
++
++ UNIONFS_F(file)->lower_files = NULL;
++ kfree(lower_files);
++ kfree(UNIONFS_F(file)->saved_branch_ids);
++ /* set to NULL because caller needs to know if to kfree on error */
++ UNIONFS_F(file)->saved_branch_ids = NULL;
++}
++
++/* open all lower files for a given file */
++static int open_all_files(struct file *file)
++{
++ int bindex, bstart, bend, err = 0;
++ struct file *lower_file;
++ struct dentry *lower_dentry;
++ struct dentry *dentry = file->f_path.dentry;
++ struct super_block *sb = dentry->d_sb;
++
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry)
++ continue;
++
++ dget(lower_dentry);
++ unionfs_mntget(dentry, bindex);
++ branchget(sb, bindex);
++
++ lower_file =
++ dentry_open(lower_dentry,
++ unionfs_lower_mnt_idx(dentry, bindex),
++ file->f_flags, current_cred());
++ if (IS_ERR(lower_file)) {
++ branchput(sb, bindex);
++ err = PTR_ERR(lower_file);
++ goto out;
++ } else {
++ unionfs_set_lower_file_idx(file, bindex, lower_file);
++ }
++ }
++out:
++ return err;
++}
++
++/* open the highest priority file for a given upper file */
++static int open_highest_file(struct file *file, bool willwrite)
++{
++ int bindex, bstart, bend, err = 0;
++ struct file *lower_file;
++ struct dentry *lower_dentry;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent = dget_parent(dentry);
++ struct inode *parent_inode = parent->d_inode;
++ struct super_block *sb = dentry->d_sb;
++
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++ if (willwrite && IS_WRITE_FLAG(file->f_flags) && is_robranch(dentry)) {
++ for (bindex = bstart - 1; bindex >= 0; bindex--) {
++ err = copyup_file(parent_inode, file, bstart, bindex,
++ i_size_read(dentry->d_inode));
++ if (!err)
++ break;
++ }
++ atomic_set(&UNIONFS_F(file)->generation,
++ atomic_read(&UNIONFS_I(dentry->d_inode)->
++ generation));
++ goto out;
++ }
++
++ dget(lower_dentry);
++ unionfs_mntget(dentry, bstart);
++ lower_file = dentry_open(lower_dentry,
++ unionfs_lower_mnt_idx(dentry, bstart),
++ file->f_flags, current_cred());
++ if (IS_ERR(lower_file)) {
++ err = PTR_ERR(lower_file);
++ goto out;
++ }
++ branchget(sb, bstart);
++ unionfs_set_lower_file(file, lower_file);
++ /* Fix up the position. */
++ lower_file->f_pos = file->f_pos;
++
++ memcpy(&lower_file->f_ra, &file->f_ra, sizeof(struct file_ra_state));
++out:
++ dput(parent);
++ return err;
++}
++
++/* perform a delayed copyup of a read-write file on a read-only branch */
++static int do_delayed_copyup(struct file *file, struct dentry *parent)
++{
++ int bindex, bstart, bend, err = 0;
++ struct dentry *dentry = file->f_path.dentry;
++ struct inode *parent_inode = parent->d_inode;
++
++ bstart = fbstart(file);
++ bend = fbend(file);
++
++ BUG_ON(!S_ISREG(dentry->d_inode->i_mode));
++
++ unionfs_check_file(file);
++ for (bindex = bstart - 1; bindex >= 0; bindex--) {
++ if (!d_deleted(dentry))
++ err = copyup_file(parent_inode, file, bstart,
++ bindex,
++ i_size_read(dentry->d_inode));
++ else
++ err = copyup_deleted_file(file, dentry, parent,
++ bstart, bindex);
++ /* if succeeded, set lower open-file flags and break */
++ if (!err) {
++ struct file *lower_file;
++ lower_file = unionfs_lower_file_idx(file, bindex);
++ lower_file->f_flags = file->f_flags;
++ break;
++ }
++ }
++ if (err || (bstart <= fbstart(file)))
++ goto out;
++ bend = fbend(file);
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ if (unionfs_lower_file_idx(file, bindex)) {
++ branchput(dentry->d_sb, bindex);
++ fput(unionfs_lower_file_idx(file, bindex));
++ unionfs_set_lower_file_idx(file, bindex, NULL);
++ }
++ }
++ path_put_lowers(dentry, bstart, bend, false);
++ iput_lowers(dentry->d_inode, bstart, bend, false);
++ /* for reg file, we only open it "once" */
++ fbend(file) = fbstart(file);
++ dbend(dentry) = dbstart(dentry);
++ ibend(dentry->d_inode) = ibstart(dentry->d_inode);
++
++out:
++ unionfs_check_file(file);
++ return err;
++}
++
++/*
++ * Helper function for unionfs_file_revalidate/locked.
++ * Expects dentry/parent to be locked already, and revalidated.
++ */
++static int __unionfs_file_revalidate(struct file *file, struct dentry *dentry,
++ struct dentry *parent,
++ struct super_block *sb, int sbgen,
++ int dgen, bool willwrite)
++{
++ int fgen;
++ int bstart, bend, orig_brid;
++ int size;
++ int err = 0;
++
++ fgen = atomic_read(&UNIONFS_F(file)->generation);
++
++ /*
++ * There are two cases we are interested in. The first is if the
++ * generation is lower than the super-block. The second is if
++ * someone has copied up this file from underneath us, we also need
++ * to refresh things.
++ */
++ if (d_deleted(dentry) ||
++ (sbgen <= fgen &&
++ dbstart(dentry) == fbstart(file) &&
++ unionfs_lower_file(file)))
++ goto out_may_copyup;
++
++ /* save orig branch ID */
++ orig_brid = UNIONFS_F(file)->saved_branch_ids[fbstart(file)];
++
++ /* First we throw out the existing files. */
++ cleanup_file(file);
++
++ /* Now we reopen the file(s) as in unionfs_open. */
++ bstart = fbstart(file) = dbstart(dentry);
++ bend = fbend(file) = dbend(dentry);
++
++ size = sizeof(struct file *) * sbmax(sb);
++ UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
++ if (unlikely(!UNIONFS_F(file)->lower_files)) {
++ err = -ENOMEM;
++ goto out;
++ }
++ size = sizeof(int) * sbmax(sb);
++ UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
++ if (unlikely(!UNIONFS_F(file)->saved_branch_ids)) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ if (S_ISDIR(dentry->d_inode->i_mode)) {
++ /* We need to open all the files. */
++ err = open_all_files(file);
++ if (err)
++ goto out;
++ } else {
++ int new_brid;
++ /* We only open the highest priority branch. */
++ err = open_highest_file(file, willwrite);
++ if (err)
++ goto out;
++ new_brid = UNIONFS_F(file)->saved_branch_ids[fbstart(file)];
++ if (unlikely(new_brid != orig_brid && sbgen > fgen)) {
++ /*
++ * If we re-opened the file on a different branch
++ * than the original one, and this was due to a new
++ * branch inserted, then update the mnt counts of
++ * the old and new branches accordingly.
++ */
++ unionfs_mntget(dentry, bstart);
++ unionfs_mntput(sb->s_root,
++ branch_id_to_idx(sb, orig_brid));
++ }
++ /* regular files have only one open lower file */
++ fbend(file) = fbstart(file);
++ }
++ atomic_set(&UNIONFS_F(file)->generation,
++ atomic_read(&UNIONFS_I(dentry->d_inode)->generation));
++
++out_may_copyup:
++ /* Copyup on the first write to a file on a readonly branch. */
++ if (willwrite && IS_WRITE_FLAG(file->f_flags) &&
++ !IS_WRITE_FLAG(unionfs_lower_file(file)->f_flags) &&
++ is_robranch(dentry)) {
++ pr_debug("unionfs: do delay copyup of \"%s\"\n",
++ dentry->d_name.name);
++ err = do_delayed_copyup(file, parent);
++ /* regular files have only one open lower file */
++ if (!err && !S_ISDIR(dentry->d_inode->i_mode))
++ fbend(file) = fbstart(file);
++ }
++
++out:
++ if (err) {
++ kfree(UNIONFS_F(file)->lower_files);
++ kfree(UNIONFS_F(file)->saved_branch_ids);
++ }
++ return err;
++}
++
++/*
++ * Revalidate the struct file
++ * @file: file to revalidate
++ * @parent: parent dentry (locked by caller)
++ * @willwrite: true if caller may cause changes to the file; false otherwise.
++ * Caller must lock/unlock dentry's branch configuration.
++ */
++int unionfs_file_revalidate(struct file *file, struct dentry *parent,
++ bool willwrite)
++{
++ struct super_block *sb;
++ struct dentry *dentry;
++ int sbgen, dgen;
++ int err = 0;
++
++ dentry = file->f_path.dentry;
++ sb = dentry->d_sb;
++ verify_locked(dentry);
++ verify_locked(parent);
++
++ /*
++ * First revalidate the dentry inside struct file,
++ * but not unhashed dentries.
++ */
++ if (!d_deleted(dentry) &&
++ !__unionfs_d_revalidate(dentry, parent, willwrite)) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ sbgen = atomic_read(&UNIONFS_SB(sb)->generation);
++ dgen = atomic_read(&UNIONFS_D(dentry)->generation);
++
++ if (unlikely(sbgen > dgen)) { /* XXX: should never happen */
++ pr_debug("unionfs: failed to revalidate dentry (%s)\n",
++ dentry->d_name.name);
++ err = -ESTALE;
++ goto out;
++ }
++
++ err = __unionfs_file_revalidate(file, dentry, parent, sb,
++ sbgen, dgen, willwrite);
++out:
++ return err;
++}
++
++/* unionfs_open helper function: open a directory */
++static int __open_dir(struct inode *inode, struct file *file)
++{
++ struct dentry *lower_dentry;
++ struct file *lower_file;
++ int bindex, bstart, bend;
++ struct vfsmount *mnt;
++
++ bstart = fbstart(file) = dbstart(file->f_path.dentry);
++ bend = fbend(file) = dbend(file->f_path.dentry);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry =
++ unionfs_lower_dentry_idx(file->f_path.dentry, bindex);
++ if (!lower_dentry)
++ continue;
++
++ dget(lower_dentry);
++ unionfs_mntget(file->f_path.dentry, bindex);
++ mnt = unionfs_lower_mnt_idx(file->f_path.dentry, bindex);
++ lower_file = dentry_open(lower_dentry, mnt, file->f_flags,
++ current_cred());
++ if (IS_ERR(lower_file))
++ return PTR_ERR(lower_file);
++
++ unionfs_set_lower_file_idx(file, bindex, lower_file);
++
++ /*
++ * The branchget goes after the open, because otherwise
++ * we would miss the reference on release.
++ */
++ branchget(inode->i_sb, bindex);
++ }
++
++ return 0;
++}
++
++/* unionfs_open helper function: open a file */
++static int __open_file(struct inode *inode, struct file *file,
++ struct dentry *parent)
++{
++ struct dentry *lower_dentry;
++ struct file *lower_file;
++ int lower_flags;
++ int bindex, bstart, bend;
++
++ lower_dentry = unionfs_lower_dentry(file->f_path.dentry);
++ lower_flags = file->f_flags;
++
++ bstart = fbstart(file) = dbstart(file->f_path.dentry);
++ bend = fbend(file) = dbend(file->f_path.dentry);
++
++ /*
++ * check for the permission for lower file. If the error is
++ * COPYUP_ERR, copyup the file.
++ */
++ if (lower_dentry->d_inode && is_robranch(file->f_path.dentry)) {
++ /*
++ * if the open will change the file, copy it up otherwise
++ * defer it.
++ */
++ if (lower_flags & O_TRUNC) {
++ int size = 0;
++ int err = -EROFS;
++
++ /* copyup the file */
++ for (bindex = bstart - 1; bindex >= 0; bindex--) {
++ err = copyup_file(parent->d_inode, file,
++ bstart, bindex, size);
++ if (!err)
++ break;
++ }
++ return err;
++ } else {
++ /*
++ * turn off writeable flags, to force delayed copyup
++ * by caller.
++ */
++ lower_flags &= ~(OPEN_WRITE_FLAGS);
++ }
++ }
++
++ dget(lower_dentry);
++
++ /*
++ * dentry_open will decrement mnt refcnt if err.
++ * otherwise fput() will do an mntput() for us upon file close.
++ */
++ unionfs_mntget(file->f_path.dentry, bstart);
++ lower_file =
++ dentry_open(lower_dentry,
++ unionfs_lower_mnt_idx(file->f_path.dentry, bstart),
++ lower_flags, current_cred());
++ if (IS_ERR(lower_file))
++ return PTR_ERR(lower_file);
++
++ unionfs_set_lower_file(file, lower_file);
++ branchget(inode->i_sb, bstart);
++
++ return 0;
++}
++
++int unionfs_open(struct inode *inode, struct file *file)
++{
++ int err = 0;
++ struct file *lower_file = NULL;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++ int bindex = 0, bstart = 0, bend = 0;
++ int size;
++ int valid = 0;
++
++ unionfs_read_lock(inode->i_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ /* don't open unhashed/deleted files */
++ if (d_deleted(dentry)) {
++ err = -ENOENT;
++ goto out_nofree;
++ }
++
++ /* XXX: should I change 'false' below to the 'willwrite' flag? */
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out_nofree;
++ }
++
++ file->private_data =
++ kzalloc(sizeof(struct unionfs_file_info), GFP_KERNEL);
++ if (unlikely(!UNIONFS_F(file))) {
++ err = -ENOMEM;
++ goto out_nofree;
++ }
++ fbstart(file) = -1;
++ fbend(file) = -1;
++ atomic_set(&UNIONFS_F(file)->generation,
++ atomic_read(&UNIONFS_I(inode)->generation));
++
++ size = sizeof(struct file *) * sbmax(inode->i_sb);
++ UNIONFS_F(file)->lower_files = kzalloc(size, GFP_KERNEL);
++ if (unlikely(!UNIONFS_F(file)->lower_files)) {
++ err = -ENOMEM;
++ goto out;
++ }
++ size = sizeof(int) * sbmax(inode->i_sb);
++ UNIONFS_F(file)->saved_branch_ids = kzalloc(size, GFP_KERNEL);
++ if (unlikely(!UNIONFS_F(file)->saved_branch_ids)) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ bstart = fbstart(file) = dbstart(dentry);
++ bend = fbend(file) = dbend(dentry);
++
++ /*
++ * open all directories and make the unionfs file struct point to
++ * these lower file structs
++ */
++ if (S_ISDIR(inode->i_mode))
++ err = __open_dir(inode, file); /* open a dir */
++ else
++ err = __open_file(inode, file, parent); /* open a file */
++
++ /* freeing the allocated resources, and fput the opened files */
++ if (err) {
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_file = unionfs_lower_file_idx(file, bindex);
++ if (!lower_file)
++ continue;
++
++ branchput(dentry->d_sb, bindex);
++ /* fput calls dput for lower_dentry */
++ fput(lower_file);
++ }
++ }
++
++out:
++ if (err) {
++ kfree(UNIONFS_F(file)->lower_files);
++ kfree(UNIONFS_F(file)->saved_branch_ids);
++ kfree(UNIONFS_F(file));
++ }
++out_nofree:
++ if (!err) {
++ unionfs_postcopyup_setmnt(dentry);
++ unionfs_copy_attr_times(inode);
++ unionfs_check_file(file);
++ unionfs_check_inode(inode);
++ }
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(inode->i_sb);
++ return err;
++}
++
++/*
++ * release all lower object references & free the file info structure
++ *
++ * No need to grab sb info's rwsem.
++ */
++int unionfs_file_release(struct inode *inode, struct file *file)
++{
++ struct file *lower_file = NULL;
++ struct unionfs_file_info *fileinfo;
++ struct unionfs_inode_info *inodeinfo;
++ struct super_block *sb = inode->i_sb;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++ int bindex, bstart, bend;
++ int fgen, err = 0;
++
++ /*
++ * Since mm/memory.c:might_fault() (under PROVE_LOCKING) was
++ * modified in 2.6.29-rc1 to call might_lock_read on mmap_sem, this
++ * has been causing false positives in file system stacking layers.
++ * In particular, our ->mmap is called after sys_mmap2 already holds
++ * mmap_sem, then we lock our own mutexes; but earlier, it's
++ * possible for lockdep to have locked our mutexes first, and then
++ * we call a lower ->readdir which could call might_fault. The
++ * different ordering of the locks is what lockdep complains about
++ * -- unnecessarily. Therefore, we have no choice but to tell
++ * lockdep to temporarily turn off lockdep here. Note: the comments
++ * inside might_sleep also suggest that it would have been
++ * nicer to only annotate paths that needs that might_lock_read.
++ */
++ lockdep_off();
++ unionfs_read_lock(sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ /*
++ * We try to revalidate, but the VFS ignores return return values
++ * from file->release, so we must always try to succeed here,
++ * including to do the kfree and dput below. So if revalidation
++ * failed, all we can do is print some message and keep going.
++ */
++ err = unionfs_file_revalidate(file, parent,
++ UNIONFS_F(file)->wrote_to_file);
++ if (!err)
++ unionfs_check_file(file);
++ fileinfo = UNIONFS_F(file);
++ BUG_ON(file->f_path.dentry->d_inode != inode);
++ inodeinfo = UNIONFS_I(inode);
++
++ /* fput all the lower files */
++ fgen = atomic_read(&fileinfo->generation);
++ bstart = fbstart(file);
++ bend = fbend(file);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_file = unionfs_lower_file_idx(file, bindex);
++
++ if (lower_file) {
++ unionfs_set_lower_file_idx(file, bindex, NULL);
++ fput(lower_file);
++ branchput(sb, bindex);
++ }
++
++ /* if there are no more refs to the dentry, dput it */
++ if (d_deleted(dentry)) {
++ dput(unionfs_lower_dentry_idx(dentry, bindex));
++ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
++ }
++ }
++
++ kfree(fileinfo->lower_files);
++ kfree(fileinfo->saved_branch_ids);
++
++ if (fileinfo->rdstate) {
++ fileinfo->rdstate->access = jiffies;
++ spin_lock(&inodeinfo->rdlock);
++ inodeinfo->rdcount++;
++ list_add_tail(&fileinfo->rdstate->cache,
++ &inodeinfo->readdircache);
++ mark_inode_dirty(inode);
++ spin_unlock(&inodeinfo->rdlock);
++ fileinfo->rdstate = NULL;
++ }
++ kfree(fileinfo);
++
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(sb);
++ lockdep_on();
++ return err;
++}
++
++/* pass the ioctl to the lower fs */
++static long do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
++{
++ struct file *lower_file;
++ int err;
++
++ lower_file = unionfs_lower_file(file);
++
++ err = -ENOTTY;
++ if (!lower_file || !lower_file->f_op)
++ goto out;
++ if (lower_file->f_op->unlocked_ioctl) {
++ err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg);
++ } else if (lower_file->f_op->ioctl) {
++ lock_kernel();
++ err = lower_file->f_op->ioctl(
++ lower_file->f_path.dentry->d_inode,
++ lower_file, cmd, arg);
++ unlock_kernel();
++ }
++
++out:
++ return err;
++}
++
++/*
++ * return to user-space the branch indices containing the file in question
++ *
++ * We use fd_set and therefore we are limited to the number of the branches
++ * to FD_SETSIZE, which is currently 1024 - plenty for most people
++ */
++static int unionfs_ioctl_queryfile(struct file *file, struct dentry *parent,
++ unsigned int cmd, unsigned long arg)
++{
++ int err = 0;
++ fd_set branchlist;
++ int bstart = 0, bend = 0, bindex = 0;
++ int orig_bstart, orig_bend;
++ struct dentry *dentry, *lower_dentry;
++ struct vfsmount *mnt;
++
++ dentry = file->f_path.dentry;
++ orig_bstart = dbstart(dentry);
++ orig_bend = dbend(dentry);
++ err = unionfs_partial_lookup(dentry, parent);
++ if (err)
++ goto out;
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++
++ FD_ZERO(&branchlist);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry)
++ continue;
++ if (likely(lower_dentry->d_inode))
++ FD_SET(bindex, &branchlist);
++ /* purge any lower objects after partial_lookup */
++ if (bindex < orig_bstart || bindex > orig_bend) {
++ dput(lower_dentry);
++ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
++ iput(unionfs_lower_inode_idx(dentry->d_inode, bindex));
++ unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
++ NULL);
++ mnt = unionfs_lower_mnt_idx(dentry, bindex);
++ if (!mnt)
++ continue;
++ unionfs_mntput(dentry, bindex);
++ unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
++ }
++ }
++ /* restore original dentry's offsets */
++ dbstart(dentry) = orig_bstart;
++ dbend(dentry) = orig_bend;
++ ibstart(dentry->d_inode) = orig_bstart;
++ ibend(dentry->d_inode) = orig_bend;
++
++ err = copy_to_user((void __user *)arg, &branchlist, sizeof(fd_set));
++ if (unlikely(err))
++ err = -EFAULT;
++
++out:
++ return err < 0 ? err : bend;
++}
++
++long unionfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
++{
++ long err;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, true);
++ if (unlikely(err))
++ goto out;
++
++ /* check if asked for local commands */
++ switch (cmd) {
++ case UNIONFS_IOCTL_INCGEN:
++ /* Increment the superblock generation count */
++ pr_info("unionfs: incgen ioctl deprecated; "
++ "use \"-o remount,incgen\"\n");
++ err = -ENOSYS;
++ break;
++
++ case UNIONFS_IOCTL_QUERYFILE:
++ /* Return list of branches containing the given file */
++ err = unionfs_ioctl_queryfile(file, parent, cmd, arg);
++ break;
++
++ default:
++ /* pass the ioctl down */
++ err = do_ioctl(file, cmd, arg);
++ break;
++ }
++
++out:
++ unionfs_check_file(file);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++int unionfs_flush(struct file *file, fl_owner_t id)
++{
++ int err = 0;
++ struct file *lower_file = NULL;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++ int bindex, bstart, bend;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent,
++ UNIONFS_F(file)->wrote_to_file);
++ if (unlikely(err))
++ goto out;
++ unionfs_check_file(file);
++
++ bstart = fbstart(file);
++ bend = fbend(file);
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_file = unionfs_lower_file_idx(file, bindex);
++
++ if (lower_file && lower_file->f_op &&
++ lower_file->f_op->flush) {
++ err = lower_file->f_op->flush(lower_file, id);
++ if (err)
++ goto out;
++ }
++
++ }
++
++out:
++ if (!err)
++ unionfs_check_file(file);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
+diff --git a/fs/unionfs/copyup.c b/fs/unionfs/copyup.c
+new file mode 100644
+index 0000000..bba3a75
+--- /dev/null
++++ b/fs/unionfs/copyup.c
+@@ -0,0 +1,896 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++/*
++ * For detailed explanation of copyup see:
++ * Documentation/filesystems/unionfs/concepts.txt
++ */
++
++#ifdef CONFIG_UNION_FS_XATTR
++/* copyup all extended attrs for a given dentry */
++static int copyup_xattrs(struct dentry *old_lower_dentry,
++ struct dentry *new_lower_dentry)
++{
++ int err = 0;
++ ssize_t list_size = -1;
++ char *name_list = NULL;
++ char *attr_value = NULL;
++ char *name_list_buf = NULL;
++
++ /* query the actual size of the xattr list */
++ list_size = vfs_listxattr(old_lower_dentry, NULL, 0);
++ if (list_size <= 0) {
++ err = list_size;
++ goto out;
++ }
++
++ /* allocate space for the actual list */
++ name_list = unionfs_xattr_alloc(list_size + 1, XATTR_LIST_MAX);
++ if (unlikely(!name_list || IS_ERR(name_list))) {
++ err = PTR_ERR(name_list);
++ goto out;
++ }
++
++ name_list_buf = name_list; /* save for kfree at end */
++
++ /* now get the actual xattr list of the source file */
++ list_size = vfs_listxattr(old_lower_dentry, name_list, list_size);
++ if (list_size <= 0) {
++ err = list_size;
++ goto out;
++ }
++
++ /* allocate space to hold each xattr's value */
++ attr_value = unionfs_xattr_alloc(XATTR_SIZE_MAX, XATTR_SIZE_MAX);
++ if (unlikely(!attr_value || IS_ERR(attr_value))) {
++ err = PTR_ERR(name_list);
++ goto out;
++ }
++
++ /* in a loop, get and set each xattr from src to dst file */
++ while (*name_list) {
++ ssize_t size;
++
++ /* Lock here since vfs_getxattr doesn't lock for us */
++ mutex_lock(&old_lower_dentry->d_inode->i_mutex);
++ size = vfs_getxattr(old_lower_dentry, name_list,
++ attr_value, XATTR_SIZE_MAX);
++ mutex_unlock(&old_lower_dentry->d_inode->i_mutex);
++ if (size < 0) {
++ err = size;
++ goto out;
++ }
++ if (size > XATTR_SIZE_MAX) {
++ err = -E2BIG;
++ goto out;
++ }
++ /* Don't lock here since vfs_setxattr does it for us. */
++ err = vfs_setxattr(new_lower_dentry, name_list, attr_value,
++ size, 0);
++ /*
++ * Selinux depends on "security.*" xattrs, so to maintain
++ * the security of copied-up files, if Selinux is active,
++ * then we must copy these xattrs as well. So we need to
++ * temporarily get FOWNER privileges.
++ * XXX: move entire copyup code to SIOQ.
++ */
++ if (err == -EPERM && !capable(CAP_FOWNER)) {
++ const struct cred *old_creds;
++ struct cred *new_creds;
++
++ new_creds = prepare_creds();
++ if (unlikely(!new_creds)) {
++ err = -ENOMEM;
++ goto out;
++ }
++ cap_raise(new_creds->cap_effective, CAP_FOWNER);
++ old_creds = override_creds(new_creds);
++ err = vfs_setxattr(new_lower_dentry, name_list,
++ attr_value, size, 0);
++ revert_creds(old_creds);
++ }
++ if (err < 0)
++ goto out;
++ name_list += strlen(name_list) + 1;
++ }
++out:
++ unionfs_xattr_kfree(name_list_buf);
++ unionfs_xattr_kfree(attr_value);
++ /* Ignore if xattr isn't supported */
++ if (err == -ENOTSUPP || err == -EOPNOTSUPP)
++ err = 0;
++ return err;
++}
++#endif /* CONFIG_UNION_FS_XATTR */
++
++/*
++ * Determine the mode based on the copyup flags, and the existing dentry.
++ *
++ * Handle file systems which may not support certain options. For example
++ * jffs2 doesn't allow one to chmod a symlink. So we ignore such harmless
++ * errors, rather than propagating them up, which results in copyup errors
++ * and errors returned back to users.
++ */
++static int copyup_permissions(struct super_block *sb,
++ struct dentry *old_lower_dentry,
++ struct dentry *new_lower_dentry)
++{
++ struct inode *i = old_lower_dentry->d_inode;
++ struct iattr newattrs;
++ int err;
++
++ newattrs.ia_atime = i->i_atime;
++ newattrs.ia_mtime = i->i_mtime;
++ newattrs.ia_ctime = i->i_ctime;
++ newattrs.ia_gid = i->i_gid;
++ newattrs.ia_uid = i->i_uid;
++ newattrs.ia_valid = ATTR_CTIME | ATTR_ATIME | ATTR_MTIME |
++ ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_FORCE |
++ ATTR_GID | ATTR_UID;
++ mutex_lock(&new_lower_dentry->d_inode->i_mutex);
++ err = notify_change(new_lower_dentry, &newattrs);
++ if (err)
++ goto out;
++
++ /* now try to change the mode and ignore EOPNOTSUPP on symlinks */
++ newattrs.ia_mode = i->i_mode;
++ newattrs.ia_valid = ATTR_MODE | ATTR_FORCE;
++ err = notify_change(new_lower_dentry, &newattrs);
++ if (err == -EOPNOTSUPP &&
++ S_ISLNK(new_lower_dentry->d_inode->i_mode)) {
++ printk(KERN_WARNING
++ "unionfs: changing \"%s\" symlink mode unsupported\n",
++ new_lower_dentry->d_name.name);
++ err = 0;
++ }
++
++out:
++ mutex_unlock(&new_lower_dentry->d_inode->i_mutex);
++ return err;
++}
++
++/*
++ * create the new device/file/directory - use copyup_permission to copyup
++ * times, and mode
++ *
++ * if the object being copied up is a regular file, the file is only created,
++ * the contents have to be copied up separately
++ */
++static int __copyup_ndentry(struct dentry *old_lower_dentry,
++ struct dentry *new_lower_dentry,
++ struct dentry *new_lower_parent_dentry,
++ char *symbuf)
++{
++ int err = 0;
++ umode_t old_mode = old_lower_dentry->d_inode->i_mode;
++ struct sioq_args args;
++
++ if (S_ISDIR(old_mode)) {
++ args.mkdir.parent = new_lower_parent_dentry->d_inode;
++ args.mkdir.dentry = new_lower_dentry;
++ args.mkdir.mode = old_mode;
++
++ run_sioq(__unionfs_mkdir, &args);
++ err = args.err;
++ } else if (S_ISLNK(old_mode)) {
++ args.symlink.parent = new_lower_parent_dentry->d_inode;
++ args.symlink.dentry = new_lower_dentry;
++ args.symlink.symbuf = symbuf;
++
++ run_sioq(__unionfs_symlink, &args);
++ err = args.err;
++ } else if (S_ISBLK(old_mode) || S_ISCHR(old_mode) ||
++ S_ISFIFO(old_mode) || S_ISSOCK(old_mode)) {
++ args.mknod.parent = new_lower_parent_dentry->d_inode;
++ args.mknod.dentry = new_lower_dentry;
++ args.mknod.mode = old_mode;
++ args.mknod.dev = old_lower_dentry->d_inode->i_rdev;
++
++ run_sioq(__unionfs_mknod, &args);
++ err = args.err;
++ } else if (S_ISREG(old_mode)) {
++ struct nameidata nd;
++ err = init_lower_nd(&nd, LOOKUP_CREATE);
++ if (unlikely(err < 0))
++ goto out;
++ args.create.nd = &nd;
++ args.create.parent = new_lower_parent_dentry->d_inode;
++ args.create.dentry = new_lower_dentry;
++ args.create.mode = old_mode;
++
++ run_sioq(__unionfs_create, &args);
++ err = args.err;
++ release_lower_nd(&nd, err);
++ } else {
++ printk(KERN_CRIT "unionfs: unknown inode type %d\n",
++ old_mode);
++ BUG();
++ }
++
++out:
++ return err;
++}
++
++static int __copyup_reg_data(struct dentry *dentry,
++ struct dentry *new_lower_dentry, int new_bindex,
++ struct dentry *old_lower_dentry, int old_bindex,
++ struct file **copyup_file, loff_t len)
++{
++ struct super_block *sb = dentry->d_sb;
++ struct file *input_file;
++ struct file *output_file;
++ struct vfsmount *output_mnt;
++ mm_segment_t old_fs;
++ char *buf = NULL;
++ ssize_t read_bytes, write_bytes;
++ loff_t size;
++ int err = 0;
++
++ /* open old file */
++ unionfs_mntget(dentry, old_bindex);
++ branchget(sb, old_bindex);
++ /* dentry_open calls dput and mntput if it returns an error */
++ input_file = dentry_open(old_lower_dentry,
++ unionfs_lower_mnt_idx(dentry, old_bindex),
++ O_RDONLY | O_LARGEFILE, current_cred());
++ if (IS_ERR(input_file)) {
++ dput(old_lower_dentry);
++ err = PTR_ERR(input_file);
++ goto out;
++ }
++ if (unlikely(!input_file->f_op || !input_file->f_op->read)) {
++ err = -EINVAL;
++ goto out_close_in;
++ }
++
++ /* open new file */
++ dget(new_lower_dentry);
++ output_mnt = unionfs_mntget(sb->s_root, new_bindex);
++ branchget(sb, new_bindex);
++ output_file = dentry_open(new_lower_dentry, output_mnt,
++ O_RDWR | O_LARGEFILE, current_cred());
++ if (IS_ERR(output_file)) {
++ err = PTR_ERR(output_file);
++ goto out_close_in2;
++ }
++ if (unlikely(!output_file->f_op || !output_file->f_op->write)) {
++ err = -EINVAL;
++ goto out_close_out;
++ }
++
++ /* allocating a buffer */
++ buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
++ if (unlikely(!buf)) {
++ err = -ENOMEM;
++ goto out_close_out;
++ }
++
++ input_file->f_pos = 0;
++ output_file->f_pos = 0;
++
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++
++ size = len;
++ err = 0;
++ do {
++ if (len >= PAGE_SIZE)
++ size = PAGE_SIZE;
++ else if ((len < PAGE_SIZE) && (len > 0))
++ size = len;
++
++ len -= PAGE_SIZE;
++
++ read_bytes =
++ input_file->f_op->read(input_file,
++ (char __user *)buf, size,
++ &input_file->f_pos);
++ if (read_bytes <= 0) {
++ err = read_bytes;
++ break;
++ }
++
++ /* see Documentation/filesystems/unionfs/issues.txt */
++ lockdep_off();
++ write_bytes =
++ output_file->f_op->write(output_file,
++ (char __user *)buf,
++ read_bytes,
++ &output_file->f_pos);
++ lockdep_on();
++ if ((write_bytes < 0) || (write_bytes < read_bytes)) {
++ err = write_bytes;
++ break;
++ }
++ } while ((read_bytes > 0) && (len > 0));
++
++ set_fs(old_fs);
++
++ kfree(buf);
++
++ if (!err)
++ err = output_file->f_op->fsync(output_file, 0);
++
++ if (err)
++ goto out_close_out;
++
++ if (copyup_file) {
++ *copyup_file = output_file;
++ goto out_close_in;
++ }
++
++out_close_out:
++ fput(output_file);
++
++out_close_in2:
++ branchput(sb, new_bindex);
++
++out_close_in:
++ fput(input_file);
++
++out:
++ branchput(sb, old_bindex);
++
++ return err;
++}
++
++/*
++ * dput the lower references for old and new dentry & clear a lower dentry
++ * pointer
++ */
++static void __clear(struct dentry *dentry, struct dentry *old_lower_dentry,
++ int old_bstart, int old_bend,
++ struct dentry *new_lower_dentry, int new_bindex)
++{
++ /* get rid of the lower dentry and all its traces */
++ unionfs_set_lower_dentry_idx(dentry, new_bindex, NULL);
++ dbstart(dentry) = old_bstart;
++ dbend(dentry) = old_bend;
++
++ dput(new_lower_dentry);
++ dput(old_lower_dentry);
++}
++
++/*
++ * Copy up a dentry to a file of specified name.
++ *
++ * @dir: used to pull the ->i_sb to access other branches
++ * @dentry: the non-negative dentry whose lower_inode we should copy
++ * @bstart: the branch of the lower_inode to copy from
++ * @new_bindex: the branch to create the new file in
++ * @name: the name of the file to create
++ * @namelen: length of @name
++ * @copyup_file: the "struct file" to return (optional)
++ * @len: how many bytes to copy-up?
++ */
++int copyup_dentry(struct inode *dir, struct dentry *dentry, int bstart,
++ int new_bindex, const char *name, int namelen,
++ struct file **copyup_file, loff_t len)
++{
++ struct dentry *new_lower_dentry;
++ struct dentry *old_lower_dentry = NULL;
++ struct super_block *sb;
++ int err = 0;
++ int old_bindex;
++ int old_bstart;
++ int old_bend;
++ struct dentry *new_lower_parent_dentry = NULL;
++ mm_segment_t oldfs;
++ char *symbuf = NULL;
++
++ verify_locked(dentry);
++
++ old_bindex = bstart;
++ old_bstart = dbstart(dentry);
++ old_bend = dbend(dentry);
++
++ BUG_ON(new_bindex < 0);
++ BUG_ON(new_bindex >= old_bindex);
++
++ sb = dir->i_sb;
++
++ err = is_robranch_super(sb, new_bindex);
++ if (err)
++ goto out;
++
++ /* Create the directory structure above this dentry. */
++ new_lower_dentry = create_parents(dir, dentry, name, new_bindex);
++ if (IS_ERR(new_lower_dentry)) {
++ err = PTR_ERR(new_lower_dentry);
++ goto out;
++ }
++
++ old_lower_dentry = unionfs_lower_dentry_idx(dentry, old_bindex);
++ /* we conditionally dput this old_lower_dentry at end of function */
++ dget(old_lower_dentry);
++
++ /* For symlinks, we must read the link before we lock the directory. */
++ if (S_ISLNK(old_lower_dentry->d_inode->i_mode)) {
++
++ symbuf = kmalloc(PATH_MAX, GFP_KERNEL);
++ if (unlikely(!symbuf)) {
++ __clear(dentry, old_lower_dentry,
++ old_bstart, old_bend,
++ new_lower_dentry, new_bindex);
++ err = -ENOMEM;
++ goto out_free;
++ }
++
++ oldfs = get_fs();
++ set_fs(KERNEL_DS);
++ err = old_lower_dentry->d_inode->i_op->readlink(
++ old_lower_dentry,
++ (char __user *)symbuf,
++ PATH_MAX);
++ set_fs(oldfs);
++ if (err < 0) {
++ __clear(dentry, old_lower_dentry,
++ old_bstart, old_bend,
++ new_lower_dentry, new_bindex);
++ goto out_free;
++ }
++ symbuf[err] = '\0';
++ }
++
++ /* Now we lock the parent, and create the object in the new branch. */
++ new_lower_parent_dentry = lock_parent(new_lower_dentry);
++
++ /* create the new inode */
++ err = __copyup_ndentry(old_lower_dentry, new_lower_dentry,
++ new_lower_parent_dentry, symbuf);
++
++ if (err) {
++ __clear(dentry, old_lower_dentry,
++ old_bstart, old_bend,
++ new_lower_dentry, new_bindex);
++ goto out_unlock;
++ }
++
++ /* We actually copyup the file here. */
++ if (S_ISREG(old_lower_dentry->d_inode->i_mode))
++ err = __copyup_reg_data(dentry, new_lower_dentry, new_bindex,
++ old_lower_dentry, old_bindex,
++ copyup_file, len);
++ if (err)
++ goto out_unlink;
++
++ /* Set permissions. */
++ err = copyup_permissions(sb, old_lower_dentry, new_lower_dentry);
++ if (err)
++ goto out_unlink;
++
++#ifdef CONFIG_UNION_FS_XATTR
++ /* Selinux uses extended attributes for permissions. */
++ err = copyup_xattrs(old_lower_dentry, new_lower_dentry);
++ if (err)
++ goto out_unlink;
++#endif /* CONFIG_UNION_FS_XATTR */
++
++ /* do not allow files getting deleted to be re-interposed */
++ if (!d_deleted(dentry))
++ unionfs_reinterpose(dentry);
++
++ goto out_unlock;
++
++out_unlink:
++ /*
++ * copyup failed, because we possibly ran out of space or
++ * quota, or something else happened so let's unlink; we don't
++ * really care about the return value of vfs_unlink
++ */
++ vfs_unlink(new_lower_parent_dentry->d_inode, new_lower_dentry);
++
++ if (copyup_file) {
++ /* need to close the file */
++
++ fput(*copyup_file);
++ branchput(sb, new_bindex);
++ }
++
++ /*
++ * TODO: should we reset the error to something like -EIO?
++ *
++ * If we don't reset, the user may get some nonsensical errors, but
++ * on the other hand, if we reset to EIO, we guarantee that the user
++ * will get a "confusing" error message.
++ */
++
++out_unlock:
++ unlock_dir(new_lower_parent_dentry);
++
++out_free:
++ /*
++ * If old_lower_dentry was not a file, then we need to dput it. If
++ * it was a file, then it was already dput indirectly by other
++ * functions we call above which operate on regular files.
++ */
++ if (old_lower_dentry && old_lower_dentry->d_inode &&
++ !S_ISREG(old_lower_dentry->d_inode->i_mode))
++ dput(old_lower_dentry);
++ kfree(symbuf);
++
++ if (err) {
++ /*
++ * if directory creation succeeded, but inode copyup failed,
++ * then purge new dentries.
++ */
++ if (dbstart(dentry) < old_bstart &&
++ ibstart(dentry->d_inode) > dbstart(dentry))
++ __clear(dentry, NULL, old_bstart, old_bend,
++ unionfs_lower_dentry(dentry), dbstart(dentry));
++ goto out;
++ }
++ if (!S_ISDIR(dentry->d_inode->i_mode)) {
++ unionfs_postcopyup_release(dentry);
++ if (!unionfs_lower_inode(dentry->d_inode)) {
++ /*
++ * If we got here, then we copied up to an
++ * unlinked-open file, whose name is .unionfsXXXXX.
++ */
++ struct inode *inode = new_lower_dentry->d_inode;
++ atomic_inc(&inode->i_count);
++ unionfs_set_lower_inode_idx(dentry->d_inode,
++ ibstart(dentry->d_inode),
++ inode);
++ }
++ }
++ unionfs_postcopyup_setmnt(dentry);
++ /* sync inode times from copied-up inode to our inode */
++ unionfs_copy_attr_times(dentry->d_inode);
++ unionfs_check_inode(dir);
++ unionfs_check_dentry(dentry);
++out:
++ return err;
++}
++
++/*
++ * This function creates a copy of a file represented by 'file' which
++ * currently resides in branch 'bstart' to branch 'new_bindex.' The copy
++ * will be named "name".
++ */
++int copyup_named_file(struct inode *dir, struct file *file, char *name,
++ int bstart, int new_bindex, loff_t len)
++{
++ int err = 0;
++ struct file *output_file = NULL;
++
++ err = copyup_dentry(dir, file->f_path.dentry, bstart, new_bindex,
++ name, strlen(name), &output_file, len);
++ if (!err) {
++ fbstart(file) = new_bindex;
++ unionfs_set_lower_file_idx(file, new_bindex, output_file);
++ }
++
++ return err;
++}
++
++/*
++ * This function creates a copy of a file represented by 'file' which
++ * currently resides in branch 'bstart' to branch 'new_bindex'.
++ */
++int copyup_file(struct inode *dir, struct file *file, int bstart,
++ int new_bindex, loff_t len)
++{
++ int err = 0;
++ struct file *output_file = NULL;
++ struct dentry *dentry = file->f_path.dentry;
++
++ err = copyup_dentry(dir, dentry, bstart, new_bindex,
++ dentry->d_name.name, dentry->d_name.len,
++ &output_file, len);
++ if (!err) {
++ fbstart(file) = new_bindex;
++ unionfs_set_lower_file_idx(file, new_bindex, output_file);
++ }
++
++ return err;
++}
++
++/* purge a dentry's lower-branch states (dput/mntput, etc.) */
++static void __cleanup_dentry(struct dentry *dentry, int bindex,
++ int old_bstart, int old_bend)
++{
++ int loop_start;
++ int loop_end;
++ int new_bstart = -1;
++ int new_bend = -1;
++ int i;
++
++ loop_start = min(old_bstart, bindex);
++ loop_end = max(old_bend, bindex);
++
++ /*
++ * This loop sets the bstart and bend for the new dentry by
++ * traversing from left to right. It also dputs all negative
++ * dentries except bindex
++ */
++ for (i = loop_start; i <= loop_end; i++) {
++ if (!unionfs_lower_dentry_idx(dentry, i))
++ continue;
++
++ if (i == bindex) {
++ new_bend = i;
++ if (new_bstart < 0)
++ new_bstart = i;
++ continue;
++ }
++
++ if (!unionfs_lower_dentry_idx(dentry, i)->d_inode) {
++ dput(unionfs_lower_dentry_idx(dentry, i));
++ unionfs_set_lower_dentry_idx(dentry, i, NULL);
++
++ unionfs_mntput(dentry, i);
++ unionfs_set_lower_mnt_idx(dentry, i, NULL);
++ } else {
++ if (new_bstart < 0)
++ new_bstart = i;
++ new_bend = i;
++ }
++ }
++
++ if (new_bstart < 0)
++ new_bstart = bindex;
++ if (new_bend < 0)
++ new_bend = bindex;
++ dbstart(dentry) = new_bstart;
++ dbend(dentry) = new_bend;
++
++}
++
++/* set lower inode ptr and update bstart & bend if necessary */
++static void __set_inode(struct dentry *upper, struct dentry *lower,
++ int bindex)
++{
++ unionfs_set_lower_inode_idx(upper->d_inode, bindex,
++ igrab(lower->d_inode));
++ if (likely(ibstart(upper->d_inode) > bindex))
++ ibstart(upper->d_inode) = bindex;
++ if (likely(ibend(upper->d_inode) < bindex))
++ ibend(upper->d_inode) = bindex;
++
++}
++
++/* set lower dentry ptr and update bstart & bend if necessary */
++static void __set_dentry(struct dentry *upper, struct dentry *lower,
++ int bindex)
++{
++ unionfs_set_lower_dentry_idx(upper, bindex, lower);
++ if (likely(dbstart(upper) > bindex))
++ dbstart(upper) = bindex;
++ if (likely(dbend(upper) < bindex))
++ dbend(upper) = bindex;
++}
++
++/*
++ * This function replicates the directory structure up-to given dentry
++ * in the bindex branch.
++ */
++struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
++ const char *name, int bindex)
++{
++ int err;
++ struct dentry *child_dentry;
++ struct dentry *parent_dentry;
++ struct dentry *lower_parent_dentry = NULL;
++ struct dentry *lower_dentry = NULL;
++ const char *childname;
++ unsigned int childnamelen;
++ int nr_dentry;
++ int count = 0;
++ int old_bstart;
++ int old_bend;
++ struct dentry **path = NULL;
++ struct super_block *sb;
++
++ verify_locked(dentry);
++
++ err = is_robranch_super(dir->i_sb, bindex);
++ if (err) {
++ lower_dentry = ERR_PTR(err);
++ goto out;
++ }
++
++ old_bstart = dbstart(dentry);
++ old_bend = dbend(dentry);
++
++ lower_dentry = ERR_PTR(-ENOMEM);
++
++ /* There is no sense allocating any less than the minimum. */
++ nr_dentry = 1;
++ path = kmalloc(nr_dentry * sizeof(struct dentry *), GFP_KERNEL);
++ if (unlikely(!path))
++ goto out;
++
++ /* assume the negative dentry of unionfs as the parent dentry */
++ parent_dentry = dentry;
++
++ /*
++ * This loop finds the first parent that exists in the given branch.
++ * We start building the directory structure from there. At the end
++ * of the loop, the following should hold:
++ * - child_dentry is the first nonexistent child
++ * - parent_dentry is the first existent parent
++ * - path[0] is the = deepest child
++ * - path[count] is the first child to create
++ */
++ do {
++ child_dentry = parent_dentry;
++
++ /* find the parent directory dentry in unionfs */
++ parent_dentry = dget_parent(child_dentry);
++
++ /* find out the lower_parent_dentry in the given branch */
++ lower_parent_dentry =
++ unionfs_lower_dentry_idx(parent_dentry, bindex);
++
++ /* grow path table */
++ if (count == nr_dentry) {
++ void *p;
++
++ nr_dentry *= 2;
++ p = krealloc(path, nr_dentry * sizeof(struct dentry *),
++ GFP_KERNEL);
++ if (unlikely(!p)) {
++ lower_dentry = ERR_PTR(-ENOMEM);
++ goto out;
++ }
++ path = p;
++ }
++
++ /* store the child dentry */
++ path[count++] = child_dentry;
++ } while (!lower_parent_dentry);
++ count--;
++
++ sb = dentry->d_sb;
++
++ /*
++ * This code goes between the begin/end labels and basically
++ * emulates a while(child_dentry != dentry), only cleaner and
++ * shorter than what would be a much longer while loop.
++ */
++begin:
++ /* get lower parent dir in the current branch */
++ lower_parent_dentry = unionfs_lower_dentry_idx(parent_dentry, bindex);
++ dput(parent_dentry);
++
++ /* init the values to lookup */
++ childname = child_dentry->d_name.name;
++ childnamelen = child_dentry->d_name.len;
++
++ if (child_dentry != dentry) {
++ /* lookup child in the underlying file system */
++ lower_dentry = lookup_lck_len(childname, lower_parent_dentry,
++ childnamelen);
++ if (IS_ERR(lower_dentry))
++ goto out;
++ } else {
++ /*
++ * Is the name a whiteout of the child name ? lookup the
++ * whiteout child in the underlying file system
++ */
++ lower_dentry = lookup_lck_len(name, lower_parent_dentry,
++ strlen(name));
++ if (IS_ERR(lower_dentry))
++ goto out;
++
++ /* Replace the current dentry (if any) with the new one */
++ dput(unionfs_lower_dentry_idx(dentry, bindex));
++ unionfs_set_lower_dentry_idx(dentry, bindex,
++ lower_dentry);
++
++ __cleanup_dentry(dentry, bindex, old_bstart, old_bend);
++ goto out;
++ }
++
++ if (lower_dentry->d_inode) {
++ /*
++ * since this already exists we dput to avoid
++ * multiple references on the same dentry
++ */
++ dput(lower_dentry);
++ } else {
++ struct sioq_args args;
++
++ /* it's a negative dentry, create a new dir */
++ lower_parent_dentry = lock_parent(lower_dentry);
++
++ args.mkdir.parent = lower_parent_dentry->d_inode;
++ args.mkdir.dentry = lower_dentry;
++ args.mkdir.mode = child_dentry->d_inode->i_mode;
++
++ run_sioq(__unionfs_mkdir, &args);
++ err = args.err;
++
++ if (!err)
++ err = copyup_permissions(dir->i_sb, child_dentry,
++ lower_dentry);
++ unlock_dir(lower_parent_dentry);
++ if (err) {
++ dput(lower_dentry);
++ lower_dentry = ERR_PTR(err);
++ goto out;
++ }
++
++ }
++
++ __set_inode(child_dentry, lower_dentry, bindex);
++ __set_dentry(child_dentry, lower_dentry, bindex);
++ /*
++ * update times of this dentry, but also the parent, because if
++ * we changed, the parent may have changed too.
++ */
++ fsstack_copy_attr_times(parent_dentry->d_inode,
++ lower_parent_dentry->d_inode);
++ unionfs_copy_attr_times(child_dentry->d_inode);
++
++ parent_dentry = child_dentry;
++ child_dentry = path[--count];
++ goto begin;
++out:
++ /* cleanup any leftover locks from the do/while loop above */
++ if (IS_ERR(lower_dentry))
++ while (count)
++ dput(path[count--]);
++ kfree(path);
++ return lower_dentry;
++}
++
++/*
++ * Post-copyup helper to ensure we have valid mnts: set lower mnt of
++ * dentry+parents to the first parent node that has an mnt.
++ */
++void unionfs_postcopyup_setmnt(struct dentry *dentry)
++{
++ struct dentry *parent, *hasone;
++ int bindex = dbstart(dentry);
++
++ if (unionfs_lower_mnt_idx(dentry, bindex))
++ return;
++ hasone = dentry->d_parent;
++ /* this loop should stop at root dentry */
++ while (!unionfs_lower_mnt_idx(hasone, bindex))
++ hasone = hasone->d_parent;
++ parent = dentry;
++ while (!unionfs_lower_mnt_idx(parent, bindex)) {
++ unionfs_set_lower_mnt_idx(parent, bindex,
++ unionfs_mntget(hasone, bindex));
++ parent = parent->d_parent;
++ }
++}
++
++/*
++ * Post-copyup helper to release all non-directory source objects of a
++ * copied-up file. Regular files should have only one lower object.
++ */
++void unionfs_postcopyup_release(struct dentry *dentry)
++{
++ int bstart, bend;
++
++ BUG_ON(S_ISDIR(dentry->d_inode->i_mode));
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++
++ path_put_lowers(dentry, bstart + 1, bend, false);
++ iput_lowers(dentry->d_inode, bstart + 1, bend, false);
++
++ dbend(dentry) = bstart;
++ ibend(dentry->d_inode) = ibstart(dentry->d_inode) = bstart;
++}
+diff --git a/fs/unionfs/debug.c b/fs/unionfs/debug.c
+new file mode 100644
+index 0000000..100d2c6
+--- /dev/null
++++ b/fs/unionfs/debug.c
+@@ -0,0 +1,532 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++/*
++ * Helper debugging functions for maintainers (and for users to report back
++ * useful information back to maintainers)
++ */
++
++/* it's always useful to know what part of the code called us */
++#define PRINT_CALLER(fname, fxn, line) \
++ do { \
++ if (!printed_caller) { \
++ pr_debug("PC:%s:%s:%d\n", (fname), (fxn), (line)); \
++ printed_caller = 1; \
++ } \
++ } while (0)
++
++/*
++ * __unionfs_check_{inode,dentry,file} perform exhaustive sanity checking on
++ * the fan-out of various Unionfs objects. We check that no lower objects
++ * exist outside the start/end branch range; that all objects within are
++ * non-NULL (with some allowed exceptions); that for every lower file
++ * there's a lower dentry+inode; that the start/end ranges match for all
++ * corresponding lower objects; that open files/symlinks have only one lower
++ * objects, but directories can have several; and more.
++ */
++void __unionfs_check_inode(const struct inode *inode,
++ const char *fname, const char *fxn, int line)
++{
++ int bindex;
++ int istart, iend;
++ struct inode *lower_inode;
++ struct super_block *sb;
++ int printed_caller = 0;
++ void *poison_ptr;
++
++ /* for inodes now */
++ BUG_ON(!inode);
++ sb = inode->i_sb;
++ istart = ibstart(inode);
++ iend = ibend(inode);
++ /* don't check inode if no lower branches */
++ if (istart < 0 && iend < 0)
++ return;
++ if (unlikely(istart > iend)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Ci0: inode=%p istart/end=%d:%d\n",
++ inode, istart, iend);
++ }
++ if (unlikely((istart == -1 && iend != -1) ||
++ (istart != -1 && iend == -1))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Ci1: inode=%p istart/end=%d:%d\n",
++ inode, istart, iend);
++ }
++ if (!S_ISDIR(inode->i_mode)) {
++ if (unlikely(iend != istart)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Ci2: inode=%p istart=%d iend=%d\n",
++ inode, istart, iend);
++ }
++ }
++
++ for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
++ if (unlikely(!UNIONFS_I(inode))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Ci3: no inode_info %p\n", inode);
++ return;
++ }
++ if (unlikely(!UNIONFS_I(inode)->lower_inodes)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Ci4: no lower_inodes %p\n", inode);
++ return;
++ }
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (lower_inode) {
++ memset(&poison_ptr, POISON_INUSE, sizeof(void *));
++ if (unlikely(bindex < istart || bindex > iend)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Ci5: inode/linode=%p:%p bindex=%d "
++ "istart/end=%d:%d\n", inode,
++ lower_inode, bindex, istart, iend);
++ } else if (unlikely(lower_inode == poison_ptr)) {
++ /* freed inode! */
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Ci6: inode/linode=%p:%p bindex=%d "
++ "istart/end=%d:%d\n", inode,
++ lower_inode, bindex, istart, iend);
++ }
++ continue;
++ }
++ /* if we get here, then lower_inode == NULL */
++ if (bindex < istart || bindex > iend)
++ continue;
++ /*
++ * directories can have NULL lower inodes in b/t start/end,
++ * but NOT if at the start/end range.
++ */
++ if (unlikely(S_ISDIR(inode->i_mode) &&
++ bindex > istart && bindex < iend))
++ continue;
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Ci7: inode/linode=%p:%p "
++ "bindex=%d istart/end=%d:%d\n",
++ inode, lower_inode, bindex, istart, iend);
++ }
++}
++
++void __unionfs_check_dentry(const struct dentry *dentry,
++ const char *fname, const char *fxn, int line)
++{
++ int bindex;
++ int dstart, dend, istart, iend;
++ struct dentry *lower_dentry;
++ struct inode *inode, *lower_inode;
++ struct super_block *sb;
++ struct vfsmount *lower_mnt;
++ int printed_caller = 0;
++ void *poison_ptr;
++
++ BUG_ON(!dentry);
++ sb = dentry->d_sb;
++ inode = dentry->d_inode;
++ dstart = dbstart(dentry);
++ dend = dbend(dentry);
++ /* don't check dentry/mnt if no lower branches */
++ if (dstart < 0 && dend < 0)
++ goto check_inode;
++ BUG_ON(dstart > dend);
++
++ if (unlikely((dstart == -1 && dend != -1) ||
++ (dstart != -1 && dend == -1))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CD0: dentry=%p dstart/end=%d:%d\n",
++ dentry, dstart, dend);
++ }
++ /*
++ * check for NULL dentries inside the start/end range, or
++ * non-NULL dentries outside the start/end range.
++ */
++ for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (lower_dentry) {
++ if (unlikely(bindex < dstart || bindex > dend)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CD1: dentry/lower=%p:%p(%p) "
++ "bindex=%d dstart/end=%d:%d\n",
++ dentry, lower_dentry,
++ (lower_dentry ? lower_dentry->d_inode :
++ (void *) -1L),
++ bindex, dstart, dend);
++ }
++ } else { /* lower_dentry == NULL */
++ if (bindex < dstart || bindex > dend)
++ continue;
++ /*
++ * Directories can have NULL lower inodes in b/t
++ * start/end, but NOT if at the start/end range.
++ * Ignore this rule, however, if this is a NULL
++ * dentry or a deleted dentry.
++ */
++ if (unlikely(!d_deleted((struct dentry *) dentry) &&
++ inode &&
++ !(inode && S_ISDIR(inode->i_mode) &&
++ bindex > dstart && bindex < dend))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CD2: dentry/lower=%p:%p(%p) "
++ "bindex=%d dstart/end=%d:%d\n",
++ dentry, lower_dentry,
++ (lower_dentry ?
++ lower_dentry->d_inode :
++ (void *) -1L),
++ bindex, dstart, dend);
++ }
++ }
++ }
++
++ /* check for vfsmounts same as for dentries */
++ for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
++ lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
++ if (lower_mnt) {
++ if (unlikely(bindex < dstart || bindex > dend)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CM0: dentry/lmnt=%p:%p bindex=%d "
++ "dstart/end=%d:%d\n", dentry,
++ lower_mnt, bindex, dstart, dend);
++ }
++ } else { /* lower_mnt == NULL */
++ if (bindex < dstart || bindex > dend)
++ continue;
++ /*
++ * Directories can have NULL lower inodes in b/t
++ * start/end, but NOT if at the start/end range.
++ * Ignore this rule, however, if this is a NULL
++ * dentry.
++ */
++ if (unlikely(inode &&
++ !(inode && S_ISDIR(inode->i_mode) &&
++ bindex > dstart && bindex < dend))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CM1: dentry/lmnt=%p:%p "
++ "bindex=%d dstart/end=%d:%d\n",
++ dentry, lower_mnt, bindex,
++ dstart, dend);
++ }
++ }
++ }
++
++check_inode:
++ /* for inodes now */
++ if (!inode)
++ return;
++ istart = ibstart(inode);
++ iend = ibend(inode);
++ /* don't check inode if no lower branches */
++ if (istart < 0 && iend < 0)
++ return;
++ BUG_ON(istart > iend);
++ if (unlikely((istart == -1 && iend != -1) ||
++ (istart != -1 && iend == -1))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CI0: dentry/inode=%p:%p istart/end=%d:%d\n",
++ dentry, inode, istart, iend);
++ }
++ if (unlikely(istart != dstart)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CI1: dentry/inode=%p:%p istart=%d dstart=%d\n",
++ dentry, inode, istart, dstart);
++ }
++ if (unlikely(iend != dend)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CI2: dentry/inode=%p:%p iend=%d dend=%d\n",
++ dentry, inode, iend, dend);
++ }
++
++ if (!S_ISDIR(inode->i_mode)) {
++ if (unlikely(dend != dstart)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CI3: dentry/inode=%p:%p dstart=%d dend=%d\n",
++ dentry, inode, dstart, dend);
++ }
++ if (unlikely(iend != istart)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CI4: dentry/inode=%p:%p istart=%d iend=%d\n",
++ dentry, inode, istart, iend);
++ }
++ }
++
++ for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (lower_inode) {
++ memset(&poison_ptr, POISON_INUSE, sizeof(void *));
++ if (unlikely(bindex < istart || bindex > iend)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CI5: dentry/linode=%p:%p bindex=%d "
++ "istart/end=%d:%d\n", dentry,
++ lower_inode, bindex, istart, iend);
++ } else if (unlikely(lower_inode == poison_ptr)) {
++ /* freed inode! */
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CI6: dentry/linode=%p:%p bindex=%d "
++ "istart/end=%d:%d\n", dentry,
++ lower_inode, bindex, istart, iend);
++ }
++ continue;
++ }
++ /* if we get here, then lower_inode == NULL */
++ if (bindex < istart || bindex > iend)
++ continue;
++ /*
++ * directories can have NULL lower inodes in b/t start/end,
++ * but NOT if at the start/end range.
++ */
++ if (unlikely(S_ISDIR(inode->i_mode) &&
++ bindex > istart && bindex < iend))
++ continue;
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CI7: dentry/linode=%p:%p "
++ "bindex=%d istart/end=%d:%d\n",
++ dentry, lower_inode, bindex, istart, iend);
++ }
++
++ /*
++ * If it's a directory, then intermediate objects b/t start/end can
++ * be NULL. But, check that all three are NULL: lower dentry, mnt,
++ * and inode.
++ */
++ if (dstart >= 0 && dend >= 0 && S_ISDIR(inode->i_mode))
++ for (bindex = dstart+1; bindex < dend; bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ lower_dentry = unionfs_lower_dentry_idx(dentry,
++ bindex);
++ lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
++ if (unlikely(!((lower_inode && lower_dentry &&
++ lower_mnt) ||
++ (!lower_inode &&
++ !lower_dentry && !lower_mnt)))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" Cx: lmnt/ldentry/linode=%p:%p:%p "
++ "bindex=%d dstart/end=%d:%d\n",
++ lower_mnt, lower_dentry, lower_inode,
++ bindex, dstart, dend);
++ }
++ }
++ /* check if lower inode is newer than upper one (it shouldn't) */
++ if (unlikely(is_newer_lower(dentry) && !is_negative_lower(dentry))) {
++ PRINT_CALLER(fname, fxn, line);
++ for (bindex = ibstart(inode); bindex <= ibend(inode);
++ bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (unlikely(!lower_inode))
++ continue;
++ pr_debug(" CI8: bindex=%d mtime/lmtime=%lu.%lu/%lu.%lu "
++ "ctime/lctime=%lu.%lu/%lu.%lu\n",
++ bindex,
++ inode->i_mtime.tv_sec,
++ inode->i_mtime.tv_nsec,
++ lower_inode->i_mtime.tv_sec,
++ lower_inode->i_mtime.tv_nsec,
++ inode->i_ctime.tv_sec,
++ inode->i_ctime.tv_nsec,
++ lower_inode->i_ctime.tv_sec,
++ lower_inode->i_ctime.tv_nsec);
++ }
++ }
++}
++
++void __unionfs_check_file(const struct file *file,
++ const char *fname, const char *fxn, int line)
++{
++ int bindex;
++ int dstart, dend, fstart, fend;
++ struct dentry *dentry;
++ struct file *lower_file;
++ struct inode *inode;
++ struct super_block *sb;
++ int printed_caller = 0;
++
++ BUG_ON(!file);
++ dentry = file->f_path.dentry;
++ sb = dentry->d_sb;
++ dstart = dbstart(dentry);
++ dend = dbend(dentry);
++ BUG_ON(dstart > dend);
++ fstart = fbstart(file);
++ fend = fbend(file);
++ BUG_ON(fstart > fend);
++
++ if (unlikely((fstart == -1 && fend != -1) ||
++ (fstart != -1 && fend == -1))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CF0: file/dentry=%p:%p fstart/end=%d:%d\n",
++ file, dentry, fstart, fend);
++ }
++ if (unlikely(fstart != dstart)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CF1: file/dentry=%p:%p fstart=%d dstart=%d\n",
++ file, dentry, fstart, dstart);
++ }
++ if (unlikely(fend != dend)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CF2: file/dentry=%p:%p fend=%d dend=%d\n",
++ file, dentry, fend, dend);
++ }
++ inode = dentry->d_inode;
++ if (!S_ISDIR(inode->i_mode)) {
++ if (unlikely(fend != fstart)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CF3: file/inode=%p:%p fstart=%d fend=%d\n",
++ file, inode, fstart, fend);
++ }
++ if (unlikely(dend != dstart)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CF4: file/dentry=%p:%p dstart=%d dend=%d\n",
++ file, dentry, dstart, dend);
++ }
++ }
++
++ /*
++ * check for NULL dentries inside the start/end range, or
++ * non-NULL dentries outside the start/end range.
++ */
++ for (bindex = sbstart(sb); bindex < sbmax(sb); bindex++) {
++ lower_file = unionfs_lower_file_idx(file, bindex);
++ if (lower_file) {
++ if (unlikely(bindex < fstart || bindex > fend)) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CF5: file/lower=%p:%p bindex=%d "
++ "fstart/end=%d:%d\n", file,
++ lower_file, bindex, fstart, fend);
++ }
++ } else { /* lower_file == NULL */
++ if (bindex >= fstart && bindex <= fend) {
++ /*
++ * directories can have NULL lower inodes in
++ * b/t start/end, but NOT if at the
++ * start/end range.
++ */
++ if (unlikely(!(S_ISDIR(inode->i_mode) &&
++ bindex > fstart &&
++ bindex < fend))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CF6: file/lower=%p:%p "
++ "bindex=%d fstart/end=%d:%d\n",
++ file, lower_file, bindex,
++ fstart, fend);
++ }
++ }
++ }
++ }
++
++ __unionfs_check_dentry(dentry, fname, fxn, line);
++}
++
++void __unionfs_check_nd(const struct nameidata *nd,
++ const char *fname, const char *fxn, int line)
++{
++ struct file *file;
++ int printed_caller = 0;
++
++ if (unlikely(!nd))
++ return;
++ if (nd->flags & LOOKUP_OPEN) {
++ file = nd->intent.open.file;
++ if (unlikely(file->f_path.dentry &&
++ strcmp(file->f_path.dentry->d_sb->s_type->name,
++ UNIONFS_NAME))) {
++ PRINT_CALLER(fname, fxn, line);
++ pr_debug(" CND1: lower_file of type %s\n",
++ file->f_path.dentry->d_sb->s_type->name);
++ }
++ }
++}
++
++/* useful to track vfsmount leaks that could cause EBUSY on unmount */
++void __show_branch_counts(const struct super_block *sb,
++ const char *file, const char *fxn, int line)
++{
++ int i;
++ struct vfsmount *mnt;
++
++ pr_debug("BC:");
++ for (i = 0; i < sbmax(sb); i++) {
++ if (likely(sb->s_root))
++ mnt = UNIONFS_D(sb->s_root)->lower_paths[i].mnt;
++ else
++ mnt = NULL;
++ printk(KERN_CONT "%d:",
++ (mnt ? atomic_read(&mnt->mnt_count) : -99));
++ }
++ printk(KERN_CONT "%s:%s:%d\n", file, fxn, line);
++}
++
++void __show_inode_times(const struct inode *inode,
++ const char *file, const char *fxn, int line)
++{
++ struct inode *lower_inode;
++ int bindex;
++
++ for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (unlikely(!lower_inode))
++ continue;
++ pr_debug("IT(%lu:%d): %s:%s:%d "
++ "um=%lu/%lu lm=%lu/%lu uc=%lu/%lu lc=%lu/%lu\n",
++ inode->i_ino, bindex,
++ file, fxn, line,
++ inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
++ lower_inode->i_mtime.tv_sec,
++ lower_inode->i_mtime.tv_nsec,
++ inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
++ lower_inode->i_ctime.tv_sec,
++ lower_inode->i_ctime.tv_nsec);
++ }
++}
++
++void __show_dinode_times(const struct dentry *dentry,
++ const char *file, const char *fxn, int line)
++{
++ struct inode *inode = dentry->d_inode;
++ struct inode *lower_inode;
++ int bindex;
++
++ for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (!lower_inode)
++ continue;
++ pr_debug("DT(%s:%lu:%d): %s:%s:%d "
++ "um=%lu/%lu lm=%lu/%lu uc=%lu/%lu lc=%lu/%lu\n",
++ dentry->d_name.name, inode->i_ino, bindex,
++ file, fxn, line,
++ inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
++ lower_inode->i_mtime.tv_sec,
++ lower_inode->i_mtime.tv_nsec,
++ inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
++ lower_inode->i_ctime.tv_sec,
++ lower_inode->i_ctime.tv_nsec);
++ }
++}
++
++void __show_inode_counts(const struct inode *inode,
++ const char *file, const char *fxn, int line)
++{
++ struct inode *lower_inode;
++ int bindex;
++
++ if (unlikely(!inode)) {
++ pr_debug("SiC: Null inode\n");
++ return;
++ }
++ for (bindex = sbstart(inode->i_sb); bindex <= sbend(inode->i_sb);
++ bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (unlikely(!lower_inode))
++ continue;
++ pr_debug("SIC(%lu:%d:%d): lc=%d %s:%s:%d\n",
++ inode->i_ino, bindex,
++ atomic_read(&(inode)->i_count),
++ atomic_read(&(lower_inode)->i_count),
++ file, fxn, line);
++ }
++}
+diff --git a/fs/unionfs/dentry.c b/fs/unionfs/dentry.c
+new file mode 100644
+index 0000000..a0c3bba
+--- /dev/null
++++ b/fs/unionfs/dentry.c
+@@ -0,0 +1,397 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++bool is_negative_lower(const struct dentry *dentry)
++{
++ int bindex;
++ struct dentry *lower_dentry;
++
++ BUG_ON(!dentry);
++ /* cache coherency: check if file was deleted on lower branch */
++ if (dbstart(dentry) < 0)
++ return true;
++ for (bindex = dbstart(dentry); bindex <= dbend(dentry); bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ /* unhashed (i.e., unlinked) lower dentries don't count */
++ if (lower_dentry && lower_dentry->d_inode &&
++ !d_deleted(lower_dentry) &&
++ !(lower_dentry->d_flags & DCACHE_NFSFS_RENAMED))
++ return false;
++ }
++ return true;
++}
++
++static inline void __dput_lowers(struct dentry *dentry, int start, int end)
++{
++ struct dentry *lower_dentry;
++ int bindex;
++
++ if (start < 0)
++ return;
++ for (bindex = start; bindex <= end; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry)
++ continue;
++ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
++ dput(lower_dentry);
++ }
++}
++
++/*
++ * Purge and invalidate as many data pages of a unionfs inode. This is
++ * called when the lower inode has changed, and we want to force processes
++ * to re-get the new data.
++ */
++static inline void purge_inode_data(struct inode *inode)
++{
++ /* remove all non-private mappings */
++ unmap_mapping_range(inode->i_mapping, 0, 0, 0);
++ /* invalidate as many pages as possible */
++ invalidate_mapping_pages(inode->i_mapping, 0, -1);
++ /*
++ * Don't try to truncate_inode_pages here, because this could lead
++ * to a deadlock between some of address_space ops and dentry
++ * revalidation: the address space op is invoked with a lock on our
++ * own page, and truncate_inode_pages will block on locked pages.
++ */
++}
++
++/*
++ * Revalidate a single file/symlink/special dentry. Assume that info nodes
++ * of the @dentry and its @parent are locked. Assume parent is valid,
++ * otherwise return false (and let's hope the VFS will try to re-lookup this
++ * dentry). Returns true if valid, false otherwise.
++ */
++bool __unionfs_d_revalidate(struct dentry *dentry, struct dentry *parent,
++ bool willwrite)
++{
++ bool valid = true; /* default is valid */
++ struct dentry *lower_dentry;
++ struct dentry *result;
++ int bindex, bstart, bend;
++ int sbgen, dgen, pdgen;
++ int positive = 0;
++ int interpose_flag;
++
++ verify_locked(dentry);
++ verify_locked(parent);
++
++ /* if the dentry is unhashed, do NOT revalidate */
++ if (d_deleted(dentry))
++ goto out;
++
++ dgen = atomic_read(&UNIONFS_D(dentry)->generation);
++
++ if (is_newer_lower(dentry)) {
++ /* root dentry is always valid */
++ if (IS_ROOT(dentry)) {
++ unionfs_copy_attr_times(dentry->d_inode);
++ } else {
++ /*
++ * reset generation number to zero, guaranteed to be
++ * "old"
++ */
++ dgen = 0;
++ atomic_set(&UNIONFS_D(dentry)->generation, dgen);
++ }
++ if (!willwrite)
++ purge_inode_data(dentry->d_inode);
++ }
++
++ sbgen = atomic_read(&UNIONFS_SB(dentry->d_sb)->generation);
++
++ BUG_ON(dbstart(dentry) == -1);
++ if (dentry->d_inode)
++ positive = 1;
++
++ /* if our dentry is valid, then validate all lower ones */
++ if (sbgen == dgen)
++ goto validate_lowers;
++
++ /* The root entry should always be valid */
++ BUG_ON(IS_ROOT(dentry));
++
++ /* We can't work correctly if our parent isn't valid. */
++ pdgen = atomic_read(&UNIONFS_D(parent)->generation);
++
++ /* Free the pointers for our inodes and this dentry. */
++ path_put_lowers_all(dentry, false);
++
++ interpose_flag = INTERPOSE_REVAL_NEG;
++ if (positive) {
++ interpose_flag = INTERPOSE_REVAL;
++ iput_lowers_all(dentry->d_inode, true);
++ }
++
++ if (realloc_dentry_private_data(dentry) != 0) {
++ valid = false;
++ goto out;
++ }
++
++ result = unionfs_lookup_full(dentry, parent, interpose_flag);
++ if (result) {
++ if (IS_ERR(result)) {
++ valid = false;
++ goto out;
++ }
++ /*
++ * current unionfs_lookup_backend() doesn't return
++ * a valid dentry
++ */
++ dput(dentry);
++ dentry = result;
++ }
++
++ if (unlikely(positive && is_negative_lower(dentry))) {
++ /* call make_bad_inode here ? */
++ d_drop(dentry);
++ valid = false;
++ goto out;
++ }
++
++ /*
++ * if we got here then we have revalidated our dentry and all lower
++ * ones, so we can return safely.
++ */
++ if (!valid) /* lower dentry revalidation failed */
++ goto out;
++
++ /*
++ * If the parent's gen no. matches the superblock's gen no., then
++ * we can update our denty's gen no. If they didn't match, then it
++ * was OK to revalidate this dentry with a stale parent, but we'll
++ * purposely not update our dentry's gen no. (so it can be redone);
++ * and, we'll mark our parent dentry as invalid so it'll force it
++ * (and our dentry) to be revalidated.
++ */
++ if (pdgen == sbgen)
++ atomic_set(&UNIONFS_D(dentry)->generation, sbgen);
++ goto out;
++
++validate_lowers:
++
++ /* The revalidation must occur across all branches */
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++ BUG_ON(bstart == -1);
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry || !lower_dentry->d_op
++ || !lower_dentry->d_op->d_revalidate)
++ continue;
++ /*
++ * Don't pass nameidata to lower file system, because we
++ * don't want an arbitrary lower file being opened or
++ * returned to us: it may be useless to us because of the
++ * fanout nature of unionfs (cf. file/directory open-file
++ * invariants). We will open lower files as and when needed
++ * later on.
++ */
++ if (!lower_dentry->d_op->d_revalidate(lower_dentry, NULL))
++ valid = false;
++ }
++
++ if (!dentry->d_inode ||
++ ibstart(dentry->d_inode) < 0 ||
++ ibend(dentry->d_inode) < 0) {
++ valid = false;
++ goto out;
++ }
++
++ if (valid) {
++ /*
++ * If we get here, and we copy the meta-data from the lower
++ * inode to our inode, then it is vital that we have already
++ * purged all unionfs-level file data. We do that in the
++ * caller (__unionfs_d_revalidate) by calling
++ * purge_inode_data.
++ */
++ unionfs_copy_attr_all(dentry->d_inode,
++ unionfs_lower_inode(dentry->d_inode));
++ fsstack_copy_inode_size(dentry->d_inode,
++ unionfs_lower_inode(dentry->d_inode));
++ }
++
++out:
++ return valid;
++}
++
++/*
++ * Determine if the lower inode objects have changed from below the unionfs
++ * inode. Return true if changed, false otherwise.
++ *
++ * We check if the mtime or ctime have changed. However, the inode times
++ * can be changed by anyone without much protection, including
++ * asynchronously. This can sometimes cause unionfs to find that the lower
++ * file system doesn't change its inode times quick enough, resulting in a
++ * false positive indication (which is harmless, it just makes unionfs do
++ * extra work in re-validating the objects). To minimize the chances of
++ * these situations, we still consider such small time changes valid, but we
++ * don't print debugging messages unless the time changes are greater than
++ * UNIONFS_MIN_CC_TIME (which defaults to 3 seconds, as with NFS's acregmin)
++ * because significant changes are more likely due to users manually
++ * touching lower files.
++ */
++bool is_newer_lower(const struct dentry *dentry)
++{
++ int bindex;
++ struct inode *inode;
++ struct inode *lower_inode;
++
++ /* ignore if we're called on semi-initialized dentries/inodes */
++ if (!dentry || !UNIONFS_D(dentry))
++ return false;
++ inode = dentry->d_inode;
++ if (!inode || !UNIONFS_I(inode)->lower_inodes ||
++ ibstart(inode) < 0 || ibend(inode) < 0)
++ return false;
++
++ for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (!lower_inode)
++ continue;
++
++ /* check if mtime/ctime have changed */
++ if (unlikely(timespec_compare(&inode->i_mtime,
++ &lower_inode->i_mtime) < 0)) {
++ if ((lower_inode->i_mtime.tv_sec -
++ inode->i_mtime.tv_sec) > UNIONFS_MIN_CC_TIME) {
++ pr_info("unionfs: new lower inode mtime "
++ "(bindex=%d, name=%s)\n", bindex,
++ dentry->d_name.name);
++ show_dinode_times(dentry);
++ }
++ return true;
++ }
++ if (unlikely(timespec_compare(&inode->i_ctime,
++ &lower_inode->i_ctime) < 0)) {
++ if ((lower_inode->i_ctime.tv_sec -
++ inode->i_ctime.tv_sec) > UNIONFS_MIN_CC_TIME) {
++ pr_info("unionfs: new lower inode ctime "
++ "(bindex=%d, name=%s)\n", bindex,
++ dentry->d_name.name);
++ show_dinode_times(dentry);
++ }
++ return true;
++ }
++ }
++
++ /*
++ * Last check: if this is a positive dentry, but somehow all lower
++ * dentries are negative or unhashed, then this dentry needs to be
++ * revalidated, because someone probably deleted the objects from
++ * the lower branches directly.
++ */
++ if (is_negative_lower(dentry))
++ return true;
++
++ return false; /* default: lower is not newer */
++}
++
++static int unionfs_d_revalidate(struct dentry *dentry,
++ struct nameidata *nd_unused)
++{
++ bool valid = true;
++ int err = 1; /* 1 means valid for the VFS */
++ struct dentry *parent;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (valid) {
++ unionfs_postcopyup_setmnt(dentry);
++ unionfs_check_dentry(dentry);
++ } else {
++ d_drop(dentry);
++ err = valid;
++ }
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++
++ return err;
++}
++
++static void unionfs_d_release(struct dentry *dentry)
++{
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ if (unlikely(!UNIONFS_D(dentry)))
++ goto out; /* skip if no lower branches */
++ /* must lock our branch configuration here */
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ unionfs_check_dentry(dentry);
++ /* this could be a negative dentry, so check first */
++ if (dbstart(dentry) < 0) {
++ unionfs_unlock_dentry(dentry);
++ goto out; /* due to a (normal) failed lookup */
++ }
++
++ /* Release all the lower dentries */
++ path_put_lowers_all(dentry, true);
++
++ unionfs_unlock_dentry(dentry);
++
++out:
++ free_dentry_private_data(dentry);
++ unionfs_read_unlock(dentry->d_sb);
++ return;
++}
++
++/*
++ * Called when we're removing the last reference to our dentry. So we
++ * should drop all lower references too.
++ */
++static void unionfs_d_iput(struct dentry *dentry, struct inode *inode)
++{
++ int rc;
++
++ BUG_ON(!dentry);
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ if (!UNIONFS_D(dentry) || dbstart(dentry) < 0)
++ goto drop_lower_inodes;
++ path_put_lowers_all(dentry, false);
++
++drop_lower_inodes:
++ rc = atomic_read(&inode->i_count);
++ if (rc == 1 && inode->i_nlink == 1 && ibstart(inode) >= 0) {
++ /* see Documentation/filesystems/unionfs/issues.txt */
++ lockdep_off();
++ iput(unionfs_lower_inode(inode));
++ lockdep_on();
++ unionfs_set_lower_inode(inode, NULL);
++ /* XXX: may need to set start/end to -1? */
++ }
++
++ iput(inode);
++
++ unionfs_unlock_dentry(dentry);
++ unionfs_read_unlock(dentry->d_sb);
++}
++
++struct dentry_operations unionfs_dops = {
++ .d_revalidate = unionfs_d_revalidate,
++ .d_release = unionfs_d_release,
++ .d_iput = unionfs_d_iput,
++};
+diff --git a/fs/unionfs/dirfops.c b/fs/unionfs/dirfops.c
+new file mode 100644
+index 0000000..7da0ff0
+--- /dev/null
++++ b/fs/unionfs/dirfops.c
+@@ -0,0 +1,302 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++/* Make sure our rdstate is playing by the rules. */
++static void verify_rdstate_offset(struct unionfs_dir_state *rdstate)
++{
++ BUG_ON(rdstate->offset >= DIREOF);
++ BUG_ON(rdstate->cookie >= MAXRDCOOKIE);
++}
++
++struct unionfs_getdents_callback {
++ struct unionfs_dir_state *rdstate;
++ void *dirent;
++ int entries_written;
++ int filldir_called;
++ int filldir_error;
++ filldir_t filldir;
++ struct super_block *sb;
++};
++
++/* based on generic filldir in fs/readir.c */
++static int unionfs_filldir(void *dirent, const char *oname, int namelen,
++ loff_t offset, u64 ino, unsigned int d_type)
++{
++ struct unionfs_getdents_callback *buf = dirent;
++ struct filldir_node *found = NULL;
++ int err = 0;
++ int is_whiteout;
++ char *name = (char *) oname;
++
++ buf->filldir_called++;
++
++ is_whiteout = is_whiteout_name(&name, &namelen);
++
++ found = find_filldir_node(buf->rdstate, name, namelen, is_whiteout);
++
++ if (found) {
++ /*
++ * If we had non-whiteout entry in dir cache, then mark it
++ * as a whiteout and but leave it in the dir cache.
++ */
++ if (is_whiteout && !found->whiteout)
++ found->whiteout = is_whiteout;
++ goto out;
++ }
++
++ /* if 'name' isn't a whiteout, filldir it. */
++ if (!is_whiteout) {
++ off_t pos = rdstate2offset(buf->rdstate);
++ u64 unionfs_ino = ino;
++
++ err = buf->filldir(buf->dirent, name, namelen, pos,
++ unionfs_ino, d_type);
++ buf->rdstate->offset++;
++ verify_rdstate_offset(buf->rdstate);
++ }
++ /*
++ * If we did fill it, stuff it in our hash, otherwise return an
++ * error.
++ */
++ if (err) {
++ buf->filldir_error = err;
++ goto out;
++ }
++ buf->entries_written++;
++ err = add_filldir_node(buf->rdstate, name, namelen,
++ buf->rdstate->bindex, is_whiteout);
++ if (err)
++ buf->filldir_error = err;
++
++out:
++ return err;
++}
++
++static int unionfs_readdir(struct file *file, void *dirent, filldir_t filldir)
++{
++ int err = 0;
++ struct file *lower_file = NULL;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++ struct inode *inode = NULL;
++ struct unionfs_getdents_callback buf;
++ struct unionfs_dir_state *uds;
++ int bend;
++ loff_t offset;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, false);
++ if (unlikely(err))
++ goto out;
++
++ inode = dentry->d_inode;
++
++ uds = UNIONFS_F(file)->rdstate;
++ if (!uds) {
++ if (file->f_pos == DIREOF) {
++ goto out;
++ } else if (file->f_pos > 0) {
++ uds = find_rdstate(inode, file->f_pos);
++ if (unlikely(!uds)) {
++ err = -ESTALE;
++ goto out;
++ }
++ UNIONFS_F(file)->rdstate = uds;
++ } else {
++ init_rdstate(file);
++ uds = UNIONFS_F(file)->rdstate;
++ }
++ }
++ bend = fbend(file);
++
++ while (uds->bindex <= bend) {
++ lower_file = unionfs_lower_file_idx(file, uds->bindex);
++ if (!lower_file) {
++ uds->bindex++;
++ uds->dirpos = 0;
++ continue;
++ }
++
++ /* prepare callback buffer */
++ buf.filldir_called = 0;
++ buf.filldir_error = 0;
++ buf.entries_written = 0;
++ buf.dirent = dirent;
++ buf.filldir = filldir;
++ buf.rdstate = uds;
++ buf.sb = inode->i_sb;
++
++ /* Read starting from where we last left off. */
++ offset = vfs_llseek(lower_file, uds->dirpos, SEEK_SET);
++ if (offset < 0) {
++ err = offset;
++ goto out;
++ }
++ err = vfs_readdir(lower_file, unionfs_filldir, &buf);
++
++ /* Save the position for when we continue. */
++ offset = vfs_llseek(lower_file, 0, SEEK_CUR);
++ if (offset < 0) {
++ err = offset;
++ goto out;
++ }
++ uds->dirpos = offset;
++
++ /* Copy the atime. */
++ fsstack_copy_attr_atime(inode,
++ lower_file->f_path.dentry->d_inode);
++
++ if (err < 0)
++ goto out;
++
++ if (buf.filldir_error)
++ break;
++
++ if (!buf.entries_written) {
++ uds->bindex++;
++ uds->dirpos = 0;
++ }
++ }
++
++ if (!buf.filldir_error && uds->bindex >= bend) {
++ /* Save the number of hash entries for next time. */
++ UNIONFS_I(inode)->hashsize = uds->hashentries;
++ free_rdstate(uds);
++ UNIONFS_F(file)->rdstate = NULL;
++ file->f_pos = DIREOF;
++ } else {
++ file->f_pos = rdstate2offset(uds);
++ }
++
++out:
++ if (!err)
++ unionfs_check_file(file);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++/*
++ * This is not meant to be a generic repositioning function. If you do
++ * things that aren't supported, then we return EINVAL.
++ *
++ * What is allowed:
++ * (1) seeking to the same position that you are currently at
++ * This really has no effect, but returns where you are.
++ * (2) seeking to the beginning of the file
++ * This throws out all state, and lets you begin again.
++ */
++static loff_t unionfs_dir_llseek(struct file *file, loff_t offset, int origin)
++{
++ struct unionfs_dir_state *rdstate;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++ loff_t err;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, false);
++ if (unlikely(err))
++ goto out;
++
++ rdstate = UNIONFS_F(file)->rdstate;
++
++ /*
++ * we let users seek to their current position, but not anywhere
++ * else.
++ */
++ if (!offset) {
++ switch (origin) {
++ case SEEK_SET:
++ if (rdstate) {
++ free_rdstate(rdstate);
++ UNIONFS_F(file)->rdstate = NULL;
++ }
++ init_rdstate(file);
++ err = 0;
++ break;
++ case SEEK_CUR:
++ err = file->f_pos;
++ break;
++ case SEEK_END:
++ /* Unsupported, because we would break everything. */
++ err = -EINVAL;
++ break;
++ }
++ } else {
++ switch (origin) {
++ case SEEK_SET:
++ if (rdstate) {
++ if (offset == rdstate2offset(rdstate))
++ err = offset;
++ else if (file->f_pos == DIREOF)
++ err = DIREOF;
++ else
++ err = -EINVAL;
++ } else {
++ struct inode *inode;
++ inode = dentry->d_inode;
++ rdstate = find_rdstate(inode, offset);
++ if (rdstate) {
++ UNIONFS_F(file)->rdstate = rdstate;
++ err = rdstate->offset;
++ } else {
++ err = -EINVAL;
++ }
++ }
++ break;
++ case SEEK_CUR:
++ case SEEK_END:
++ /* Unsupported, because we would break everything. */
++ err = -EINVAL;
++ break;
++ }
++ }
++
++out:
++ if (!err)
++ unionfs_check_file(file);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++/*
++ * Trimmed directory options, we shouldn't pass everything down since
++ * we don't want to operate on partial directories.
++ */
++struct file_operations unionfs_dir_fops = {
++ .llseek = unionfs_dir_llseek,
++ .read = generic_read_dir,
++ .readdir = unionfs_readdir,
++ .unlocked_ioctl = unionfs_ioctl,
++ .open = unionfs_open,
++ .release = unionfs_file_release,
++ .flush = unionfs_flush,
++ .fsync = unionfs_fsync,
++ .fasync = unionfs_fasync,
++};
+diff --git a/fs/unionfs/dirhelper.c b/fs/unionfs/dirhelper.c
+new file mode 100644
+index 0000000..033343b
+--- /dev/null
++++ b/fs/unionfs/dirhelper.c
+@@ -0,0 +1,158 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++#define RD_NONE 0
++#define RD_CHECK_EMPTY 1
++/* The callback structure for check_empty. */
++struct unionfs_rdutil_callback {
++ int err;
++ int filldir_called;
++ struct unionfs_dir_state *rdstate;
++ int mode;
++};
++
++/* This filldir function makes sure only whiteouts exist within a directory. */
++static int readdir_util_callback(void *dirent, const char *oname, int namelen,
++ loff_t offset, u64 ino, unsigned int d_type)
++{
++ int err = 0;
++ struct unionfs_rdutil_callback *buf = dirent;
++ int is_whiteout;
++ struct filldir_node *found;
++ char *name = (char *) oname;
++
++ buf->filldir_called = 1;
++
++ if (name[0] == '.' && (namelen == 1 ||
++ (name[1] == '.' && namelen == 2)))
++ goto out;
++
++ is_whiteout = is_whiteout_name(&name, &namelen);
++
++ found = find_filldir_node(buf->rdstate, name, namelen, is_whiteout);
++ /* If it was found in the table there was a previous whiteout. */
++ if (found)
++ goto out;
++
++ /*
++ * if it wasn't found and isn't a whiteout, the directory isn't
++ * empty.
++ */
++ err = -ENOTEMPTY;
++ if ((buf->mode == RD_CHECK_EMPTY) && !is_whiteout)
++ goto out;
++
++ err = add_filldir_node(buf->rdstate, name, namelen,
++ buf->rdstate->bindex, is_whiteout);
++
++out:
++ buf->err = err;
++ return err;
++}
++
++/* Is a directory logically empty? */
++int check_empty(struct dentry *dentry, struct dentry *parent,
++ struct unionfs_dir_state **namelist)
++{
++ int err = 0;
++ struct dentry *lower_dentry = NULL;
++ struct vfsmount *mnt;
++ struct super_block *sb;
++ struct file *lower_file;
++ struct unionfs_rdutil_callback *buf = NULL;
++ int bindex, bstart, bend, bopaque;
++
++ sb = dentry->d_sb;
++
++
++ BUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
++
++ err = unionfs_partial_lookup(dentry, parent);
++ if (err)
++ goto out;
++
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++ bopaque = dbopaque(dentry);
++ if (0 <= bopaque && bopaque < bend)
++ bend = bopaque;
++
++ buf = kmalloc(sizeof(struct unionfs_rdutil_callback), GFP_KERNEL);
++ if (unlikely(!buf)) {
++ err = -ENOMEM;
++ goto out;
++ }
++ buf->err = 0;
++ buf->mode = RD_CHECK_EMPTY;
++ buf->rdstate = alloc_rdstate(dentry->d_inode, bstart);
++ if (unlikely(!buf->rdstate)) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ /* Process the lower directories with rdutil_callback as a filldir. */
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry)
++ continue;
++ if (!lower_dentry->d_inode)
++ continue;
++ if (!S_ISDIR(lower_dentry->d_inode->i_mode))
++ continue;
++
++ dget(lower_dentry);
++ mnt = unionfs_mntget(dentry, bindex);
++ branchget(sb, bindex);
++ lower_file = dentry_open(lower_dentry, mnt, O_RDONLY, current_cred());
++ if (IS_ERR(lower_file)) {
++ err = PTR_ERR(lower_file);
++ branchput(sb, bindex);
++ goto out;
++ }
++
++ do {
++ buf->filldir_called = 0;
++ buf->rdstate->bindex = bindex;
++ err = vfs_readdir(lower_file,
++ readdir_util_callback, buf);
++ if (buf->err)
++ err = buf->err;
++ } while ((err >= 0) && buf->filldir_called);
++
++ /* fput calls dput for lower_dentry */
++ fput(lower_file);
++ branchput(sb, bindex);
++
++ if (err < 0)
++ goto out;
++ }
++
++out:
++ if (buf) {
++ if (namelist && !err)
++ *namelist = buf->rdstate;
++ else if (buf->rdstate)
++ free_rdstate(buf->rdstate);
++ kfree(buf);
++ }
++
++
++ return err;
++}
+diff --git a/fs/unionfs/fanout.h b/fs/unionfs/fanout.h
+new file mode 100644
+index 0000000..5b77eac
+--- /dev/null
++++ b/fs/unionfs/fanout.h
+@@ -0,0 +1,407 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#ifndef _FANOUT_H_
++#define _FANOUT_H_
++
++/*
++ * Inode to private data
++ *
++ * Since we use containers and the struct inode is _inside_ the
++ * unionfs_inode_info structure, UNIONFS_I will always (given a non-NULL
++ * inode pointer), return a valid non-NULL pointer.
++ */
++static inline struct unionfs_inode_info *UNIONFS_I(const struct inode *inode)
++{
++ return container_of(inode, struct unionfs_inode_info, vfs_inode);
++}
++
++#define ibstart(ino) (UNIONFS_I(ino)->bstart)
++#define ibend(ino) (UNIONFS_I(ino)->bend)
++
++/* Dentry to private data */
++#define UNIONFS_D(dent) ((struct unionfs_dentry_info *)(dent)->d_fsdata)
++#define dbstart(dent) (UNIONFS_D(dent)->bstart)
++#define dbend(dent) (UNIONFS_D(dent)->bend)
++#define dbopaque(dent) (UNIONFS_D(dent)->bopaque)
++
++/* Superblock to private data */
++#define UNIONFS_SB(super) ((struct unionfs_sb_info *)(super)->s_fs_info)
++#define sbstart(sb) 0
++#define sbend(sb) (UNIONFS_SB(sb)->bend)
++#define sbmax(sb) (UNIONFS_SB(sb)->bend + 1)
++#define sbhbid(sb) (UNIONFS_SB(sb)->high_branch_id)
++
++/* File to private Data */
++#define UNIONFS_F(file) ((struct unionfs_file_info *)((file)->private_data))
++#define fbstart(file) (UNIONFS_F(file)->bstart)
++#define fbend(file) (UNIONFS_F(file)->bend)
++
++/* macros to manipulate branch IDs in stored in our superblock */
++static inline int branch_id(struct super_block *sb, int index)
++{
++ BUG_ON(!sb || index < 0);
++ return UNIONFS_SB(sb)->data[index].branch_id;
++}
++
++static inline void set_branch_id(struct super_block *sb, int index, int val)
++{
++ BUG_ON(!sb || index < 0);
++ UNIONFS_SB(sb)->data[index].branch_id = val;
++}
++
++static inline void new_branch_id(struct super_block *sb, int index)
++{
++ BUG_ON(!sb || index < 0);
++ set_branch_id(sb, index, ++UNIONFS_SB(sb)->high_branch_id);
++}
++
++/*
++ * Find new index of matching branch with an existing superblock of a known
++ * (possibly old) id. This is needed because branches could have been
++ * added/deleted causing the branches of any open files to shift.
++ *
++ * @sb: the new superblock which may have new/different branch IDs
++ * @id: the old/existing id we're looking for
++ * Returns index of newly found branch (0 or greater), -1 otherwise.
++ */
++static inline int branch_id_to_idx(struct super_block *sb, int id)
++{
++ int i;
++ for (i = 0; i < sbmax(sb); i++) {
++ if (branch_id(sb, i) == id)
++ return i;
++ }
++ /* in the non-ODF code, this should really never happen */
++ printk(KERN_WARNING "unionfs: cannot find branch with id %d\n", id);
++ return -1;
++}
++
++/* File to lower file. */
++static inline struct file *unionfs_lower_file(const struct file *f)
++{
++ BUG_ON(!f);
++ return UNIONFS_F(f)->lower_files[fbstart(f)];
++}
++
++static inline struct file *unionfs_lower_file_idx(const struct file *f,
++ int index)
++{
++ BUG_ON(!f || index < 0);
++ return UNIONFS_F(f)->lower_files[index];
++}
++
++static inline void unionfs_set_lower_file_idx(struct file *f, int index,
++ struct file *val)
++{
++ BUG_ON(!f || index < 0);
++ UNIONFS_F(f)->lower_files[index] = val;
++ /* save branch ID (may be redundant?) */
++ UNIONFS_F(f)->saved_branch_ids[index] =
++ branch_id((f)->f_path.dentry->d_sb, index);
++}
++
++static inline void unionfs_set_lower_file(struct file *f, struct file *val)
++{
++ BUG_ON(!f);
++ unionfs_set_lower_file_idx((f), fbstart(f), (val));
++}
++
++/* Inode to lower inode. */
++static inline struct inode *unionfs_lower_inode(const struct inode *i)
++{
++ BUG_ON(!i);
++ return UNIONFS_I(i)->lower_inodes[ibstart(i)];
++}
++
++static inline struct inode *unionfs_lower_inode_idx(const struct inode *i,
++ int index)
++{
++ BUG_ON(!i || index < 0);
++ return UNIONFS_I(i)->lower_inodes[index];
++}
++
++static inline void unionfs_set_lower_inode_idx(struct inode *i, int index,
++ struct inode *val)
++{
++ BUG_ON(!i || index < 0);
++ UNIONFS_I(i)->lower_inodes[index] = val;
++}
++
++static inline void unionfs_set_lower_inode(struct inode *i, struct inode *val)
++{
++ BUG_ON(!i);
++ UNIONFS_I(i)->lower_inodes[ibstart(i)] = val;
++}
++
++/* Superblock to lower superblock. */
++static inline struct super_block *unionfs_lower_super(
++ const struct super_block *sb)
++{
++ BUG_ON(!sb);
++ return UNIONFS_SB(sb)->data[sbstart(sb)].sb;
++}
++
++static inline struct super_block *unionfs_lower_super_idx(
++ const struct super_block *sb,
++ int index)
++{
++ BUG_ON(!sb || index < 0);
++ return UNIONFS_SB(sb)->data[index].sb;
++}
++
++static inline void unionfs_set_lower_super_idx(struct super_block *sb,
++ int index,
++ struct super_block *val)
++{
++ BUG_ON(!sb || index < 0);
++ UNIONFS_SB(sb)->data[index].sb = val;
++}
++
++static inline void unionfs_set_lower_super(struct super_block *sb,
++ struct super_block *val)
++{
++ BUG_ON(!sb);
++ UNIONFS_SB(sb)->data[sbstart(sb)].sb = val;
++}
++
++/* Branch count macros. */
++static inline int branch_count(const struct super_block *sb, int index)
++{
++ BUG_ON(!sb || index < 0);
++ return atomic_read(&UNIONFS_SB(sb)->data[index].open_files);
++}
++
++static inline void set_branch_count(struct super_block *sb, int index, int val)
++{
++ BUG_ON(!sb || index < 0);
++ atomic_set(&UNIONFS_SB(sb)->data[index].open_files, val);
++}
++
++static inline void branchget(struct super_block *sb, int index)
++{
++ BUG_ON(!sb || index < 0);
++ atomic_inc(&UNIONFS_SB(sb)->data[index].open_files);
++}
++
++static inline void branchput(struct super_block *sb, int index)
++{
++ BUG_ON(!sb || index < 0);
++ atomic_dec(&UNIONFS_SB(sb)->data[index].open_files);
++}
++
++/* Dentry macros */
++static inline void unionfs_set_lower_dentry_idx(struct dentry *dent, int index,
++ struct dentry *val)
++{
++ BUG_ON(!dent || index < 0);
++ UNIONFS_D(dent)->lower_paths[index].dentry = val;
++}
++
++static inline struct dentry *unionfs_lower_dentry_idx(
++ const struct dentry *dent,
++ int index)
++{
++ BUG_ON(!dent || index < 0);
++ return UNIONFS_D(dent)->lower_paths[index].dentry;
++}
++
++static inline struct dentry *unionfs_lower_dentry(const struct dentry *dent)
++{
++ BUG_ON(!dent);
++ return unionfs_lower_dentry_idx(dent, dbstart(dent));
++}
++
++static inline void unionfs_set_lower_mnt_idx(struct dentry *dent, int index,
++ struct vfsmount *mnt)
++{
++ BUG_ON(!dent || index < 0);
++ UNIONFS_D(dent)->lower_paths[index].mnt = mnt;
++}
++
++static inline struct vfsmount *unionfs_lower_mnt_idx(
++ const struct dentry *dent,
++ int index)
++{
++ BUG_ON(!dent || index < 0);
++ return UNIONFS_D(dent)->lower_paths[index].mnt;
++}
++
++static inline struct vfsmount *unionfs_lower_mnt(const struct dentry *dent)
++{
++ BUG_ON(!dent);
++ return unionfs_lower_mnt_idx(dent, dbstart(dent));
++}
++
++/* Macros for locking a dentry. */
++enum unionfs_dentry_lock_class {
++ UNIONFS_DMUTEX_NORMAL,
++ UNIONFS_DMUTEX_ROOT,
++ UNIONFS_DMUTEX_PARENT,
++ UNIONFS_DMUTEX_CHILD,
++ UNIONFS_DMUTEX_WHITEOUT,
++ UNIONFS_DMUTEX_REVAL_PARENT, /* for file/dentry revalidate */
++ UNIONFS_DMUTEX_REVAL_CHILD, /* for file/dentry revalidate */
++};
++
++static inline void unionfs_lock_dentry(struct dentry *d,
++ unsigned int subclass)
++{
++ BUG_ON(!d);
++ mutex_lock_nested(&UNIONFS_D(d)->lock, subclass);
++}
++
++static inline void unionfs_unlock_dentry(struct dentry *d)
++{
++ BUG_ON(!d);
++ mutex_unlock(&UNIONFS_D(d)->lock);
++}
++
++static inline struct dentry *unionfs_lock_parent(struct dentry *d,
++ unsigned int subclass)
++{
++ struct dentry *p;
++
++ BUG_ON(!d);
++ p = dget_parent(d);
++ if (p != d)
++ mutex_lock_nested(&UNIONFS_D(p)->lock, subclass);
++ return p;
++}
++
++static inline void unionfs_unlock_parent(struct dentry *d, struct dentry *p)
++{
++ BUG_ON(!d);
++ BUG_ON(!p);
++ if (p != d) {
++ BUG_ON(!mutex_is_locked(&UNIONFS_D(p)->lock));
++ mutex_unlock(&UNIONFS_D(p)->lock);
++ }
++ dput(p);
++}
++
++static inline void verify_locked(struct dentry *d)
++{
++ BUG_ON(!d);
++ BUG_ON(!mutex_is_locked(&UNIONFS_D(d)->lock));
++}
++
++/* macros to put lower objects */
++
++/*
++ * iput lower inodes of an unionfs dentry, from bstart to bend. If
++ * @free_lower is true, then also kfree the memory used to hold the lower
++ * object pointers.
++ */
++static inline void iput_lowers(struct inode *inode,
++ int bstart, int bend, bool free_lower)
++{
++ struct inode *lower_inode;
++ int bindex;
++
++ BUG_ON(!inode);
++ BUG_ON(!UNIONFS_I(inode));
++ BUG_ON(bstart < 0);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (lower_inode) {
++ unionfs_set_lower_inode_idx(inode, bindex, NULL);
++ /* see Documentation/filesystems/unionfs/issues.txt */
++ lockdep_off();
++ iput(lower_inode);
++ lockdep_on();
++ }
++ }
++
++ if (free_lower) {
++ kfree(UNIONFS_I(inode)->lower_inodes);
++ UNIONFS_I(inode)->lower_inodes = NULL;
++ }
++}
++
++/* iput all lower inodes, and reset start/end branch indices to -1 */
++static inline void iput_lowers_all(struct inode *inode, bool free_lower)
++{
++ int bstart, bend;
++
++ BUG_ON(!inode);
++ BUG_ON(!UNIONFS_I(inode));
++ bstart = ibstart(inode);
++ bend = ibend(inode);
++ BUG_ON(bstart < 0);
++
++ iput_lowers(inode, bstart, bend, free_lower);
++ ibstart(inode) = ibend(inode) = -1;
++}
++
++/*
++ * dput/mntput all lower dentries and vfsmounts of an unionfs dentry, from
++ * bstart to bend. If @free_lower is true, then also kfree the memory used
++ * to hold the lower object pointers.
++ *
++ * XXX: implement using path_put VFS macros
++ */
++static inline void path_put_lowers(struct dentry *dentry,
++ int bstart, int bend, bool free_lower)
++{
++ struct dentry *lower_dentry;
++ struct vfsmount *lower_mnt;
++ int bindex;
++
++ BUG_ON(!dentry);
++ BUG_ON(!UNIONFS_D(dentry));
++ BUG_ON(bstart < 0);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (lower_dentry) {
++ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
++ dput(lower_dentry);
++ }
++ lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
++ if (lower_mnt) {
++ unionfs_set_lower_mnt_idx(dentry, bindex, NULL);
++ mntput(lower_mnt);
++ }
++ }
++
++ if (free_lower) {
++ kfree(UNIONFS_D(dentry)->lower_paths);
++ UNIONFS_D(dentry)->lower_paths = NULL;
++ }
++}
++
++/*
++ * dput/mntput all lower dentries and vfsmounts, and reset start/end branch
++ * indices to -1.
++ */
++static inline void path_put_lowers_all(struct dentry *dentry, bool free_lower)
++{
++ int bstart, bend;
++
++ BUG_ON(!dentry);
++ BUG_ON(!UNIONFS_D(dentry));
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++ BUG_ON(bstart < 0);
++
++ path_put_lowers(dentry, bstart, bend, free_lower);
++ dbstart(dentry) = dbend(dentry) = -1;
++}
++
++#endif /* not _FANOUT_H */
+diff --git a/fs/unionfs/file.c b/fs/unionfs/file.c
+new file mode 100644
+index 0000000..5a8f4e0
+--- /dev/null
++++ b/fs/unionfs/file.c
+@@ -0,0 +1,379 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++static ssize_t unionfs_read(struct file *file, char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ int err;
++ struct file *lower_file;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, false);
++ if (unlikely(err))
++ goto out;
++
++ lower_file = unionfs_lower_file(file);
++ err = vfs_read(lower_file, buf, count, ppos);
++ /* update our inode atime upon a successful lower read */
++ if (err >= 0) {
++ fsstack_copy_attr_atime(dentry->d_inode,
++ lower_file->f_path.dentry->d_inode);
++ unionfs_check_file(file);
++ }
++
++out:
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++static ssize_t unionfs_write(struct file *file, const char __user *buf,
++ size_t count, loff_t *ppos)
++{
++ int err = 0;
++ struct file *lower_file;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, true);
++ if (unlikely(err))
++ goto out;
++
++ lower_file = unionfs_lower_file(file);
++ err = vfs_write(lower_file, buf, count, ppos);
++ /* update our inode times+sizes upon a successful lower write */
++ if (err >= 0) {
++ fsstack_copy_inode_size(dentry->d_inode,
++ lower_file->f_path.dentry->d_inode);
++ fsstack_copy_attr_times(dentry->d_inode,
++ lower_file->f_path.dentry->d_inode);
++ UNIONFS_F(file)->wrote_to_file = true; /* for delayed copyup */
++ unionfs_check_file(file);
++ }
++
++out:
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++static int unionfs_file_readdir(struct file *file, void *dirent,
++ filldir_t filldir)
++{
++ return -ENOTDIR;
++}
++
++static int unionfs_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ int err = 0;
++ bool willwrite;
++ struct file *lower_file;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++ const struct vm_operations_struct *saved_vm_ops = NULL;
++
++ /*
++ * Since mm/memory.c:might_fault() (under PROVE_LOCKING) was
++ * modified in 2.6.29-rc1 to call might_lock_read on mmap_sem, this
++ * has been causing false positives in file system stacking layers.
++ * In particular, our ->mmap is called after sys_mmap2 already holds
++ * mmap_sem, then we lock our own mutexes; but earlier, it's
++ * possible for lockdep to have locked our mutexes first, and then
++ * we call a lower ->readdir which could call might_fault. The
++ * different ordering of the locks is what lockdep complains about
++ * -- unnecessarily. Therefore, we have no choice but to tell
++ * lockdep to temporarily turn off lockdep here. Note: the comments
++ * inside might_sleep also suggest that it would have been
++ * nicer to only annotate paths that needs that might_lock_read.
++ */
++ lockdep_off();
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ /* This might be deferred to mmap's writepage */
++ willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags);
++ err = unionfs_file_revalidate(file, parent, willwrite);
++ if (unlikely(err))
++ goto out;
++ unionfs_check_file(file);
++
++ /*
++ * File systems which do not implement ->writepage may use
++ * generic_file_readonly_mmap as their ->mmap op. If you call
++ * generic_file_readonly_mmap with VM_WRITE, you'd get an -EINVAL.
++ * But we cannot call the lower ->mmap op, so we can't tell that
++ * writeable mappings won't work. Therefore, our only choice is to
++ * check if the lower file system supports the ->writepage, and if
++ * not, return EINVAL (the same error that
++ * generic_file_readonly_mmap returns in that case).
++ */
++ lower_file = unionfs_lower_file(file);
++ if (willwrite && !lower_file->f_mapping->a_ops->writepage) {
++ err = -EINVAL;
++ printk(KERN_ERR "unionfs: branch %d file system does not "
++ "support writeable mmap\n", fbstart(file));
++ goto out;
++ }
++
++ /*
++ * find and save lower vm_ops.
++ *
++ * XXX: the VFS should have a cleaner way of finding the lower vm_ops
++ */
++ if (!UNIONFS_F(file)->lower_vm_ops) {
++ err = lower_file->f_op->mmap(lower_file, vma);
++ if (err) {
++ printk(KERN_ERR "unionfs: lower mmap failed %d\n", err);
++ goto out;
++ }
++ saved_vm_ops = vma->vm_ops;
++ err = do_munmap(current->mm, vma->vm_start,
++ vma->vm_end - vma->vm_start);
++ if (err) {
++ printk(KERN_ERR "unionfs: do_munmap failed %d\n", err);
++ goto out;
++ }
++ }
++
++ file->f_mapping->a_ops = &unionfs_dummy_aops;
++ err = generic_file_mmap(file, vma);
++ file->f_mapping->a_ops = &unionfs_aops;
++ if (err) {
++ printk(KERN_ERR "unionfs: generic_file_mmap failed %d\n", err);
++ goto out;
++ }
++ vma->vm_ops = &unionfs_vm_ops;
++ if (!UNIONFS_F(file)->lower_vm_ops)
++ UNIONFS_F(file)->lower_vm_ops = saved_vm_ops;
++
++out:
++ if (!err) {
++ /* copyup could cause parent dir times to change */
++ unionfs_copy_attr_times(parent->d_inode);
++ unionfs_check_file(file);
++ }
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ lockdep_on();
++ return err;
++}
++
++int unionfs_fsync(struct file *file, int datasync)
++{
++ int bindex, bstart, bend;
++ struct file *lower_file;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *lower_dentry;
++ struct dentry *parent;
++ struct inode *lower_inode, *inode;
++ int err = -EINVAL;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, true);
++ if (unlikely(err))
++ goto out;
++ unionfs_check_file(file);
++
++ bstart = fbstart(file);
++ bend = fbend(file);
++ if (bstart < 0 || bend < 0)
++ goto out;
++
++ inode = dentry->d_inode;
++ if (unlikely(!inode)) {
++ printk(KERN_ERR
++ "unionfs: null lower inode in unionfs_fsync\n");
++ goto out;
++ }
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (!lower_inode || !lower_inode->i_fop->fsync)
++ continue;
++ lower_file = unionfs_lower_file_idx(file, bindex);
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ mutex_lock(&lower_inode->i_mutex);
++ err = lower_inode->i_fop->fsync(lower_file, datasync);
++ if (!err && bindex == bstart)
++ fsstack_copy_attr_times(inode, lower_inode);
++ mutex_unlock(&lower_inode->i_mutex);
++ if (err)
++ goto out;
++ }
++
++out:
++ if (!err)
++ unionfs_check_file(file);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++int unionfs_fasync(int fd, struct file *file, int flag)
++{
++ int bindex, bstart, bend;
++ struct file *lower_file;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++ struct inode *lower_inode, *inode;
++ int err = 0;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, true);
++ if (unlikely(err))
++ goto out;
++ unionfs_check_file(file);
++
++ bstart = fbstart(file);
++ bend = fbend(file);
++ if (bstart < 0 || bend < 0)
++ goto out;
++
++ inode = dentry->d_inode;
++ if (unlikely(!inode)) {
++ printk(KERN_ERR
++ "unionfs: null lower inode in unionfs_fasync\n");
++ goto out;
++ }
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (!lower_inode || !lower_inode->i_fop->fasync)
++ continue;
++ lower_file = unionfs_lower_file_idx(file, bindex);
++ mutex_lock(&lower_inode->i_mutex);
++ err = lower_inode->i_fop->fasync(fd, lower_file, flag);
++ if (!err && bindex == bstart)
++ fsstack_copy_attr_times(inode, lower_inode);
++ mutex_unlock(&lower_inode->i_mutex);
++ if (err)
++ goto out;
++ }
++
++out:
++ if (!err)
++ unionfs_check_file(file);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++static ssize_t unionfs_splice_read(struct file *file, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags)
++{
++ ssize_t err;
++ struct file *lower_file;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, false);
++ if (unlikely(err))
++ goto out;
++
++ lower_file = unionfs_lower_file(file);
++ err = vfs_splice_to(lower_file, ppos, pipe, len, flags);
++ /* update our inode atime upon a successful lower splice-read */
++ if (err >= 0) {
++ fsstack_copy_attr_atime(dentry->d_inode,
++ lower_file->f_path.dentry->d_inode);
++ unionfs_check_file(file);
++ }
++
++out:
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++static ssize_t unionfs_splice_write(struct pipe_inode_info *pipe,
++ struct file *file, loff_t *ppos,
++ size_t len, unsigned int flags)
++{
++ ssize_t err = 0;
++ struct file *lower_file;
++ struct dentry *dentry = file->f_path.dentry;
++ struct dentry *parent;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_PARENT);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ err = unionfs_file_revalidate(file, parent, true);
++ if (unlikely(err))
++ goto out;
++
++ lower_file = unionfs_lower_file(file);
++ err = vfs_splice_from(pipe, lower_file, ppos, len, flags);
++ /* update our inode times+sizes upon a successful lower write */
++ if (err >= 0) {
++ fsstack_copy_inode_size(dentry->d_inode,
++ lower_file->f_path.dentry->d_inode);
++ fsstack_copy_attr_times(dentry->d_inode,
++ lower_file->f_path.dentry->d_inode);
++ unionfs_check_file(file);
++ }
++
++out:
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++struct file_operations unionfs_main_fops = {
++ .llseek = generic_file_llseek,
++ .read = unionfs_read,
++ .write = unionfs_write,
++ .readdir = unionfs_file_readdir,
++ .unlocked_ioctl = unionfs_ioctl,
++ .mmap = unionfs_mmap,
++ .open = unionfs_open,
++ .flush = unionfs_flush,
++ .release = unionfs_file_release,
++ .fsync = unionfs_fsync,
++ .fasync = unionfs_fasync,
++ .splice_read = unionfs_splice_read,
++ .splice_write = unionfs_splice_write,
++};
+diff --git a/fs/unionfs/inode.c b/fs/unionfs/inode.c
+new file mode 100644
+index 0000000..cc994bd
+--- /dev/null
++++ b/fs/unionfs/inode.c
+@@ -0,0 +1,1074 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++/*
++ * Find a writeable branch to create new object in. Checks all writeble
++ * branches of the parent inode, from istart to iend order; if none are
++ * suitable, also tries branch 0 (which may require a copyup).
++ *
++ * Return a lower_dentry we can use to create object in, or ERR_PTR.
++ */
++static struct dentry *find_writeable_branch(struct inode *parent,
++ struct dentry *dentry)
++{
++ int err = -EINVAL;
++ int bindex, istart, iend;
++ struct dentry *lower_dentry = NULL;
++
++ istart = ibstart(parent);
++ iend = ibend(parent);
++ if (istart < 0)
++ goto out;
++
++begin:
++ for (bindex = istart; bindex <= iend; bindex++) {
++ /* skip non-writeable branches */
++ err = is_robranch_super(dentry->d_sb, bindex);
++ if (err) {
++ err = -EROFS;
++ continue;
++ }
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry)
++ continue;
++ /*
++ * check for whiteouts in writeable branch, and remove them
++ * if necessary.
++ */
++ err = check_unlink_whiteout(dentry, lower_dentry, bindex);
++ if (err > 0) /* ignore if whiteout found and removed */
++ err = 0;
++ if (err)
++ continue;
++ /* if get here, we can write to the branch */
++ break;
++ }
++ /*
++ * If istart wasn't already branch 0, and we got any error, then try
++ * branch 0 (which may require copyup)
++ */
++ if (err && istart > 0) {
++ istart = iend = 0;
++ goto begin;
++ }
++
++ /*
++ * If we tried even branch 0, and still got an error, abort. But if
++ * the error was an EROFS, then we should try to copyup.
++ */
++ if (err && err != -EROFS)
++ goto out;
++
++ /*
++ * If we get here, then check if copyup needed. If lower_dentry is
++ * NULL, create the entire dentry directory structure in branch 0.
++ */
++ if (!lower_dentry) {
++ bindex = 0;
++ lower_dentry = create_parents(parent, dentry,
++ dentry->d_name.name, bindex);
++ if (IS_ERR(lower_dentry)) {
++ err = PTR_ERR(lower_dentry);
++ goto out;
++ }
++ }
++ err = 0; /* all's well */
++out:
++ if (err)
++ return ERR_PTR(err);
++ return lower_dentry;
++}
++
++static int unionfs_create(struct inode *dir, struct dentry *dentry,
++ int mode, struct nameidata *nd_unused)
++{
++ int err = 0;
++ struct dentry *lower_dentry = NULL;
++ struct dentry *lower_parent_dentry = NULL;
++ struct dentry *parent;
++ int valid = 0;
++ struct nameidata lower_nd;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE; /* same as what real_lookup does */
++ goto out;
++ }
++
++ lower_dentry = find_writeable_branch(dir, dentry);
++ if (IS_ERR(lower_dentry)) {
++ err = PTR_ERR(lower_dentry);
++ goto out;
++ }
++
++ lower_parent_dentry = lock_parent(lower_dentry);
++ if (IS_ERR(lower_parent_dentry)) {
++ err = PTR_ERR(lower_parent_dentry);
++ goto out_unlock;
++ }
++
++ err = init_lower_nd(&lower_nd, LOOKUP_CREATE);
++ if (unlikely(err < 0))
++ goto out_unlock;
++ err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode,
++ &lower_nd);
++ release_lower_nd(&lower_nd, err);
++
++ if (!err) {
++ err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0));
++ if (!err) {
++ unionfs_copy_attr_times(dir);
++ fsstack_copy_inode_size(dir,
++ lower_parent_dentry->d_inode);
++ /* update no. of links on parent directory */
++ dir->i_nlink = unionfs_get_nlinks(dir);
++ }
++ }
++
++out_unlock:
++ unlock_dir(lower_parent_dentry);
++out:
++ if (!err) {
++ unionfs_postcopyup_setmnt(dentry);
++ unionfs_check_inode(dir);
++ unionfs_check_dentry(dentry);
++ }
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++/*
++ * unionfs_lookup is the only special function which takes a dentry, yet we
++ * do NOT want to call __unionfs_d_revalidate_chain because by definition,
++ * we don't have a valid dentry here yet.
++ */
++static struct dentry *unionfs_lookup(struct inode *dir,
++ struct dentry *dentry,
++ struct nameidata *nd_unused)
++{
++ struct dentry *ret, *parent;
++ int err = 0;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++
++ /*
++ * As long as we lock/dget the parent, then can skip validating the
++ * parent now; we may have to rebuild this dentry on the next
++ * ->d_revalidate, however.
++ */
++
++ /* allocate dentry private data. We free it in ->d_release */
++ err = new_dentry_private_data(dentry, UNIONFS_DMUTEX_CHILD);
++ if (unlikely(err)) {
++ ret = ERR_PTR(err);
++ goto out;
++ }
++
++ ret = unionfs_lookup_full(dentry, parent, INTERPOSE_LOOKUP);
++
++ if (!IS_ERR(ret)) {
++ if (ret)
++ dentry = ret;
++ /* lookup_full can return multiple positive dentries */
++ if (dentry->d_inode && !S_ISDIR(dentry->d_inode->i_mode)) {
++ BUG_ON(dbstart(dentry) < 0);
++ unionfs_postcopyup_release(dentry);
++ }
++ unionfs_copy_attr_times(dentry->d_inode);
++ }
++
++ unionfs_check_inode(dir);
++ if (!IS_ERR(ret))
++ unionfs_check_dentry(dentry);
++ unionfs_check_dentry(parent);
++ unionfs_unlock_dentry(dentry); /* locked in new_dentry_private data */
++
++out:
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++
++ return ret;
++}
++
++static int unionfs_link(struct dentry *old_dentry, struct inode *dir,
++ struct dentry *new_dentry)
++{
++ int err = 0;
++ struct dentry *lower_old_dentry = NULL;
++ struct dentry *lower_new_dentry = NULL;
++ struct dentry *lower_dir_dentry = NULL;
++ struct dentry *old_parent, *new_parent;
++ char *name = NULL;
++ bool valid;
++
++ unionfs_read_lock(old_dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ old_parent = dget_parent(old_dentry);
++ new_parent = dget_parent(new_dentry);
++ unionfs_double_lock_parents(old_parent, new_parent);
++ unionfs_double_lock_dentry(old_dentry, new_dentry);
++
++ valid = __unionfs_d_revalidate(old_dentry, old_parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++ if (new_dentry->d_inode) {
++ valid = __unionfs_d_revalidate(new_dentry, new_parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++ }
++
++ lower_new_dentry = unionfs_lower_dentry(new_dentry);
++
++ /* check for a whiteout in new dentry branch, and delete it */
++ err = check_unlink_whiteout(new_dentry, lower_new_dentry,
++ dbstart(new_dentry));
++ if (err > 0) { /* whiteout found and removed successfully */
++ lower_dir_dentry = dget_parent(lower_new_dentry);
++ fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
++ dput(lower_dir_dentry);
++ dir->i_nlink = unionfs_get_nlinks(dir);
++ err = 0;
++ }
++ if (err)
++ goto out;
++
++ /* check if parent hierachy is needed, then link in same branch */
++ if (dbstart(old_dentry) != dbstart(new_dentry)) {
++ lower_new_dentry = create_parents(dir, new_dentry,
++ new_dentry->d_name.name,
++ dbstart(old_dentry));
++ err = PTR_ERR(lower_new_dentry);
++ if (IS_COPYUP_ERR(err))
++ goto docopyup;
++ if (!lower_new_dentry || IS_ERR(lower_new_dentry))
++ goto out;
++ }
++ lower_new_dentry = unionfs_lower_dentry(new_dentry);
++ lower_old_dentry = unionfs_lower_dentry(old_dentry);
++
++ BUG_ON(dbstart(old_dentry) != dbstart(new_dentry));
++ lower_dir_dentry = lock_parent(lower_new_dentry);
++ err = is_robranch(old_dentry);
++ if (!err) {
++ /* see Documentation/filesystems/unionfs/issues.txt */
++ lockdep_off();
++ err = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
++ lower_new_dentry);
++ lockdep_on();
++ }
++ unlock_dir(lower_dir_dentry);
++
++docopyup:
++ if (IS_COPYUP_ERR(err)) {
++ int old_bstart = dbstart(old_dentry);
++ int bindex;
++
++ for (bindex = old_bstart - 1; bindex >= 0; bindex--) {
++ err = copyup_dentry(old_parent->d_inode,
++ old_dentry, old_bstart,
++ bindex, old_dentry->d_name.name,
++ old_dentry->d_name.len, NULL,
++ i_size_read(old_dentry->d_inode));
++ if (err)
++ continue;
++ lower_new_dentry =
++ create_parents(dir, new_dentry,
++ new_dentry->d_name.name,
++ bindex);
++ lower_old_dentry = unionfs_lower_dentry(old_dentry);
++ lower_dir_dentry = lock_parent(lower_new_dentry);
++ /* see Documentation/filesystems/unionfs/issues.txt */
++ lockdep_off();
++ /* do vfs_link */
++ err = vfs_link(lower_old_dentry,
++ lower_dir_dentry->d_inode,
++ lower_new_dentry);
++ lockdep_on();
++ unlock_dir(lower_dir_dentry);
++ goto check_link;
++ }
++ goto out;
++ }
++
++check_link:
++ if (err || !lower_new_dentry->d_inode)
++ goto out;
++
++ /* Its a hard link, so use the same inode */
++ new_dentry->d_inode = igrab(old_dentry->d_inode);
++ d_add(new_dentry, new_dentry->d_inode);
++ unionfs_copy_attr_all(dir, lower_new_dentry->d_parent->d_inode);
++ fsstack_copy_inode_size(dir, lower_new_dentry->d_parent->d_inode);
++
++ /* propagate number of hard-links */
++ old_dentry->d_inode->i_nlink = unionfs_get_nlinks(old_dentry->d_inode);
++ /* new dentry's ctime may have changed due to hard-link counts */
++ unionfs_copy_attr_times(new_dentry->d_inode);
++
++out:
++ if (!new_dentry->d_inode)
++ d_drop(new_dentry);
++
++ kfree(name);
++ if (!err)
++ unionfs_postcopyup_setmnt(new_dentry);
++
++ unionfs_check_inode(dir);
++ unionfs_check_dentry(new_dentry);
++ unionfs_check_dentry(old_dentry);
++
++ unionfs_double_unlock_dentry(old_dentry, new_dentry);
++ unionfs_double_unlock_parents(old_parent, new_parent);
++ dput(new_parent);
++ dput(old_parent);
++ unionfs_read_unlock(old_dentry->d_sb);
++
++ return err;
++}
++
++static int unionfs_symlink(struct inode *dir, struct dentry *dentry,
++ const char *symname)
++{
++ int err = 0;
++ struct dentry *lower_dentry = NULL;
++ struct dentry *wh_dentry = NULL;
++ struct dentry *lower_parent_dentry = NULL;
++ struct dentry *parent;
++ char *name = NULL;
++ int valid = 0;
++ umode_t mode;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ /*
++ * It's only a bug if this dentry was not negative and couldn't be
++ * revalidated (shouldn't happen).
++ */
++ BUG_ON(!valid && dentry->d_inode);
++
++ lower_dentry = find_writeable_branch(dir, dentry);
++ if (IS_ERR(lower_dentry)) {
++ err = PTR_ERR(lower_dentry);
++ goto out;
++ }
++
++ lower_parent_dentry = lock_parent(lower_dentry);
++ if (IS_ERR(lower_parent_dentry)) {
++ err = PTR_ERR(lower_parent_dentry);
++ goto out_unlock;
++ }
++
++ mode = S_IALLUGO;
++ err = vfs_symlink(lower_parent_dentry->d_inode, lower_dentry, symname);
++ if (!err) {
++ err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0));
++ if (!err) {
++ unionfs_copy_attr_times(dir);
++ fsstack_copy_inode_size(dir,
++ lower_parent_dentry->d_inode);
++ /* update no. of links on parent directory */
++ dir->i_nlink = unionfs_get_nlinks(dir);
++ }
++ }
++
++out_unlock:
++ unlock_dir(lower_parent_dentry);
++out:
++ dput(wh_dentry);
++ kfree(name);
++
++ if (!err) {
++ unionfs_postcopyup_setmnt(dentry);
++ unionfs_check_inode(dir);
++ unionfs_check_dentry(dentry);
++ }
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++static int unionfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
++{
++ int err = 0;
++ struct dentry *lower_dentry = NULL;
++ struct dentry *lower_parent_dentry = NULL;
++ struct dentry *parent;
++ int bindex = 0, bstart;
++ char *name = NULL;
++ int valid;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE; /* same as what real_lookup does */
++ goto out;
++ }
++
++ bstart = dbstart(dentry);
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++
++ /* check for a whiteout in new dentry branch, and delete it */
++ err = check_unlink_whiteout(dentry, lower_dentry, bstart);
++ if (err > 0) /* whiteout found and removed successfully */
++ err = 0;
++ if (err) {
++ /* exit if the error returned was NOT -EROFS */
++ if (!IS_COPYUP_ERR(err))
++ goto out;
++ bstart--;
++ }
++
++ /* check if copyup's needed, and mkdir */
++ for (bindex = bstart; bindex >= 0; bindex--) {
++ int i;
++ int bend = dbend(dentry);
++
++ if (is_robranch_super(dentry->d_sb, bindex))
++ continue;
++
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry) {
++ lower_dentry = create_parents(dir, dentry,
++ dentry->d_name.name,
++ bindex);
++ if (!lower_dentry || IS_ERR(lower_dentry)) {
++ printk(KERN_ERR "unionfs: lower dentry "
++ " NULL for bindex = %d\n", bindex);
++ continue;
++ }
++ }
++
++ lower_parent_dentry = lock_parent(lower_dentry);
++
++ if (IS_ERR(lower_parent_dentry)) {
++ err = PTR_ERR(lower_parent_dentry);
++ goto out;
++ }
++
++ err = vfs_mkdir(lower_parent_dentry->d_inode, lower_dentry,
++ mode);
++
++ unlock_dir(lower_parent_dentry);
++
++ /* did the mkdir succeed? */
++ if (err)
++ break;
++
++ for (i = bindex + 1; i <= bend; i++) {
++ /* XXX: use path_put_lowers? */
++ if (unionfs_lower_dentry_idx(dentry, i)) {
++ dput(unionfs_lower_dentry_idx(dentry, i));
++ unionfs_set_lower_dentry_idx(dentry, i, NULL);
++ }
++ }
++ dbend(dentry) = bindex;
++
++ /*
++ * Only INTERPOSE_LOOKUP can return a value other than 0 on
++ * err.
++ */
++ err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0));
++ if (!err) {
++ unionfs_copy_attr_times(dir);
++ fsstack_copy_inode_size(dir,
++ lower_parent_dentry->d_inode);
++
++ /* update number of links on parent directory */
++ dir->i_nlink = unionfs_get_nlinks(dir);
++ }
++
++ err = make_dir_opaque(dentry, dbstart(dentry));
++ if (err) {
++ printk(KERN_ERR "unionfs: mkdir: error creating "
++ ".wh.__dir_opaque: %d\n", err);
++ goto out;
++ }
++
++ /* we are done! */
++ break;
++ }
++
++out:
++ if (!dentry->d_inode)
++ d_drop(dentry);
++
++ kfree(name);
++
++ if (!err) {
++ unionfs_copy_attr_times(dentry->d_inode);
++ unionfs_postcopyup_setmnt(dentry);
++ }
++ unionfs_check_inode(dir);
++ unionfs_check_dentry(dentry);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++
++ return err;
++}
++
++static int unionfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
++ dev_t dev)
++{
++ int err = 0;
++ struct dentry *lower_dentry = NULL;
++ struct dentry *wh_dentry = NULL;
++ struct dentry *lower_parent_dentry = NULL;
++ struct dentry *parent;
++ char *name = NULL;
++ int valid = 0;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ /*
++ * It's only a bug if this dentry was not negative and couldn't be
++ * revalidated (shouldn't happen).
++ */
++ BUG_ON(!valid && dentry->d_inode);
++
++ lower_dentry = find_writeable_branch(dir, dentry);
++ if (IS_ERR(lower_dentry)) {
++ err = PTR_ERR(lower_dentry);
++ goto out;
++ }
++
++ lower_parent_dentry = lock_parent(lower_dentry);
++ if (IS_ERR(lower_parent_dentry)) {
++ err = PTR_ERR(lower_parent_dentry);
++ goto out_unlock;
++ }
++
++ err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev);
++ if (!err) {
++ err = PTR_ERR(unionfs_interpose(dentry, dir->i_sb, 0));
++ if (!err) {
++ unionfs_copy_attr_times(dir);
++ fsstack_copy_inode_size(dir,
++ lower_parent_dentry->d_inode);
++ /* update no. of links on parent directory */
++ dir->i_nlink = unionfs_get_nlinks(dir);
++ }
++ }
++
++out_unlock:
++ unlock_dir(lower_parent_dentry);
++out:
++ dput(wh_dentry);
++ kfree(name);
++
++ if (!err) {
++ unionfs_postcopyup_setmnt(dentry);
++ unionfs_check_inode(dir);
++ unionfs_check_dentry(dentry);
++ }
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++/* requires sb, dentry, and parent to already be locked */
++static int __unionfs_readlink(struct dentry *dentry, char __user *buf,
++ int bufsiz)
++{
++ int err;
++ struct dentry *lower_dentry;
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++
++ if (!lower_dentry->d_inode->i_op ||
++ !lower_dentry->d_inode->i_op->readlink) {
++ err = -EINVAL;
++ goto out;
++ }
++
++ err = lower_dentry->d_inode->i_op->readlink(lower_dentry,
++ buf, bufsiz);
++ if (err >= 0)
++ fsstack_copy_attr_atime(dentry->d_inode,
++ lower_dentry->d_inode);
++
++out:
++ return err;
++}
++
++static int unionfs_readlink(struct dentry *dentry, char __user *buf,
++ int bufsiz)
++{
++ int err;
++ struct dentry *parent;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ if (unlikely(!__unionfs_d_revalidate(dentry, parent, false))) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ err = __unionfs_readlink(dentry, buf, bufsiz);
++
++out:
++ unionfs_check_dentry(dentry);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++
++ return err;
++}
++
++static void *unionfs_follow_link(struct dentry *dentry, struct nameidata *nd)
++{
++ char *buf;
++ int len = PAGE_SIZE, err;
++ mm_segment_t old_fs;
++ struct dentry *parent;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ /* This is freed by the put_link method assuming a successful call. */
++ buf = kmalloc(len, GFP_KERNEL);
++ if (unlikely(!buf)) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ /* read the symlink, and then we will follow it */
++ old_fs = get_fs();
++ set_fs(KERNEL_DS);
++ err = __unionfs_readlink(dentry, buf, len);
++ set_fs(old_fs);
++ if (err < 0) {
++ kfree(buf);
++ buf = NULL;
++ goto out;
++ }
++ buf[err] = 0;
++ nd_set_link(nd, buf);
++ err = 0;
++
++out:
++ if (err >= 0) {
++ unionfs_check_nd(nd);
++ unionfs_check_dentry(dentry);
++ }
++
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++
++ return ERR_PTR(err);
++}
++
++/* this @nd *IS* still used */
++static void unionfs_put_link(struct dentry *dentry, struct nameidata *nd,
++ void *cookie)
++{
++ struct dentry *parent;
++ char *buf;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ if (unlikely(!__unionfs_d_revalidate(dentry, parent, false)))
++ printk(KERN_ERR
++ "unionfs: put_link failed to revalidate dentry\n");
++
++ unionfs_check_dentry(dentry);
++#if 0
++ /* XXX: can't run this check b/c this fxn can receive a poisoned 'nd' PTR */
++ unionfs_check_nd(nd);
++#endif
++ buf = nd_get_link(nd);
++ if (!IS_ERR(buf))
++ kfree(buf);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++}
++
++/*
++ * This is a variant of fs/namei.c:permission() or inode_permission() which
++ * skips over EROFS tests (because we perform copyup on EROFS).
++ */
++static int __inode_permission(struct inode *inode, int mask)
++{
++ int retval;
++
++ /* nobody gets write access to an immutable file */
++ if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
++ return -EACCES;
++
++ /* Ordinary permission routines do not understand MAY_APPEND. */
++ if (inode->i_op && inode->i_op->permission) {
++ retval = inode->i_op->permission(inode, mask);
++ if (!retval) {
++ /*
++ * Exec permission on a regular file is denied if none
++ * of the execute bits are set.
++ *
++ * This check should be done by the ->permission()
++ * method.
++ */
++ if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode) &&
++ !(inode->i_mode & S_IXUGO))
++ return -EACCES;
++ }
++ } else {
++ retval = generic_permission(inode, mask, NULL);
++ }
++ if (retval)
++ return retval;
++
++ return security_inode_permission(inode,
++ mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND));
++}
++
++/*
++ * Don't grab the superblock read-lock in unionfs_permission, which prevents
++ * a deadlock with the branch-management "add branch" code (which grabbed
++ * the write lock). It is safe to not grab the read lock here, because even
++ * with branch management taking place, there is no chance that
++ * unionfs_permission, or anything it calls, will use stale branch
++ * information.
++ */
++static int unionfs_permission(struct inode *inode, int mask)
++{
++ struct inode *lower_inode = NULL;
++ int err = 0;
++ int bindex, bstart, bend;
++ const int is_file = !S_ISDIR(inode->i_mode);
++ const int write_mask = (mask & MAY_WRITE) && !(mask & MAY_READ);
++ struct inode *inode_grabbed = igrab(inode);
++ struct dentry *dentry = d_find_alias(inode);
++
++ if (dentry)
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ if (!UNIONFS_I(inode)->lower_inodes) {
++ if (is_file) /* dirs can be unlinked but chdir'ed to */
++ err = -ESTALE; /* force revalidate */
++ goto out;
++ }
++ bstart = ibstart(inode);
++ bend = ibend(inode);
++ if (unlikely(bstart < 0 || bend < 0)) {
++ /*
++ * With branch-management, we can get a stale inode here.
++ * If so, we return ESTALE back to link_path_walk, which
++ * would discard the dcache entry and re-lookup the
++ * dentry+inode. This should be equivalent to issuing
++ * __unionfs_d_revalidate_chain on nd.dentry here.
++ */
++ if (is_file) /* dirs can be unlinked but chdir'ed to */
++ err = -ESTALE; /* force revalidate */
++ goto out;
++ }
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (!lower_inode)
++ continue;
++
++ /*
++ * check the condition for D-F-D underlying files/directories,
++ * we don't have to check for files, if we are checking for
++ * directories.
++ */
++ if (!is_file && !S_ISDIR(lower_inode->i_mode))
++ continue;
++
++ /*
++ * We check basic permissions, but we ignore any conditions
++ * such as readonly file systems or branches marked as
++ * readonly, because those conditions should lead to a
++ * copyup taking place later on. However, if user never had
++ * access to the file, then no copyup could ever take place.
++ */
++ err = __inode_permission(lower_inode, mask);
++ if (err && err != -EACCES && err != EPERM && bindex > 0) {
++ umode_t mode = lower_inode->i_mode;
++ if ((is_robranch_super(inode->i_sb, bindex) ||
++ __is_rdonly(lower_inode)) &&
++ (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
++ err = 0;
++ if (IS_COPYUP_ERR(err))
++ err = 0;
++ }
++
++ /*
++ * NFS HACK: NFSv2/3 return EACCES on readonly-exported,
++ * locally readonly-mounted file systems, instead of EROFS
++ * like other file systems do. So we have no choice here
++ * but to intercept this and ignore it for NFS branches
++ * marked readonly. Specifically, we avoid using NFS's own
++ * "broken" ->permission method, and rely on
++ * generic_permission() to do basic checking for us.
++ */
++ if (err && err == -EACCES &&
++ is_robranch_super(inode->i_sb, bindex) &&
++ lower_inode->i_sb->s_magic == NFS_SUPER_MAGIC)
++ err = generic_permission(lower_inode, mask, NULL);
++
++ /*
++ * The permissions are an intersection of the overall directory
++ * permissions, so we fail if one fails.
++ */
++ if (err)
++ goto out;
++
++ /* only the leftmost file matters. */
++ if (is_file || write_mask) {
++ if (is_file && write_mask) {
++ err = get_write_access(lower_inode);
++ if (!err)
++ put_write_access(lower_inode);
++ }
++ break;
++ }
++ }
++ /* sync times which may have changed (asynchronously) below */
++ unionfs_copy_attr_times(inode);
++
++out:
++ unionfs_check_inode(inode);
++ if (dentry) {
++ unionfs_unlock_dentry(dentry);
++ dput(dentry);
++ }
++ iput(inode_grabbed);
++ return err;
++}
++
++static int unionfs_setattr(struct dentry *dentry, struct iattr *ia)
++{
++ int err = 0;
++ struct dentry *lower_dentry;
++ struct dentry *parent;
++ struct inode *inode;
++ struct inode *lower_inode;
++ int bstart, bend, bindex;
++ loff_t size;
++ struct iattr lower_ia;
++
++ /* check if user has permission to change inode */
++ err = inode_change_ok(dentry->d_inode, ia);
++ if (err)
++ goto out_err;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ if (unlikely(!__unionfs_d_revalidate(dentry, parent, false))) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++ inode = dentry->d_inode;
++
++ /*
++ * mode change is for clearing setuid/setgid. Allow lower filesystem
++ * to reinterpret it in its own way.
++ */
++ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
++ ia->ia_valid &= ~ATTR_MODE;
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++ if (!lower_dentry) { /* should never happen after above revalidate */
++ err = -EINVAL;
++ goto out;
++ }
++ lower_inode = unionfs_lower_inode(inode);
++
++ /* check if user has permission to change lower inode */
++ err = inode_change_ok(lower_inode, ia);
++ if (err)
++ goto out;
++
++ /* copyup if the file is on a read only branch */
++ if (is_robranch_super(dentry->d_sb, bstart)
++ || __is_rdonly(lower_inode)) {
++ /* check if we have a branch to copy up to */
++ if (bstart <= 0) {
++ err = -EACCES;
++ goto out;
++ }
++
++ if (ia->ia_valid & ATTR_SIZE)
++ size = ia->ia_size;
++ else
++ size = i_size_read(inode);
++ /* copyup to next available branch */
++ for (bindex = bstart - 1; bindex >= 0; bindex--) {
++ err = copyup_dentry(parent->d_inode,
++ dentry, bstart, bindex,
++ dentry->d_name.name,
++ dentry->d_name.len,
++ NULL, size);
++ if (!err)
++ break;
++ }
++ if (err)
++ goto out;
++ /* get updated lower_dentry/inode after copyup */
++ lower_dentry = unionfs_lower_dentry(dentry);
++ lower_inode = unionfs_lower_inode(inode);
++ }
++
++ /*
++ * If shrinking, first truncate upper level to cancel writing dirty
++ * pages beyond the new eof; and also if its' maxbytes is more
++ * limiting (fail with -EFBIG before making any change to the lower
++ * level). There is no need to vmtruncate the upper level
++ * afterwards in the other cases: we fsstack_copy_inode_size from
++ * the lower level.
++ */
++ if (ia->ia_valid & ATTR_SIZE) {
++ size = i_size_read(inode);
++ if (ia->ia_size < size || (ia->ia_size > size &&
++ inode->i_sb->s_maxbytes < lower_inode->i_sb->s_maxbytes)) {
++ err = vmtruncate(inode, ia->ia_size);
++ if (err)
++ goto out;
++ }
++ }
++
++ /* notify the (possibly copied-up) lower inode */
++ /*
++ * Note: we use lower_dentry->d_inode, because lower_inode may be
++ * unlinked (no inode->i_sb and i_ino==0. This happens if someone
++ * tries to open(), unlink(), then ftruncate() a file.
++ */
++ /* prepare our own lower struct iattr (with our own lower file) */
++ memcpy(&lower_ia, ia, sizeof(lower_ia));
++ if (ia->ia_valid & ATTR_FILE) {
++ lower_ia.ia_file = unionfs_lower_file(ia->ia_file);
++ BUG_ON(!lower_ia.ia_file); // XXX?
++ }
++
++ mutex_lock(&lower_dentry->d_inode->i_mutex);
++ err = notify_change(lower_dentry, &lower_ia);
++ mutex_unlock(&lower_dentry->d_inode->i_mutex);
++ if (err)
++ goto out;
++
++ /* get attributes from the first lower inode */
++ if (ibstart(inode) >= 0)
++ unionfs_copy_attr_all(inode, lower_inode);
++ /*
++ * unionfs_copy_attr_all will copy the lower times to our inode if
++ * the lower ones are newer (useful for cache coherency). However,
++ * ->setattr is the only place in which we may have to copy the
++ * lower inode times absolutely, to support utimes(2).
++ */
++ if (ia->ia_valid & ATTR_MTIME_SET)
++ inode->i_mtime = lower_inode->i_mtime;
++ if (ia->ia_valid & ATTR_CTIME)
++ inode->i_ctime = lower_inode->i_ctime;
++ if (ia->ia_valid & ATTR_ATIME_SET)
++ inode->i_atime = lower_inode->i_atime;
++ fsstack_copy_inode_size(inode, lower_inode);
++
++out:
++ if (!err)
++ unionfs_check_dentry(dentry);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++out_err:
++ return err;
++}
++
++struct inode_operations unionfs_symlink_iops = {
++ .readlink = unionfs_readlink,
++ .permission = unionfs_permission,
++ .follow_link = unionfs_follow_link,
++ .setattr = unionfs_setattr,
++ .put_link = unionfs_put_link,
++};
++
++struct inode_operations unionfs_dir_iops = {
++ .create = unionfs_create,
++ .lookup = unionfs_lookup,
++ .link = unionfs_link,
++ .unlink = unionfs_unlink,
++ .symlink = unionfs_symlink,
++ .mkdir = unionfs_mkdir,
++ .rmdir = unionfs_rmdir,
++ .mknod = unionfs_mknod,
++ .rename = unionfs_rename,
++ .permission = unionfs_permission,
++ .setattr = unionfs_setattr,
++#ifdef CONFIG_UNION_FS_XATTR
++ .setxattr = unionfs_setxattr,
++ .getxattr = unionfs_getxattr,
++ .removexattr = unionfs_removexattr,
++ .listxattr = unionfs_listxattr,
++#endif /* CONFIG_UNION_FS_XATTR */
++};
++
++struct inode_operations unionfs_main_iops = {
++ .permission = unionfs_permission,
++ .setattr = unionfs_setattr,
++#ifdef CONFIG_UNION_FS_XATTR
++ .setxattr = unionfs_setxattr,
++ .getxattr = unionfs_getxattr,
++ .removexattr = unionfs_removexattr,
++ .listxattr = unionfs_listxattr,
++#endif /* CONFIG_UNION_FS_XATTR */
++};
+diff --git a/fs/unionfs/lookup.c b/fs/unionfs/lookup.c
+new file mode 100644
+index 0000000..b63c17e
+--- /dev/null
++++ b/fs/unionfs/lookup.c
+@@ -0,0 +1,569 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++/*
++ * Lookup one path component @name relative to a <base,mnt> path pair.
++ * Behaves nearly the same as lookup_one_len (i.e., return negative dentry
++ * on ENOENT), but uses the @mnt passed, so it can cross bind mounts and
++ * other lower mounts properly. If @new_mnt is non-null, will fill in the
++ * new mnt there. Caller is responsible to dput/mntput/path_put returned
++ * @dentry and @new_mnt.
++ */
++struct dentry *__lookup_one(struct dentry *base, struct vfsmount *mnt,
++ const char *name, struct vfsmount **new_mnt)
++{
++ struct dentry *dentry = NULL;
++ struct nameidata lower_nd;
++ int err;
++
++ /* we use flags=0 to get basic lookup */
++ err = vfs_path_lookup(base, mnt, name, 0, &lower_nd);
++
++ switch (err) {
++ case 0: /* no error */
++ dentry = lower_nd.path.dentry;
++ if (new_mnt)
++ *new_mnt = lower_nd.path.mnt; /* rc already inc'ed */
++ break;
++ case -ENOENT:
++ /*
++ * We don't consider ENOENT an error, and we want to return
++ * a negative dentry (ala lookup_one_len). As we know
++ * there was no inode for this name before (-ENOENT), then
++ * it's safe to call lookup_one_len (which doesn't take a
++ * vfsmount).
++ */
++ dentry = lookup_lck_len(name, base, strlen(name));
++ if (new_mnt)
++ *new_mnt = mntget(lower_nd.path.mnt);
++ break;
++ default: /* all other real errors */
++ dentry = ERR_PTR(err);
++ break;
++ }
++
++ return dentry;
++}
++
++/*
++ * This is a utility function that fills in a unionfs dentry.
++ * Caller must lock this dentry with unionfs_lock_dentry.
++ *
++ * Returns: 0 (ok), or -ERRNO if an error occurred.
++ * XXX: get rid of _partial_lookup and make callers call _lookup_full directly
++ */
++int unionfs_partial_lookup(struct dentry *dentry, struct dentry *parent)
++{
++ struct dentry *tmp;
++ int err = -ENOSYS;
++
++ tmp = unionfs_lookup_full(dentry, parent, INTERPOSE_PARTIAL);
++
++ if (!tmp) {
++ err = 0;
++ goto out;
++ }
++ if (IS_ERR(tmp)) {
++ err = PTR_ERR(tmp);
++ goto out;
++ }
++ /* XXX: need to change the interface */
++ BUG_ON(tmp != dentry);
++out:
++ return err;
++}
++
++/* The dentry cache is just so we have properly sized dentries. */
++static struct kmem_cache *unionfs_dentry_cachep;
++int unionfs_init_dentry_cache(void)
++{
++ unionfs_dentry_cachep =
++ kmem_cache_create("unionfs_dentry",
++ sizeof(struct unionfs_dentry_info),
++ 0, SLAB_RECLAIM_ACCOUNT, NULL);
++
++ return (unionfs_dentry_cachep ? 0 : -ENOMEM);
++}
++
++void unionfs_destroy_dentry_cache(void)
++{
++ if (unionfs_dentry_cachep)
++ kmem_cache_destroy(unionfs_dentry_cachep);
++}
++
++void free_dentry_private_data(struct dentry *dentry)
++{
++ if (!dentry || !dentry->d_fsdata)
++ return;
++ kfree(UNIONFS_D(dentry)->lower_paths);
++ UNIONFS_D(dentry)->lower_paths = NULL;
++ kmem_cache_free(unionfs_dentry_cachep, dentry->d_fsdata);
++ dentry->d_fsdata = NULL;
++}
++
++static inline int __realloc_dentry_private_data(struct dentry *dentry)
++{
++ struct unionfs_dentry_info *info = UNIONFS_D(dentry);
++ void *p;
++ int size;
++
++ BUG_ON(!info);
++
++ size = sizeof(struct path) * sbmax(dentry->d_sb);
++ p = krealloc(info->lower_paths, size, GFP_ATOMIC);
++ if (unlikely(!p))
++ return -ENOMEM;
++
++ info->lower_paths = p;
++
++ info->bstart = -1;
++ info->bend = -1;
++ info->bopaque = -1;
++ info->bcount = sbmax(dentry->d_sb);
++ atomic_set(&info->generation,
++ atomic_read(&UNIONFS_SB(dentry->d_sb)->generation));
++
++ memset(info->lower_paths, 0, size);
++
++ return 0;
++}
++
++/* UNIONFS_D(dentry)->lock must be locked */
++int realloc_dentry_private_data(struct dentry *dentry)
++{
++ if (!__realloc_dentry_private_data(dentry))
++ return 0;
++
++ kfree(UNIONFS_D(dentry)->lower_paths);
++ free_dentry_private_data(dentry);
++ return -ENOMEM;
++}
++
++/* allocate new dentry private data */
++int new_dentry_private_data(struct dentry *dentry, int subclass)
++{
++ struct unionfs_dentry_info *info = UNIONFS_D(dentry);
++
++ BUG_ON(info);
++
++ info = kmem_cache_alloc(unionfs_dentry_cachep, GFP_ATOMIC);
++ if (unlikely(!info))
++ return -ENOMEM;
++
++ mutex_init(&info->lock);
++ mutex_lock_nested(&info->lock, subclass);
++
++ info->lower_paths = NULL;
++
++ dentry->d_fsdata = info;
++
++ if (!__realloc_dentry_private_data(dentry))
++ return 0;
++
++ mutex_unlock(&info->lock);
++ free_dentry_private_data(dentry);
++ return -ENOMEM;
++}
++
++/*
++ * scan through the lower dentry objects, and set bstart to reflect the
++ * starting branch
++ */
++void update_bstart(struct dentry *dentry)
++{
++ int bindex;
++ int bstart = dbstart(dentry);
++ int bend = dbend(dentry);
++ struct dentry *lower_dentry;
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry)
++ continue;
++ if (lower_dentry->d_inode) {
++ dbstart(dentry) = bindex;
++ break;
++ }
++ dput(lower_dentry);
++ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
++ }
++}
++
++
++/*
++ * Initialize a nameidata structure (the intent part) we can pass to a lower
++ * file system. Returns 0 on success or -error (only -ENOMEM possible).
++ * Inside that nd structure, this function may also return an allocated
++ * struct file (for open intents). The caller, when done with this nd, must
++ * kfree the intent file (using release_lower_nd).
++ *
++ * XXX: this code, and the callers of this code, should be redone using
++ * vfs_path_lookup() when (1) the nameidata structure is refactored into a
++ * separate intent-structure, and (2) open_namei() is broken into a VFS-only
++ * function and a method that other file systems can call.
++ */
++int init_lower_nd(struct nameidata *nd, unsigned int flags)
++{
++ int err = 0;
++#ifdef ALLOC_LOWER_ND_FILE
++ /*
++ * XXX: one day we may need to have the lower return an open file
++ * for us. It is not needed in 2.6.23-rc1 for nfs2/nfs3, but may
++ * very well be needed for nfs4.
++ */
++ struct file *file;
++#endif /* ALLOC_LOWER_ND_FILE */
++
++ memset(nd, 0, sizeof(struct nameidata));
++ if (!flags)
++ return err;
++
++ switch (flags) {
++ case LOOKUP_CREATE:
++ nd->intent.open.flags |= O_CREAT;
++ /* fall through: shared code for create/open cases */
++ case LOOKUP_OPEN:
++ nd->flags = flags;
++ nd->intent.open.flags |= (FMODE_READ | FMODE_WRITE);
++#ifdef ALLOC_LOWER_ND_FILE
++ file = kzalloc(sizeof(struct file), GFP_KERNEL);
++ if (unlikely(!file)) {
++ err = -ENOMEM;
++ break; /* exit switch statement and thus return */
++ }
++ nd->intent.open.file = file;
++#endif /* ALLOC_LOWER_ND_FILE */
++ break;
++ default:
++ /*
++ * We should never get here, for now.
++ * We can add new cases here later on.
++ */
++ pr_debug("unionfs: unknown nameidata flag 0x%x\n", flags);
++ BUG();
++ break;
++ }
++
++ return err;
++}
++
++void release_lower_nd(struct nameidata *nd, int err)
++{
++ if (!nd->intent.open.file)
++ return;
++ else if (!err)
++ release_open_intent(nd);
++#ifdef ALLOC_LOWER_ND_FILE
++ kfree(nd->intent.open.file);
++#endif /* ALLOC_LOWER_ND_FILE */
++}
++
++/*
++ * Main (and complex) driver function for Unionfs's lookup
++ *
++ * Returns: NULL (ok), ERR_PTR if an error occurred, or a non-null non-error
++ * PTR if d_splice returned a different dentry.
++ *
++ * If lookupmode is INTERPOSE_PARTIAL/REVAL/REVAL_NEG, the passed dentry's
++ * inode info must be locked. If lookupmode is INTERPOSE_LOOKUP (i.e., a
++ * newly looked-up dentry), then unionfs_lookup_backend will return a locked
++ * dentry's info, which the caller must unlock.
++ */
++struct dentry *unionfs_lookup_full(struct dentry *dentry,
++ struct dentry *parent, int lookupmode)
++{
++ int err = 0;
++ struct dentry *lower_dentry = NULL;
++ struct vfsmount *lower_mnt;
++ struct vfsmount *lower_dir_mnt;
++ struct dentry *wh_lower_dentry = NULL;
++ struct dentry *lower_dir_dentry = NULL;
++ struct dentry *d_interposed = NULL;
++ int bindex, bstart, bend, bopaque;
++ int opaque, num_positive = 0;
++ const char *name;
++ int namelen;
++ int pos_start, pos_end;
++
++ /*
++ * We should already have a lock on this dentry in the case of a
++ * partial lookup, or a revalidation. Otherwise it is returned from
++ * new_dentry_private_data already locked.
++ */
++ verify_locked(dentry);
++ verify_locked(parent);
++
++ /* must initialize dentry operations */
++ dentry->d_op = &unionfs_dops;
++
++ /* We never partial lookup the root directory. */
++ if (IS_ROOT(dentry))
++ goto out;
++
++ name = dentry->d_name.name;
++ namelen = dentry->d_name.len;
++
++ /* No dentries should get created for possible whiteout names. */
++ if (!is_validname(name)) {
++ err = -EPERM;
++ goto out_free;
++ }
++
++ /* Now start the actual lookup procedure. */
++ bstart = dbstart(parent);
++ bend = dbend(parent);
++ bopaque = dbopaque(parent);
++ BUG_ON(bstart < 0);
++
++ /* adjust bend to bopaque if needed */
++ if ((bopaque >= 0) && (bopaque < bend))
++ bend = bopaque;
++
++ /* lookup all possible dentries */
++ for (bindex = bstart; bindex <= bend; bindex++) {
++
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ lower_mnt = unionfs_lower_mnt_idx(dentry, bindex);
++
++ /* skip if we already have a positive lower dentry */
++ if (lower_dentry) {
++ if (dbstart(dentry) < 0)
++ dbstart(dentry) = bindex;
++ if (bindex > dbend(dentry))
++ dbend(dentry) = bindex;
++ if (lower_dentry->d_inode)
++ num_positive++;
++ continue;
++ }
++
++ lower_dir_dentry =
++ unionfs_lower_dentry_idx(parent, bindex);
++ /* if the lower dentry's parent does not exist, skip this */
++ if (!lower_dir_dentry || !lower_dir_dentry->d_inode)
++ continue;
++
++ /* also skip it if the parent isn't a directory. */
++ if (!S_ISDIR(lower_dir_dentry->d_inode->i_mode))
++ continue; /* XXX: should be BUG_ON */
++
++ /* check for whiteouts: stop lookup if found */
++ wh_lower_dentry = lookup_whiteout(name, lower_dir_dentry);
++ if (IS_ERR(wh_lower_dentry)) {
++ err = PTR_ERR(wh_lower_dentry);
++ goto out_free;
++ }
++ if (wh_lower_dentry->d_inode) {
++ dbend(dentry) = dbopaque(dentry) = bindex;
++ if (dbstart(dentry) < 0)
++ dbstart(dentry) = bindex;
++ dput(wh_lower_dentry);
++ break;
++ }
++ dput(wh_lower_dentry);
++
++ /* Now do regular lookup; lookup @name */
++ lower_dir_mnt = unionfs_lower_mnt_idx(parent, bindex);
++ lower_mnt = NULL; /* XXX: needed? */
++
++ lower_dentry = __lookup_one(lower_dir_dentry, lower_dir_mnt,
++ name, &lower_mnt);
++
++ if (IS_ERR(lower_dentry)) {
++ err = PTR_ERR(lower_dentry);
++ goto out_free;
++ }
++ unionfs_set_lower_dentry_idx(dentry, bindex, lower_dentry);
++ if (!lower_mnt)
++ lower_mnt = unionfs_mntget(dentry->d_sb->s_root,
++ bindex);
++ unionfs_set_lower_mnt_idx(dentry, bindex, lower_mnt);
++
++ /* adjust dbstart/end */
++ if (dbstart(dentry) < 0)
++ dbstart(dentry) = bindex;
++ if (bindex > dbend(dentry))
++ dbend(dentry) = bindex;
++ /*
++ * We always store the lower dentries above, and update
++ * dbstart/dbend, even if the whole unionfs dentry is
++ * negative (i.e., no lower inodes).
++ */
++ if (!lower_dentry->d_inode)
++ continue;
++ num_positive++;
++
++ /*
++ * check if we just found an opaque directory, if so, stop
++ * lookups here.
++ */
++ if (!S_ISDIR(lower_dentry->d_inode->i_mode))
++ continue;
++ opaque = is_opaque_dir(dentry, bindex);
++ if (opaque < 0) {
++ err = opaque;
++ goto out_free;
++ } else if (opaque) {
++ dbend(dentry) = dbopaque(dentry) = bindex;
++ break;
++ }
++ dbend(dentry) = bindex;
++
++ /* update parent directory's atime with the bindex */
++ fsstack_copy_attr_atime(parent->d_inode,
++ lower_dir_dentry->d_inode);
++ }
++
++ /* sanity checks, then decide if to process a negative dentry */
++ BUG_ON(dbstart(dentry) < 0 && dbend(dentry) >= 0);
++ BUG_ON(dbstart(dentry) >= 0 && dbend(dentry) < 0);
++
++ if (num_positive > 0)
++ goto out_positive;
++
++ /*** handle NEGATIVE dentries ***/
++
++ /*
++ * If negative, keep only first lower negative dentry, to save on
++ * memory.
++ */
++ if (dbstart(dentry) < dbend(dentry)) {
++ path_put_lowers(dentry, dbstart(dentry) + 1,
++ dbend(dentry), false);
++ dbend(dentry) = dbstart(dentry);
++ }
++ if (lookupmode == INTERPOSE_PARTIAL)
++ goto out;
++ if (lookupmode == INTERPOSE_LOOKUP) {
++ /*
++ * If all we found was a whiteout in the first available
++ * branch, then create a negative dentry for a possibly new
++ * file to be created.
++ */
++ if (dbopaque(dentry) < 0)
++ goto out;
++ /* XXX: need to get mnt here */
++ bindex = dbstart(dentry);
++ if (unionfs_lower_dentry_idx(dentry, bindex))
++ goto out;
++ lower_dir_dentry =
++ unionfs_lower_dentry_idx(parent, bindex);
++ if (!lower_dir_dentry || !lower_dir_dentry->d_inode)
++ goto out;
++ if (!S_ISDIR(lower_dir_dentry->d_inode->i_mode))
++ goto out; /* XXX: should be BUG_ON */
++ /* XXX: do we need to cross bind mounts here? */
++ lower_dentry = lookup_lck_len(name, lower_dir_dentry, namelen);
++ if (IS_ERR(lower_dentry)) {
++ err = PTR_ERR(lower_dentry);
++ goto out;
++ }
++ /* XXX: need to mntget/mntput as needed too! */
++ unionfs_set_lower_dentry_idx(dentry, bindex, lower_dentry);
++ /* XXX: wrong mnt for crossing bind mounts! */
++ lower_mnt = unionfs_mntget(dentry->d_sb->s_root, bindex);
++ unionfs_set_lower_mnt_idx(dentry, bindex, lower_mnt);
++
++ goto out;
++ }
++
++ /* if we're revalidating a positive dentry, don't make it negative */
++ if (lookupmode != INTERPOSE_REVAL)
++ d_add(dentry, NULL);
++
++ goto out;
++
++out_positive:
++ /*** handle POSITIVE dentries ***/
++
++ /*
++ * This unionfs dentry is positive (at least one lower inode
++ * exists), so scan entire dentry from beginning to end, and remove
++ * any negative lower dentries, if any. Then, update dbstart/dbend
++ * to reflect the start/end of positive dentries.
++ */
++ pos_start = pos_end = -1;
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry,
++ bindex);
++ if (lower_dentry && lower_dentry->d_inode) {
++ if (pos_start < 0)
++ pos_start = bindex;
++ if (bindex > pos_end)
++ pos_end = bindex;
++ continue;
++ }
++ path_put_lowers(dentry, bindex, bindex, false);
++ }
++ if (pos_start >= 0)
++ dbstart(dentry) = pos_start;
++ if (pos_end >= 0)
++ dbend(dentry) = pos_end;
++
++ /* Partial lookups need to re-interpose, or throw away older negs. */
++ if (lookupmode == INTERPOSE_PARTIAL) {
++ if (dentry->d_inode) {
++ unionfs_reinterpose(dentry);
++ goto out;
++ }
++
++ /*
++ * This dentry was positive, so it is as if we had a
++ * negative revalidation.
++ */
++ lookupmode = INTERPOSE_REVAL_NEG;
++ update_bstart(dentry);
++ }
++
++ /*
++ * Interpose can return a dentry if d_splice returned a different
++ * dentry.
++ */
++ d_interposed = unionfs_interpose(dentry, dentry->d_sb, lookupmode);
++ if (IS_ERR(d_interposed))
++ err = PTR_ERR(d_interposed);
++ else if (d_interposed)
++ dentry = d_interposed;
++
++ if (!err)
++ goto out;
++ d_drop(dentry);
++
++out_free:
++ /* should dput/mntput all the underlying dentries on error condition */
++ if (dbstart(dentry) >= 0)
++ path_put_lowers_all(dentry, false);
++ /* free lower_paths unconditionally */
++ kfree(UNIONFS_D(dentry)->lower_paths);
++ UNIONFS_D(dentry)->lower_paths = NULL;
++
++out:
++ if (dentry && UNIONFS_D(dentry)) {
++ BUG_ON(dbstart(dentry) < 0 && dbend(dentry) >= 0);
++ BUG_ON(dbstart(dentry) >= 0 && dbend(dentry) < 0);
++ }
++ if (d_interposed && UNIONFS_D(d_interposed)) {
++ BUG_ON(dbstart(d_interposed) < 0 && dbend(d_interposed) >= 0);
++ BUG_ON(dbstart(d_interposed) >= 0 && dbend(d_interposed) < 0);
++ }
++
++ if (!err && d_interposed)
++ return d_interposed;
++ return ERR_PTR(err);
++}
+diff --git a/fs/unionfs/main.c b/fs/unionfs/main.c
+new file mode 100644
+index 0000000..9ee58eb
+--- /dev/null
++++ b/fs/unionfs/main.c
+@@ -0,0 +1,762 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++
++static void unionfs_fill_inode(struct dentry *dentry,
++ struct inode *inode)
++{
++ struct inode *lower_inode;
++ struct dentry *lower_dentry;
++ int bindex, bstart, bend;
++
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry) {
++ unionfs_set_lower_inode_idx(inode, bindex, NULL);
++ continue;
++ }
++
++ /* Initialize the lower inode to the new lower inode. */
++ if (!lower_dentry->d_inode)
++ continue;
++
++ unionfs_set_lower_inode_idx(inode, bindex,
++ igrab(lower_dentry->d_inode));
++ }
++
++ ibstart(inode) = dbstart(dentry);
++ ibend(inode) = dbend(dentry);
++
++ /* Use attributes from the first branch. */
++ lower_inode = unionfs_lower_inode(inode);
++
++ /* Use different set of inode ops for symlinks & directories */
++ if (S_ISLNK(lower_inode->i_mode))
++ inode->i_op = &unionfs_symlink_iops;
++ else if (S_ISDIR(lower_inode->i_mode))
++ inode->i_op = &unionfs_dir_iops;
++
++ /* Use different set of file ops for directories */
++ if (S_ISDIR(lower_inode->i_mode))
++ inode->i_fop = &unionfs_dir_fops;
++
++ /* properly initialize special inodes */
++ if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) ||
++ S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode))
++ init_special_inode(inode, lower_inode->i_mode,
++ lower_inode->i_rdev);
++
++ /* all well, copy inode attributes */
++ unionfs_copy_attr_all(inode, lower_inode);
++ fsstack_copy_inode_size(inode, lower_inode);
++}
++
++/*
++ * Connect a unionfs inode dentry/inode with several lower ones. This is
++ * the classic stackable file system "vnode interposition" action.
++ *
++ * @sb: unionfs's super_block
++ */
++struct dentry *unionfs_interpose(struct dentry *dentry, struct super_block *sb,
++ int flag)
++{
++ int err = 0;
++ struct inode *inode;
++ int need_fill_inode = 1;
++ struct dentry *spliced = NULL;
++
++ verify_locked(dentry);
++
++ /*
++ * We allocate our new inode below by calling unionfs_iget,
++ * which will initialize some of the new inode's fields
++ */
++
++ /*
++ * On revalidate we've already got our own inode and just need
++ * to fix it up.
++ */
++ if (flag == INTERPOSE_REVAL) {
++ inode = dentry->d_inode;
++ UNIONFS_I(inode)->bstart = -1;
++ UNIONFS_I(inode)->bend = -1;
++ atomic_set(&UNIONFS_I(inode)->generation,
++ atomic_read(&UNIONFS_SB(sb)->generation));
++
++ UNIONFS_I(inode)->lower_inodes =
++ kcalloc(sbmax(sb), sizeof(struct inode *), GFP_KERNEL);
++ if (unlikely(!UNIONFS_I(inode)->lower_inodes)) {
++ err = -ENOMEM;
++ goto out;
++ }
++ } else {
++ /* get unique inode number for unionfs */
++ inode = unionfs_iget(sb, iunique(sb, UNIONFS_ROOT_INO));
++ if (IS_ERR(inode)) {
++ err = PTR_ERR(inode);
++ goto out;
++ }
++ if (atomic_read(&inode->i_count) > 1)
++ goto skip;
++ }
++
++ need_fill_inode = 0;
++ unionfs_fill_inode(dentry, inode);
++
++skip:
++ /* only (our) lookup wants to do a d_add */
++ switch (flag) {
++ case INTERPOSE_DEFAULT:
++ /* for operations which create new inodes */
++ d_add(dentry, inode);
++ break;
++ case INTERPOSE_REVAL_NEG:
++ d_instantiate(dentry, inode);
++ break;
++ case INTERPOSE_LOOKUP:
++ spliced = d_splice_alias(inode, dentry);
++ if (spliced && spliced != dentry) {
++ /*
++ * d_splice can return a dentry if it was
++ * disconnected and had to be moved. We must ensure
++ * that the private data of the new dentry is
++ * correct and that the inode info was filled
++ * properly. Finally we must return this new
++ * dentry.
++ */
++ spliced->d_op = &unionfs_dops;
++ spliced->d_fsdata = dentry->d_fsdata;
++ dentry->d_fsdata = NULL;
++ dentry = spliced;
++ if (need_fill_inode) {
++ need_fill_inode = 0;
++ unionfs_fill_inode(dentry, inode);
++ }
++ goto out_spliced;
++ } else if (!spliced) {
++ if (need_fill_inode) {
++ need_fill_inode = 0;
++ unionfs_fill_inode(dentry, inode);
++ goto out_spliced;
++ }
++ }
++ break;
++ case INTERPOSE_REVAL:
++ /* Do nothing. */
++ break;
++ default:
++ printk(KERN_CRIT "unionfs: invalid interpose flag passed!\n");
++ BUG();
++ }
++ goto out;
++
++out_spliced:
++ if (!err)
++ return spliced;
++out:
++ return ERR_PTR(err);
++}
++
++/* like interpose above, but for an already existing dentry */
++void unionfs_reinterpose(struct dentry *dentry)
++{
++ struct dentry *lower_dentry;
++ struct inode *inode;
++ int bindex, bstart, bend;
++
++ verify_locked(dentry);
++
++ /* This is pre-allocated inode */
++ inode = dentry->d_inode;
++
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry)
++ continue;
++
++ if (!lower_dentry->d_inode)
++ continue;
++ if (unionfs_lower_inode_idx(inode, bindex))
++ continue;
++ unionfs_set_lower_inode_idx(inode, bindex,
++ igrab(lower_dentry->d_inode));
++ }
++ ibstart(inode) = dbstart(dentry);
++ ibend(inode) = dbend(dentry);
++}
++
++/*
++ * make sure the branch we just looked up (nd) makes sense:
++ *
++ * 1) we're not trying to stack unionfs on top of unionfs
++ * 2) it exists
++ * 3) is a directory
++ */
++int check_branch(struct nameidata *nd)
++{
++ /* XXX: remove in ODF code -- stacking unions allowed there */
++ if (!strcmp(nd->path.dentry->d_sb->s_type->name, UNIONFS_NAME))
++ return -EINVAL;
++ if (!nd->path.dentry->d_inode)
++ return -ENOENT;
++ if (!S_ISDIR(nd->path.dentry->d_inode->i_mode))
++ return -ENOTDIR;
++ return 0;
++}
++
++/* checks if two lower_dentries have overlapping branches */
++static int is_branch_overlap(struct dentry *dent1, struct dentry *dent2)
++{
++ struct dentry *dent = NULL;
++
++ dent = dent1;
++ while ((dent != dent2) && (dent->d_parent != dent))
++ dent = dent->d_parent;
++
++ if (dent == dent2)
++ return 1;
++
++ dent = dent2;
++ while ((dent != dent1) && (dent->d_parent != dent))
++ dent = dent->d_parent;
++
++ return (dent == dent1);
++}
++
++/*
++ * Parse "ro" or "rw" options, but default to "rw" if no mode options was
++ * specified. Fill the mode bits in @perms. If encounter an unknown
++ * string, return -EINVAL. Otherwise return 0.
++ */
++int parse_branch_mode(const char *name, int *perms)
++{
++ if (!name || !strcmp(name, "rw")) {
++ *perms = MAY_READ | MAY_WRITE;
++ return 0;
++ }
++ if (!strcmp(name, "ro")) {
++ *perms = MAY_READ;
++ return 0;
++ }
++ return -EINVAL;
++}
++
++/*
++ * parse the dirs= mount argument
++ *
++ * We don't need to lock the superblock private data's rwsem, as we get
++ * called only by unionfs_read_super - it is still a long time before anyone
++ * can even get a reference to us.
++ */
++static int parse_dirs_option(struct super_block *sb, struct unionfs_dentry_info
++ *lower_root_info, char *options)
++{
++ struct nameidata nd;
++ char *name;
++ int err = 0;
++ int branches = 1;
++ int bindex = 0;
++ int i = 0;
++ int j = 0;
++ struct dentry *dent1;
++ struct dentry *dent2;
++
++ if (options[0] == '\0') {
++ printk(KERN_ERR "unionfs: no branches specified\n");
++ err = -EINVAL;
++ goto out_return;
++ }
++
++ /*
++ * Each colon means we have a separator, this is really just a rough
++ * guess, since strsep will handle empty fields for us.
++ */
++ for (i = 0; options[i]; i++)
++ if (options[i] == ':')
++ branches++;
++
++ /* allocate space for underlying pointers to lower dentry */
++ UNIONFS_SB(sb)->data =
++ kcalloc(branches, sizeof(struct unionfs_data), GFP_KERNEL);
++ if (unlikely(!UNIONFS_SB(sb)->data)) {
++ err = -ENOMEM;
++ goto out_return;
++ }
++
++ lower_root_info->lower_paths =
++ kcalloc(branches, sizeof(struct path), GFP_KERNEL);
++ if (unlikely(!lower_root_info->lower_paths)) {
++ err = -ENOMEM;
++ /* free the underlying pointer array */
++ kfree(UNIONFS_SB(sb)->data);
++ UNIONFS_SB(sb)->data = NULL;
++ goto out_return;
++ }
++
++ /* now parsing a string such as "b1:b2=rw:b3=ro:b4" */
++ branches = 0;
++ while ((name = strsep(&options, ":")) != NULL) {
++ int perms;
++ char *mode = strchr(name, '=');
++
++ if (!name)
++ continue;
++ if (!*name) { /* bad use of ':' (extra colons) */
++ err = -EINVAL;
++ goto out;
++ }
++
++ branches++;
++
++ /* strip off '=' if any */
++ if (mode)
++ *mode++ = '\0';
++
++ err = parse_branch_mode(mode, &perms);
++ if (err) {
++ printk(KERN_ERR "unionfs: invalid mode \"%s\" for "
++ "branch %d\n", mode, bindex);
++ goto out;
++ }
++ /* ensure that leftmost branch is writeable */
++ if (!bindex && !(perms & MAY_WRITE)) {
++ printk(KERN_ERR "unionfs: leftmost branch cannot be "
++ "read-only (use \"-o ro\" to create a "
++ "read-only union)\n");
++ err = -EINVAL;
++ goto out;
++ }
++
++ err = path_lookup(name, LOOKUP_FOLLOW, &nd);
++ if (err) {
++ printk(KERN_ERR "unionfs: error accessing "
++ "lower directory '%s' (error %d)\n",
++ name, err);
++ goto out;
++ }
++
++ err = check_branch(&nd);
++ if (err) {
++ printk(KERN_ERR "unionfs: lower directory "
++ "'%s' is not a valid branch\n", name);
++ path_put(&nd.path);
++ goto out;
++ }
++
++ lower_root_info->lower_paths[bindex].dentry = nd.path.dentry;
++ lower_root_info->lower_paths[bindex].mnt = nd.path.mnt;
++
++ set_branchperms(sb, bindex, perms);
++ set_branch_count(sb, bindex, 0);
++ new_branch_id(sb, bindex);
++
++ if (lower_root_info->bstart < 0)
++ lower_root_info->bstart = bindex;
++ lower_root_info->bend = bindex;
++ bindex++;
++ }
++
++ if (branches == 0) {
++ printk(KERN_ERR "unionfs: no branches specified\n");
++ err = -EINVAL;
++ goto out;
++ }
++
++ BUG_ON(branches != (lower_root_info->bend + 1));
++
++ /*
++ * Ensure that no overlaps exist in the branches.
++ *
++ * This test is required because the Linux kernel has no support
++ * currently for ensuring coherency between stackable layers and
++ * branches. If we were to allow overlapping branches, it would be
++ * possible, for example, to delete a file via one branch, which
++ * would not be reflected in another branch. Such incoherency could
++ * lead to inconsistencies and even kernel oopses. Rather than
++ * implement hacks to work around some of these cache-coherency
++ * problems, we prevent branch overlapping, for now. A complete
++ * solution will involve proper kernel/VFS support for cache
++ * coherency, at which time we could safely remove this
++ * branch-overlapping test.
++ */
++ for (i = 0; i < branches; i++) {
++ dent1 = lower_root_info->lower_paths[i].dentry;
++ for (j = i + 1; j < branches; j++) {
++ dent2 = lower_root_info->lower_paths[j].dentry;
++ if (is_branch_overlap(dent1, dent2)) {
++ printk(KERN_ERR "unionfs: branches %d and "
++ "%d overlap\n", i, j);
++ err = -EINVAL;
++ goto out;
++ }
++ }
++ }
++
++out:
++ if (err) {
++ for (i = 0; i < branches; i++)
++ path_put(&lower_root_info->lower_paths[i]);
++
++ kfree(lower_root_info->lower_paths);
++ kfree(UNIONFS_SB(sb)->data);
++
++ /*
++ * MUST clear the pointers to prevent potential double free if
++ * the caller dies later on
++ */
++ lower_root_info->lower_paths = NULL;
++ UNIONFS_SB(sb)->data = NULL;
++ }
++out_return:
++ return err;
++}
++
++/*
++ * Parse mount options. See the manual page for usage instructions.
++ *
++ * Returns the dentry object of the lower-level (lower) directory;
++ * We want to mount our stackable file system on top of that lower directory.
++ */
++static struct unionfs_dentry_info *unionfs_parse_options(
++ struct super_block *sb,
++ char *options)
++{
++ struct unionfs_dentry_info *lower_root_info;
++ char *optname;
++ int err = 0;
++ int bindex;
++ int dirsfound = 0;
++
++ /* allocate private data area */
++ err = -ENOMEM;
++ lower_root_info =
++ kzalloc(sizeof(struct unionfs_dentry_info), GFP_KERNEL);
++ if (unlikely(!lower_root_info))
++ goto out_error;
++ lower_root_info->bstart = -1;
++ lower_root_info->bend = -1;
++ lower_root_info->bopaque = -1;
++
++ while ((optname = strsep(&options, ",")) != NULL) {
++ char *optarg;
++
++ if (!optname || !*optname)
++ continue;
++
++ optarg = strchr(optname, '=');
++ if (optarg)
++ *optarg++ = '\0';
++
++ /*
++ * All of our options take an argument now. Insert ones that
++ * don't, above this check.
++ */
++ if (!optarg) {
++ printk(KERN_ERR "unionfs: %s requires an argument\n",
++ optname);
++ err = -EINVAL;
++ goto out_error;
++ }
++
++ if (!strcmp("dirs", optname)) {
++ if (++dirsfound > 1) {
++ printk(KERN_ERR
++ "unionfs: multiple dirs specified\n");
++ err = -EINVAL;
++ goto out_error;
++ }
++ err = parse_dirs_option(sb, lower_root_info, optarg);
++ if (err)
++ goto out_error;
++ continue;
++ }
++
++ err = -EINVAL;
++ printk(KERN_ERR
++ "unionfs: unrecognized option '%s'\n", optname);
++ goto out_error;
++ }
++ if (dirsfound != 1) {
++ printk(KERN_ERR "unionfs: dirs option required\n");
++ err = -EINVAL;
++ goto out_error;
++ }
++ goto out;
++
++out_error:
++ if (lower_root_info && lower_root_info->lower_paths) {
++ for (bindex = lower_root_info->bstart;
++ bindex >= 0 && bindex <= lower_root_info->bend;
++ bindex++)
++ path_put(&lower_root_info->lower_paths[bindex]);
++ }
++
++ kfree(lower_root_info->lower_paths);
++ kfree(lower_root_info);
++
++ kfree(UNIONFS_SB(sb)->data);
++ UNIONFS_SB(sb)->data = NULL;
++
++ lower_root_info = ERR_PTR(err);
++out:
++ return lower_root_info;
++}
++
++/*
++ * our custom d_alloc_root work-alike
++ *
++ * we can't use d_alloc_root if we want to use our own interpose function
++ * unchanged, so we simply call our own "fake" d_alloc_root
++ */
++static struct dentry *unionfs_d_alloc_root(struct super_block *sb)
++{
++ struct dentry *ret = NULL;
++
++ if (sb) {
++ static const struct qstr name = {
++ .name = "/",
++ .len = 1
++ };
++
++ ret = d_alloc(NULL, &name);
++ if (likely(ret)) {
++ ret->d_op = &unionfs_dops;
++ ret->d_sb = sb;
++ ret->d_parent = ret;
++ }
++ }
++ return ret;
++}
++
++/*
++ * There is no need to lock the unionfs_super_info's rwsem as there is no
++ * way anyone can have a reference to the superblock at this point in time.
++ */
++static int unionfs_read_super(struct super_block *sb, void *raw_data,
++ int silent)
++{
++ int err = 0;
++ struct unionfs_dentry_info *lower_root_info = NULL;
++ int bindex, bstart, bend;
++
++ if (!raw_data) {
++ printk(KERN_ERR
++ "unionfs: read_super: missing data argument\n");
++ err = -EINVAL;
++ goto out;
++ }
++
++ /* Allocate superblock private data */
++ sb->s_fs_info = kzalloc(sizeof(struct unionfs_sb_info), GFP_KERNEL);
++ if (unlikely(!UNIONFS_SB(sb))) {
++ printk(KERN_CRIT "unionfs: read_super: out of memory\n");
++ err = -ENOMEM;
++ goto out;
++ }
++
++ UNIONFS_SB(sb)->bend = -1;
++ atomic_set(&UNIONFS_SB(sb)->generation, 1);
++ init_rwsem(&UNIONFS_SB(sb)->rwsem);
++ UNIONFS_SB(sb)->high_branch_id = -1; /* -1 == invalid branch ID */
++
++ lower_root_info = unionfs_parse_options(sb, raw_data);
++ if (IS_ERR(lower_root_info)) {
++ printk(KERN_ERR
++ "unionfs: read_super: error while parsing options "
++ "(err = %ld)\n", PTR_ERR(lower_root_info));
++ err = PTR_ERR(lower_root_info);
++ lower_root_info = NULL;
++ goto out_free;
++ }
++ if (lower_root_info->bstart == -1) {
++ err = -ENOENT;
++ goto out_free;
++ }
++
++ /* set the lower superblock field of upper superblock */
++ bstart = lower_root_info->bstart;
++ BUG_ON(bstart != 0);
++ sbend(sb) = bend = lower_root_info->bend;
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ struct dentry *d = lower_root_info->lower_paths[bindex].dentry;
++ atomic_inc(&d->d_sb->s_active);
++ unionfs_set_lower_super_idx(sb, bindex, d->d_sb);
++ }
++
++ /* max Bytes is the maximum bytes from highest priority branch */
++ sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes;
++
++ /*
++ * Our c/m/atime granularity is 1 ns because we may stack on file
++ * systems whose granularity is as good. This is important for our
++ * time-based cache coherency.
++ */
++ sb->s_time_gran = 1;
++
++ sb->s_op = &unionfs_sops;
++
++ /* See comment next to the definition of unionfs_d_alloc_root */
++ sb->s_root = unionfs_d_alloc_root(sb);
++ if (unlikely(!sb->s_root)) {
++ err = -ENOMEM;
++ goto out_dput;
++ }
++
++ /* link the upper and lower dentries */
++ sb->s_root->d_fsdata = NULL;
++ err = new_dentry_private_data(sb->s_root, UNIONFS_DMUTEX_ROOT);
++ if (unlikely(err))
++ goto out_freedpd;
++
++ /* Set the lower dentries for s_root */
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ struct dentry *d;
++ struct vfsmount *m;
++
++ d = lower_root_info->lower_paths[bindex].dentry;
++ m = lower_root_info->lower_paths[bindex].mnt;
++
++ unionfs_set_lower_dentry_idx(sb->s_root, bindex, d);
++ unionfs_set_lower_mnt_idx(sb->s_root, bindex, m);
++ }
++ dbstart(sb->s_root) = bstart;
++ dbend(sb->s_root) = bend;
++
++ /* Set the generation number to one, since this is for the mount. */
++ atomic_set(&UNIONFS_D(sb->s_root)->generation, 1);
++
++ /*
++ * Call interpose to create the upper level inode. Only
++ * INTERPOSE_LOOKUP can return a value other than 0 on err.
++ */
++ err = PTR_ERR(unionfs_interpose(sb->s_root, sb, 0));
++ unionfs_unlock_dentry(sb->s_root);
++ if (!err)
++ goto out;
++ /* else fall through */
++
++out_freedpd:
++ if (UNIONFS_D(sb->s_root)) {
++ kfree(UNIONFS_D(sb->s_root)->lower_paths);
++ free_dentry_private_data(sb->s_root);
++ }
++ dput(sb->s_root);
++
++out_dput:
++ if (lower_root_info && !IS_ERR(lower_root_info)) {
++ for (bindex = lower_root_info->bstart;
++ bindex <= lower_root_info->bend; bindex++) {
++ struct dentry *d;
++ d = lower_root_info->lower_paths[bindex].dentry;
++ /* drop refs we took earlier */
++ atomic_dec(&d->d_sb->s_active);
++ path_put(&lower_root_info->lower_paths[bindex]);
++ }
++ kfree(lower_root_info->lower_paths);
++ kfree(lower_root_info);
++ lower_root_info = NULL;
++ }
++
++out_free:
++ kfree(UNIONFS_SB(sb)->data);
++ kfree(UNIONFS_SB(sb));
++ sb->s_fs_info = NULL;
++
++out:
++ if (lower_root_info && !IS_ERR(lower_root_info)) {
++ kfree(lower_root_info->lower_paths);
++ kfree(lower_root_info);
++ }
++ return err;
++}
++
++static int unionfs_get_sb(struct file_system_type *fs_type,
++ int flags, const char *dev_name,
++ void *raw_data, struct vfsmount *mnt)
++{
++ int err;
++ err = get_sb_nodev(fs_type, flags, raw_data, unionfs_read_super, mnt);
++ if (!err)
++ UNIONFS_SB(mnt->mnt_sb)->dev_name =
++ kstrdup(dev_name, GFP_KERNEL);
++ return err;
++}
++
++static struct file_system_type unionfs_fs_type = {
++ .owner = THIS_MODULE,
++ .name = UNIONFS_NAME,
++ .get_sb = unionfs_get_sb,
++ .kill_sb = generic_shutdown_super,
++ .fs_flags = FS_REVAL_DOT,
++};
++
++static int __init init_unionfs_fs(void)
++{
++ int err;
++
++ pr_info("Registering unionfs " UNIONFS_VERSION "\n");
++
++ err = unionfs_init_filldir_cache();
++ if (unlikely(err))
++ goto out;
++ err = unionfs_init_inode_cache();
++ if (unlikely(err))
++ goto out;
++ err = unionfs_init_dentry_cache();
++ if (unlikely(err))
++ goto out;
++ err = init_sioq();
++ if (unlikely(err))
++ goto out;
++ err = register_filesystem(&unionfs_fs_type);
++out:
++ if (unlikely(err)) {
++ stop_sioq();
++ unionfs_destroy_filldir_cache();
++ unionfs_destroy_inode_cache();
++ unionfs_destroy_dentry_cache();
++ }
++ return err;
++}
++
++static void __exit exit_unionfs_fs(void)
++{
++ stop_sioq();
++ unionfs_destroy_filldir_cache();
++ unionfs_destroy_inode_cache();
++ unionfs_destroy_dentry_cache();
++ unregister_filesystem(&unionfs_fs_type);
++ pr_info("Completed unionfs module unload\n");
++}
++
++MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University"
++ " (http://www.fsl.cs.sunysb.edu)");
++MODULE_DESCRIPTION("Unionfs " UNIONFS_VERSION
++ " (http://unionfs.filesystems.org)");
++MODULE_LICENSE("GPL");
++
++module_init(init_unionfs_fs);
++module_exit(exit_unionfs_fs);
+diff --git a/fs/unionfs/mmap.c b/fs/unionfs/mmap.c
+new file mode 100644
+index 0000000..1f70535
+--- /dev/null
++++ b/fs/unionfs/mmap.c
+@@ -0,0 +1,89 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2006 Shaya Potter
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++
++/*
++ * XXX: we need a dummy readpage handler because generic_file_mmap (which we
++ * use in unionfs_mmap) checks for the existence of
++ * mapping->a_ops->readpage, else it returns -ENOEXEC. The VFS will need to
++ * be fixed to allow a file system to define vm_ops->fault without any
++ * address_space_ops whatsoever.
++ *
++ * Otherwise, we don't want to use our readpage method at all.
++ */
++static int unionfs_readpage(struct file *file, struct page *page)
++{
++ BUG();
++ return -EINVAL;
++}
++
++static int unionfs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
++{
++ int err;
++ struct file *file, *lower_file;
++ const struct vm_operations_struct *lower_vm_ops;
++ struct vm_area_struct lower_vma;
++
++ BUG_ON(!vma);
++ memcpy(&lower_vma, vma, sizeof(struct vm_area_struct));
++ file = lower_vma.vm_file;
++ lower_vm_ops = UNIONFS_F(file)->lower_vm_ops;
++ BUG_ON(!lower_vm_ops);
++
++ lower_file = unionfs_lower_file(file);
++ BUG_ON(!lower_file);
++ /*
++ * XXX: vm_ops->fault may be called in parallel. Because we have to
++ * resort to temporarily changing the vma->vm_file to point to the
++ * lower file, a concurrent invocation of unionfs_fault could see a
++ * different value. In this workaround, we keep a different copy of
++ * the vma structure in our stack, so we never expose a different
++ * value of the vma->vm_file called to us, even temporarily. A
++ * better fix would be to change the calling semantics of ->fault to
++ * take an explicit file pointer.
++ */
++ lower_vma.vm_file = lower_file;
++ err = lower_vm_ops->fault(&lower_vma, vmf);
++ return err;
++}
++
++/*
++ * XXX: the default address_space_ops for unionfs is empty. We cannot set
++ * our inode->i_mapping->a_ops to NULL because too many code paths expect
++ * the a_ops vector to be non-NULL.
++ */
++struct address_space_operations unionfs_aops = {
++ /* empty on purpose */
++};
++
++/*
++ * XXX: we need a second, dummy address_space_ops vector, to be used
++ * temporarily during unionfs_mmap, because the latter calls
++ * generic_file_mmap, which checks if ->readpage exists, else returns
++ * -ENOEXEC.
++ */
++struct address_space_operations unionfs_dummy_aops = {
++ .readpage = unionfs_readpage,
++};
++
++struct vm_operations_struct unionfs_vm_ops = {
++ .fault = unionfs_fault,
++};
+diff --git a/fs/unionfs/rdstate.c b/fs/unionfs/rdstate.c
+new file mode 100644
+index 0000000..f745fbc
+--- /dev/null
++++ b/fs/unionfs/rdstate.c
+@@ -0,0 +1,285 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++/* This file contains the routines for maintaining readdir state. */
++
++/*
++ * There are two structures here, rdstate which is a hash table
++ * of the second structure which is a filldir_node.
++ */
++
++/*
++ * This is a struct kmem_cache for filldir nodes, because we allocate a lot
++ * of them and they shouldn't waste memory. If the node has a small name
++ * (as defined by the dentry structure), then we use an inline name to
++ * preserve kmalloc space.
++ */
++static struct kmem_cache *unionfs_filldir_cachep;
++
++int unionfs_init_filldir_cache(void)
++{
++ unionfs_filldir_cachep =
++ kmem_cache_create("unionfs_filldir",
++ sizeof(struct filldir_node), 0,
++ SLAB_RECLAIM_ACCOUNT, NULL);
++
++ return (unionfs_filldir_cachep ? 0 : -ENOMEM);
++}
++
++void unionfs_destroy_filldir_cache(void)
++{
++ if (unionfs_filldir_cachep)
++ kmem_cache_destroy(unionfs_filldir_cachep);
++}
++
++/*
++ * This is a tuning parameter that tells us roughly how big to make the
++ * hash table in directory entries per page. This isn't perfect, but
++ * at least we get a hash table size that shouldn't be too overloaded.
++ * The following averages are based on my home directory.
++ * 14.44693 Overall
++ * 12.29 Single Page Directories
++ * 117.93 Multi-page directories
++ */
++#define DENTPAGE 4096
++#define DENTPERONEPAGE 12
++#define DENTPERPAGE 118
++#define MINHASHSIZE 1
++static int guesstimate_hash_size(struct inode *inode)
++{
++ struct inode *lower_inode;
++ int bindex;
++ int hashsize = MINHASHSIZE;
++
++ if (UNIONFS_I(inode)->hashsize > 0)
++ return UNIONFS_I(inode)->hashsize;
++
++ for (bindex = ibstart(inode); bindex <= ibend(inode); bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (!lower_inode)
++ continue;
++
++ if (i_size_read(lower_inode) == DENTPAGE)
++ hashsize += DENTPERONEPAGE;
++ else
++ hashsize += (i_size_read(lower_inode) / DENTPAGE) *
++ DENTPERPAGE;
++ }
++
++ return hashsize;
++}
++
++int init_rdstate(struct file *file)
++{
++ BUG_ON(sizeof(loff_t) !=
++ (sizeof(unsigned int) + sizeof(unsigned int)));
++ BUG_ON(UNIONFS_F(file)->rdstate != NULL);
++
++ UNIONFS_F(file)->rdstate = alloc_rdstate(file->f_path.dentry->d_inode,
++ fbstart(file));
++
++ return (UNIONFS_F(file)->rdstate ? 0 : -ENOMEM);
++}
++
++struct unionfs_dir_state *find_rdstate(struct inode *inode, loff_t fpos)
++{
++ struct unionfs_dir_state *rdstate = NULL;
++ struct list_head *pos;
++
++ spin_lock(&UNIONFS_I(inode)->rdlock);
++ list_for_each(pos, &UNIONFS_I(inode)->readdircache) {
++ struct unionfs_dir_state *r =
++ list_entry(pos, struct unionfs_dir_state, cache);
++ if (fpos == rdstate2offset(r)) {
++ UNIONFS_I(inode)->rdcount--;
++ list_del(&r->cache);
++ rdstate = r;
++ break;
++ }
++ }
++ spin_unlock(&UNIONFS_I(inode)->rdlock);
++ return rdstate;
++}
++
++struct unionfs_dir_state *alloc_rdstate(struct inode *inode, int bindex)
++{
++ int i = 0;
++ int hashsize;
++ unsigned long mallocsize = sizeof(struct unionfs_dir_state);
++ struct unionfs_dir_state *rdstate;
++
++ hashsize = guesstimate_hash_size(inode);
++ mallocsize += hashsize * sizeof(struct list_head);
++ mallocsize = __roundup_pow_of_two(mallocsize);
++
++ /* This should give us about 500 entries anyway. */
++ if (mallocsize > PAGE_SIZE)
++ mallocsize = PAGE_SIZE;
++
++ hashsize = (mallocsize - sizeof(struct unionfs_dir_state)) /
++ sizeof(struct list_head);
++
++ rdstate = kmalloc(mallocsize, GFP_KERNEL);
++ if (unlikely(!rdstate))
++ return NULL;
++
++ spin_lock(&UNIONFS_I(inode)->rdlock);
++ if (UNIONFS_I(inode)->cookie >= (MAXRDCOOKIE - 1))
++ UNIONFS_I(inode)->cookie = 1;
++ else
++ UNIONFS_I(inode)->cookie++;
++
++ rdstate->cookie = UNIONFS_I(inode)->cookie;
++ spin_unlock(&UNIONFS_I(inode)->rdlock);
++ rdstate->offset = 1;
++ rdstate->access = jiffies;
++ rdstate->bindex = bindex;
++ rdstate->dirpos = 0;
++ rdstate->hashentries = 0;
++ rdstate->size = hashsize;
++ for (i = 0; i < rdstate->size; i++)
++ INIT_LIST_HEAD(&rdstate->list[i]);
++
++ return rdstate;
++}
++
++static void free_filldir_node(struct filldir_node *node)
++{
++ if (node->namelen >= DNAME_INLINE_LEN_MIN)
++ kfree(node->name);
++ kmem_cache_free(unionfs_filldir_cachep, node);
++}
++
++void free_rdstate(struct unionfs_dir_state *state)
++{
++ struct filldir_node *tmp;
++ int i;
++
++ for (i = 0; i < state->size; i++) {
++ struct list_head *head = &(state->list[i]);
++ struct list_head *pos, *n;
++
++ /* traverse the list and deallocate space */
++ list_for_each_safe(pos, n, head) {
++ tmp = list_entry(pos, struct filldir_node, file_list);
++ list_del(&tmp->file_list);
++ free_filldir_node(tmp);
++ }
++ }
++
++ kfree(state);
++}
++
++struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate,
++ const char *name, int namelen,
++ int is_whiteout)
++{
++ int index;
++ unsigned int hash;
++ struct list_head *head;
++ struct list_head *pos;
++ struct filldir_node *cursor = NULL;
++ int found = 0;
++
++ BUG_ON(namelen <= 0);
++
++ hash = full_name_hash(name, namelen);
++ index = hash % rdstate->size;
++
++ head = &(rdstate->list[index]);
++ list_for_each(pos, head) {
++ cursor = list_entry(pos, struct filldir_node, file_list);
++
++ if (cursor->namelen == namelen && cursor->hash == hash &&
++ !strncmp(cursor->name, name, namelen)) {
++ /*
++ * a duplicate exists, and hence no need to create
++ * entry to the list
++ */
++ found = 1;
++
++ /*
++ * if a duplicate is found in this branch, and is
++ * not due to the caller looking for an entry to
++ * whiteout, then the file system may be corrupted.
++ */
++ if (unlikely(!is_whiteout &&
++ cursor->bindex == rdstate->bindex))
++ printk(KERN_ERR "unionfs: filldir: possible "
++ "I/O error: a file is duplicated "
++ "in the same branch %d: %s\n",
++ rdstate->bindex, cursor->name);
++ break;
++ }
++ }
++
++ if (!found)
++ cursor = NULL;
++
++ return cursor;
++}
++
++int add_filldir_node(struct unionfs_dir_state *rdstate, const char *name,
++ int namelen, int bindex, int whiteout)
++{
++ struct filldir_node *new;
++ unsigned int hash;
++ int index;
++ int err = 0;
++ struct list_head *head;
++
++ BUG_ON(namelen <= 0);
++
++ hash = full_name_hash(name, namelen);
++ index = hash % rdstate->size;
++ head = &(rdstate->list[index]);
++
++ new = kmem_cache_alloc(unionfs_filldir_cachep, GFP_KERNEL);
++ if (unlikely(!new)) {
++ err = -ENOMEM;
++ goto out;
++ }
++
++ INIT_LIST_HEAD(&new->file_list);
++ new->namelen = namelen;
++ new->hash = hash;
++ new->bindex = bindex;
++ new->whiteout = whiteout;
++
++ if (namelen < DNAME_INLINE_LEN_MIN) {
++ new->name = new->iname;
++ } else {
++ new->name = kmalloc(namelen + 1, GFP_KERNEL);
++ if (unlikely(!new->name)) {
++ kmem_cache_free(unionfs_filldir_cachep, new);
++ new = NULL;
++ goto out;
++ }
++ }
++
++ memcpy(new->name, name, namelen);
++ new->name[namelen] = '\0';
++
++ rdstate->hashentries++;
++
++ list_add(&(new->file_list), head);
++out:
++ return err;
++}
+diff --git a/fs/unionfs/rename.c b/fs/unionfs/rename.c
+new file mode 100644
+index 0000000..936700e
+--- /dev/null
++++ b/fs/unionfs/rename.c
+@@ -0,0 +1,517 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++/*
++ * This is a helper function for rename, used when rename ends up with hosed
++ * over dentries and we need to revert.
++ */
++static int unionfs_refresh_lower_dentry(struct dentry *dentry,
++ struct dentry *parent, int bindex)
++{
++ struct dentry *lower_dentry;
++ struct dentry *lower_parent;
++ int err = 0;
++
++ verify_locked(dentry);
++
++ lower_parent = unionfs_lower_dentry_idx(parent, bindex);
++
++ BUG_ON(!S_ISDIR(lower_parent->d_inode->i_mode));
++
++ lower_dentry = lookup_one_len(dentry->d_name.name, lower_parent,
++ dentry->d_name.len);
++ if (IS_ERR(lower_dentry)) {
++ err = PTR_ERR(lower_dentry);
++ goto out;
++ }
++
++ dput(unionfs_lower_dentry_idx(dentry, bindex));
++ iput(unionfs_lower_inode_idx(dentry->d_inode, bindex));
++ unionfs_set_lower_inode_idx(dentry->d_inode, bindex, NULL);
++
++ if (!lower_dentry->d_inode) {
++ dput(lower_dentry);
++ unionfs_set_lower_dentry_idx(dentry, bindex, NULL);
++ } else {
++ unionfs_set_lower_dentry_idx(dentry, bindex, lower_dentry);
++ unionfs_set_lower_inode_idx(dentry->d_inode, bindex,
++ igrab(lower_dentry->d_inode));
++ }
++
++out:
++ return err;
++}
++
++static int __unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
++ struct dentry *old_parent,
++ struct inode *new_dir, struct dentry *new_dentry,
++ struct dentry *new_parent,
++ int bindex)
++{
++ int err = 0;
++ struct dentry *lower_old_dentry;
++ struct dentry *lower_new_dentry;
++ struct dentry *lower_old_dir_dentry;
++ struct dentry *lower_new_dir_dentry;
++ struct dentry *trap;
++
++ lower_new_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
++ lower_old_dentry = unionfs_lower_dentry_idx(old_dentry, bindex);
++
++ if (!lower_new_dentry) {
++ lower_new_dentry =
++ create_parents(new_parent->d_inode,
++ new_dentry, new_dentry->d_name.name,
++ bindex);
++ if (IS_ERR(lower_new_dentry)) {
++ err = PTR_ERR(lower_new_dentry);
++ if (IS_COPYUP_ERR(err))
++ goto out;
++ printk(KERN_ERR "unionfs: error creating directory "
++ "tree for rename, bindex=%d err=%d\n",
++ bindex, err);
++ goto out;
++ }
++ }
++
++ /* check for and remove whiteout, if any */
++ err = check_unlink_whiteout(new_dentry, lower_new_dentry, bindex);
++ if (err > 0) /* ignore if whiteout found and successfully removed */
++ err = 0;
++ if (err)
++ goto out;
++
++ /* check of old_dentry branch is writable */
++ err = is_robranch_super(old_dentry->d_sb, bindex);
++ if (err)
++ goto out;
++
++ dget(lower_old_dentry);
++ dget(lower_new_dentry);
++ lower_old_dir_dentry = dget_parent(lower_old_dentry);
++ lower_new_dir_dentry = dget_parent(lower_new_dentry);
++
++ trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
++ /* source should not be ancenstor of target */
++ if (trap == lower_old_dentry) {
++ err = -EINVAL;
++ goto out_err_unlock;
++ }
++ /* target should not be ancenstor of source */
++ if (trap == lower_new_dentry) {
++ err = -ENOTEMPTY;
++ goto out_err_unlock;
++ }
++ err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
++ lower_new_dir_dentry->d_inode, lower_new_dentry);
++out_err_unlock:
++ if (!err) {
++ /* update parent dir times */
++ fsstack_copy_attr_times(old_dir, lower_old_dir_dentry->d_inode);
++ fsstack_copy_attr_times(new_dir, lower_new_dir_dentry->d_inode);
++ }
++ unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
++
++ dput(lower_old_dir_dentry);
++ dput(lower_new_dir_dentry);
++ dput(lower_old_dentry);
++ dput(lower_new_dentry);
++
++out:
++ if (!err) {
++ /* Fixup the new_dentry. */
++ if (bindex < dbstart(new_dentry))
++ dbstart(new_dentry) = bindex;
++ else if (bindex > dbend(new_dentry))
++ dbend(new_dentry) = bindex;
++ }
++
++ return err;
++}
++
++/*
++ * Main rename code. This is sufficiently complex, that it's documented in
++ * Documentation/filesystems/unionfs/rename.txt. This routine calls
++ * __unionfs_rename() above to perform some of the work.
++ */
++static int do_unionfs_rename(struct inode *old_dir,
++ struct dentry *old_dentry,
++ struct dentry *old_parent,
++ struct inode *new_dir,
++ struct dentry *new_dentry,
++ struct dentry *new_parent)
++{
++ int err = 0;
++ int bindex;
++ int old_bstart, old_bend;
++ int new_bstart, new_bend;
++ int do_copyup = -1;
++ int local_err = 0;
++ int eio = 0;
++ int revert = 0;
++
++ old_bstart = dbstart(old_dentry);
++ old_bend = dbend(old_dentry);
++
++ new_bstart = dbstart(new_dentry);
++ new_bend = dbend(new_dentry);
++
++ /* Rename source to destination. */
++ err = __unionfs_rename(old_dir, old_dentry, old_parent,
++ new_dir, new_dentry, new_parent,
++ old_bstart);
++ if (err) {
++ if (!IS_COPYUP_ERR(err))
++ goto out;
++ do_copyup = old_bstart - 1;
++ } else {
++ revert = 1;
++ }
++
++ /*
++ * Unlink all instances of destination that exist to the left of
++ * bstart of source. On error, revert back, goto out.
++ */
++ for (bindex = old_bstart - 1; bindex >= new_bstart; bindex--) {
++ struct dentry *unlink_dentry;
++ struct dentry *unlink_dir_dentry;
++
++ BUG_ON(bindex < 0);
++ unlink_dentry = unionfs_lower_dentry_idx(new_dentry, bindex);
++ if (!unlink_dentry)
++ continue;
++
++ unlink_dir_dentry = lock_parent(unlink_dentry);
++ err = is_robranch_super(old_dir->i_sb, bindex);
++ if (!err)
++ err = vfs_unlink(unlink_dir_dentry->d_inode,
++ unlink_dentry);
++
++ fsstack_copy_attr_times(new_parent->d_inode,
++ unlink_dir_dentry->d_inode);
++ /* propagate number of hard-links */
++ new_parent->d_inode->i_nlink =
++ unionfs_get_nlinks(new_parent->d_inode);
++
++ unlock_dir(unlink_dir_dentry);
++ if (!err) {
++ if (bindex != new_bstart) {
++ dput(unlink_dentry);
++ unionfs_set_lower_dentry_idx(new_dentry,
++ bindex, NULL);
++ }
++ } else if (IS_COPYUP_ERR(err)) {
++ do_copyup = bindex - 1;
++ } else if (revert) {
++ goto revert;
++ }
++ }
++
++ if (do_copyup != -1) {
++ for (bindex = do_copyup; bindex >= 0; bindex--) {
++ /*
++ * copyup the file into some left directory, so that
++ * you can rename it
++ */
++ err = copyup_dentry(old_parent->d_inode,
++ old_dentry, old_bstart, bindex,
++ old_dentry->d_name.name,
++ old_dentry->d_name.len, NULL,
++ i_size_read(old_dentry->d_inode));
++ /* if copyup failed, try next branch to the left */
++ if (err)
++ continue;
++ /*
++ * create whiteout before calling __unionfs_rename
++ * because the latter will change the old_dentry's
++ * lower name and parent dir, resulting in the
++ * whiteout getting created in the wrong dir.
++ */
++ err = create_whiteout(old_dentry, bindex);
++ if (err) {
++ printk(KERN_ERR "unionfs: can't create a "
++ "whiteout for %s in rename (err=%d)\n",
++ old_dentry->d_name.name, err);
++ continue;
++ }
++ err = __unionfs_rename(old_dir, old_dentry, old_parent,
++ new_dir, new_dentry, new_parent,
++ bindex);
++ break;
++ }
++ }
++
++ /* make it opaque */
++ if (S_ISDIR(old_dentry->d_inode->i_mode)) {
++ err = make_dir_opaque(old_dentry, dbstart(old_dentry));
++ if (err)
++ goto revert;
++ }
++
++ /*
++ * Create whiteout for source, only if:
++ * (1) There is more than one underlying instance of source.
++ * (We did a copy_up is taken care of above).
++ */
++ if ((old_bstart != old_bend) && (do_copyup == -1)) {
++ err = create_whiteout(old_dentry, old_bstart);
++ if (err) {
++ /* can't fix anything now, so we exit with -EIO */
++ printk(KERN_ERR "unionfs: can't create a whiteout for "
++ "%s in rename!\n", old_dentry->d_name.name);
++ err = -EIO;
++ }
++ }
++
++out:
++ return err;
++
++revert:
++ /* Do revert here. */
++ local_err = unionfs_refresh_lower_dentry(new_dentry, new_parent,
++ old_bstart);
++ if (local_err) {
++ printk(KERN_ERR "unionfs: revert failed in rename: "
++ "the new refresh failed\n");
++ eio = -EIO;
++ }
++
++ local_err = unionfs_refresh_lower_dentry(old_dentry, old_parent,
++ old_bstart);
++ if (local_err) {
++ printk(KERN_ERR "unionfs: revert failed in rename: "
++ "the old refresh failed\n");
++ eio = -EIO;
++ goto revert_out;
++ }
++
++ if (!unionfs_lower_dentry_idx(new_dentry, bindex) ||
++ !unionfs_lower_dentry_idx(new_dentry, bindex)->d_inode) {
++ printk(KERN_ERR "unionfs: revert failed in rename: "
++ "the object disappeared from under us!\n");
++ eio = -EIO;
++ goto revert_out;
++ }
++
++ if (unionfs_lower_dentry_idx(old_dentry, bindex) &&
++ unionfs_lower_dentry_idx(old_dentry, bindex)->d_inode) {
++ printk(KERN_ERR "unionfs: revert failed in rename: "
++ "the object was created underneath us!\n");
++ eio = -EIO;
++ goto revert_out;
++ }
++
++ local_err = __unionfs_rename(new_dir, new_dentry, new_parent,
++ old_dir, old_dentry, old_parent,
++ old_bstart);
++
++ /* If we can't fix it, then we cop-out with -EIO. */
++ if (local_err) {
++ printk(KERN_ERR "unionfs: revert failed in rename!\n");
++ eio = -EIO;
++ }
++
++ local_err = unionfs_refresh_lower_dentry(new_dentry, new_parent,
++ bindex);
++ if (local_err)
++ eio = -EIO;
++ local_err = unionfs_refresh_lower_dentry(old_dentry, old_parent,
++ bindex);
++ if (local_err)
++ eio = -EIO;
++
++revert_out:
++ if (eio)
++ err = eio;
++ return err;
++}
++
++/*
++ * We can't copyup a directory, because it may involve huge numbers of
++ * children, etc. Doing that in the kernel would be bad, so instead we
++ * return EXDEV to the user-space utility that caused this, and let the
++ * user-space recurse and ask us to copy up each file separately.
++ */
++static int may_rename_dir(struct dentry *dentry, struct dentry *parent)
++{
++ int err, bstart;
++
++ err = check_empty(dentry, parent, NULL);
++ if (err == -ENOTEMPTY) {
++ if (is_robranch(dentry))
++ return -EXDEV;
++ } else if (err) {
++ return err;
++ }
++
++ bstart = dbstart(dentry);
++ if (dbend(dentry) == bstart || dbopaque(dentry) == bstart)
++ return 0;
++
++ dbstart(dentry) = bstart + 1;
++ err = check_empty(dentry, parent, NULL);
++ dbstart(dentry) = bstart;
++ if (err == -ENOTEMPTY)
++ err = -EXDEV;
++ return err;
++}
++
++/*
++ * The locking rules in unionfs_rename are complex. We could use a simpler
++ * superblock-level name-space lock for renames and copy-ups.
++ */
++int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
++ struct inode *new_dir, struct dentry *new_dentry)
++{
++ int err = 0;
++ struct dentry *wh_dentry;
++ struct dentry *old_parent, *new_parent;
++ int valid = true;
++
++ unionfs_read_lock(old_dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ old_parent = dget_parent(old_dentry);
++ new_parent = dget_parent(new_dentry);
++ /* un/lock parent dentries only if they differ from old/new_dentry */
++ if (old_parent != old_dentry &&
++ old_parent != new_dentry)
++ unionfs_lock_dentry(old_parent, UNIONFS_DMUTEX_REVAL_PARENT);
++ if (new_parent != old_dentry &&
++ new_parent != new_dentry &&
++ new_parent != old_parent)
++ unionfs_lock_dentry(new_parent, UNIONFS_DMUTEX_REVAL_CHILD);
++ unionfs_double_lock_dentry(old_dentry, new_dentry);
++
++ valid = __unionfs_d_revalidate(old_dentry, old_parent, false);
++ if (!valid) {
++ err = -ESTALE;
++ goto out;
++ }
++ if (!d_deleted(new_dentry) && new_dentry->d_inode) {
++ valid = __unionfs_d_revalidate(new_dentry, new_parent, false);
++ if (!valid) {
++ err = -ESTALE;
++ goto out;
++ }
++ }
++
++ if (!S_ISDIR(old_dentry->d_inode->i_mode))
++ err = unionfs_partial_lookup(old_dentry, old_parent);
++ else
++ err = may_rename_dir(old_dentry, old_parent);
++
++ if (err)
++ goto out;
++
++ err = unionfs_partial_lookup(new_dentry, new_parent);
++ if (err)
++ goto out;
++
++ /*
++ * if new_dentry is already lower because of whiteout,
++ * simply override it even if the whited-out dir is not empty.
++ */
++ wh_dentry = find_first_whiteout(new_dentry);
++ if (!IS_ERR(wh_dentry)) {
++ dput(wh_dentry);
++ } else if (new_dentry->d_inode) {
++ if (S_ISDIR(old_dentry->d_inode->i_mode) !=
++ S_ISDIR(new_dentry->d_inode->i_mode)) {
++ err = S_ISDIR(old_dentry->d_inode->i_mode) ?
++ -ENOTDIR : -EISDIR;
++ goto out;
++ }
++
++ if (S_ISDIR(new_dentry->d_inode->i_mode)) {
++ struct unionfs_dir_state *namelist = NULL;
++ /* check if this unionfs directory is empty or not */
++ err = check_empty(new_dentry, new_parent, &namelist);
++ if (err)
++ goto out;
++
++ if (!is_robranch(new_dentry))
++ err = delete_whiteouts(new_dentry,
++ dbstart(new_dentry),
++ namelist);
++
++ free_rdstate(namelist);
++
++ if (err)
++ goto out;
++ }
++ }
++
++ err = do_unionfs_rename(old_dir, old_dentry, old_parent,
++ new_dir, new_dentry, new_parent);
++ if (err)
++ goto out;
++
++ /*
++ * force re-lookup since the dir on ro branch is not renamed, and
++ * lower dentries still indicate the un-renamed ones.
++ */
++ if (S_ISDIR(old_dentry->d_inode->i_mode))
++ atomic_dec(&UNIONFS_D(old_dentry)->generation);
++ else
++ unionfs_postcopyup_release(old_dentry);
++ if (new_dentry->d_inode && !S_ISDIR(new_dentry->d_inode->i_mode)) {
++ unionfs_postcopyup_release(new_dentry);
++ unionfs_postcopyup_setmnt(new_dentry);
++ if (!unionfs_lower_inode(new_dentry->d_inode)) {
++ /*
++ * If we get here, it means that no copyup was
++ * needed, and that a file by the old name already
++ * existing on the destination branch; that file got
++ * renamed earlier in this function, so all we need
++ * to do here is set the lower inode.
++ */
++ struct inode *inode;
++ inode = unionfs_lower_inode(old_dentry->d_inode);
++ igrab(inode);
++ unionfs_set_lower_inode_idx(new_dentry->d_inode,
++ dbstart(new_dentry),
++ inode);
++ }
++ }
++ /* if all of this renaming succeeded, update our times */
++ unionfs_copy_attr_times(old_dentry->d_inode);
++ unionfs_copy_attr_times(new_dentry->d_inode);
++ unionfs_check_inode(old_dir);
++ unionfs_check_inode(new_dir);
++ unionfs_check_dentry(old_dentry);
++ unionfs_check_dentry(new_dentry);
++
++out:
++ if (err) /* clear the new_dentry stuff created */
++ d_drop(new_dentry);
++
++ unionfs_double_unlock_dentry(old_dentry, new_dentry);
++ if (new_parent != old_dentry &&
++ new_parent != new_dentry &&
++ new_parent != old_parent)
++ unionfs_unlock_dentry(new_parent);
++ if (old_parent != old_dentry &&
++ old_parent != new_dentry)
++ unionfs_unlock_dentry(old_parent);
++ dput(new_parent);
++ dput(old_parent);
++ unionfs_read_unlock(old_dentry->d_sb);
++
++ return err;
++}
+diff --git a/fs/unionfs/sioq.c b/fs/unionfs/sioq.c
+new file mode 100644
+index 0000000..760c580
+--- /dev/null
++++ b/fs/unionfs/sioq.c
+@@ -0,0 +1,101 @@
++/*
++ * Copyright (c) 2006-2010 Erez Zadok
++ * Copyright (c) 2006 Charles P. Wright
++ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2006 Junjiro Okajima
++ * Copyright (c) 2006 David P. Quigley
++ * Copyright (c) 2006-2010 Stony Brook University
++ * Copyright (c) 2006-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++/*
++ * Super-user IO work Queue - sometimes we need to perform actions which
++ * would fail due to the unix permissions on the parent directory (e.g.,
++ * rmdir a directory which appears empty, but in reality contains
++ * whiteouts).
++ */
++
++static struct workqueue_struct *superio_workqueue;
++
++int __init init_sioq(void)
++{
++ int err;
++
++ superio_workqueue = create_workqueue("unionfs_siod");
++ if (!IS_ERR(superio_workqueue))
++ return 0;
++
++ err = PTR_ERR(superio_workqueue);
++ printk(KERN_ERR "unionfs: create_workqueue failed %d\n", err);
++ superio_workqueue = NULL;
++ return err;
++}
++
++void stop_sioq(void)
++{
++ if (superio_workqueue)
++ destroy_workqueue(superio_workqueue);
++}
++
++void run_sioq(work_func_t func, struct sioq_args *args)
++{
++ INIT_WORK(&args->work, func);
++
++ init_completion(&args->comp);
++ while (!queue_work(superio_workqueue, &args->work)) {
++ /* TODO: do accounting if needed */
++ schedule();
++ }
++ wait_for_completion(&args->comp);
++}
++
++void __unionfs_create(struct work_struct *work)
++{
++ struct sioq_args *args = container_of(work, struct sioq_args, work);
++ struct create_args *c = &args->create;
++
++ args->err = vfs_create(c->parent, c->dentry, c->mode, c->nd);
++ complete(&args->comp);
++}
++
++void __unionfs_mkdir(struct work_struct *work)
++{
++ struct sioq_args *args = container_of(work, struct sioq_args, work);
++ struct mkdir_args *m = &args->mkdir;
++
++ args->err = vfs_mkdir(m->parent, m->dentry, m->mode);
++ complete(&args->comp);
++}
++
++void __unionfs_mknod(struct work_struct *work)
++{
++ struct sioq_args *args = container_of(work, struct sioq_args, work);
++ struct mknod_args *m = &args->mknod;
++
++ args->err = vfs_mknod(m->parent, m->dentry, m->mode, m->dev);
++ complete(&args->comp);
++}
++
++void __unionfs_symlink(struct work_struct *work)
++{
++ struct sioq_args *args = container_of(work, struct sioq_args, work);
++ struct symlink_args *s = &args->symlink;
++
++ args->err = vfs_symlink(s->parent, s->dentry, s->symbuf);
++ complete(&args->comp);
++}
++
++void __unionfs_unlink(struct work_struct *work)
++{
++ struct sioq_args *args = container_of(work, struct sioq_args, work);
++ struct unlink_args *u = &args->unlink;
++
++ args->err = vfs_unlink(u->parent, u->dentry);
++ complete(&args->comp);
++}
+diff --git a/fs/unionfs/sioq.h b/fs/unionfs/sioq.h
+new file mode 100644
+index 0000000..b26d248
+--- /dev/null
++++ b/fs/unionfs/sioq.h
+@@ -0,0 +1,91 @@
++/*
++ * Copyright (c) 2006-2010 Erez Zadok
++ * Copyright (c) 2006 Charles P. Wright
++ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2006 Junjiro Okajima
++ * Copyright (c) 2006 David P. Quigley
++ * Copyright (c) 2006-2010 Stony Brook University
++ * Copyright (c) 2006-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#ifndef _SIOQ_H
++#define _SIOQ_H
++
++struct deletewh_args {
++ struct unionfs_dir_state *namelist;
++ struct dentry *dentry;
++ int bindex;
++};
++
++struct is_opaque_args {
++ struct dentry *dentry;
++};
++
++struct create_args {
++ struct inode *parent;
++ struct dentry *dentry;
++ umode_t mode;
++ struct nameidata *nd;
++};
++
++struct mkdir_args {
++ struct inode *parent;
++ struct dentry *dentry;
++ umode_t mode;
++};
++
++struct mknod_args {
++ struct inode *parent;
++ struct dentry *dentry;
++ umode_t mode;
++ dev_t dev;
++};
++
++struct symlink_args {
++ struct inode *parent;
++ struct dentry *dentry;
++ char *symbuf;
++};
++
++struct unlink_args {
++ struct inode *parent;
++ struct dentry *dentry;
++};
++
++
++struct sioq_args {
++ struct completion comp;
++ struct work_struct work;
++ int err;
++ void *ret;
++
++ union {
++ struct deletewh_args deletewh;
++ struct is_opaque_args is_opaque;
++ struct create_args create;
++ struct mkdir_args mkdir;
++ struct mknod_args mknod;
++ struct symlink_args symlink;
++ struct unlink_args unlink;
++ };
++};
++
++/* Extern definitions for SIOQ functions */
++extern int __init init_sioq(void);
++extern void stop_sioq(void);
++extern void run_sioq(work_func_t func, struct sioq_args *args);
++
++/* Extern definitions for our privilege escalation helpers */
++extern void __unionfs_create(struct work_struct *work);
++extern void __unionfs_mkdir(struct work_struct *work);
++extern void __unionfs_mknod(struct work_struct *work);
++extern void __unionfs_symlink(struct work_struct *work);
++extern void __unionfs_unlink(struct work_struct *work);
++extern void __delete_whiteouts(struct work_struct *work);
++extern void __is_opaque_dir(struct work_struct *work);
++
++#endif /* not _SIOQ_H */
+diff --git a/fs/unionfs/subr.c b/fs/unionfs/subr.c
+new file mode 100644
+index 0000000..570a344
+--- /dev/null
++++ b/fs/unionfs/subr.c
+@@ -0,0 +1,95 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++/*
++ * returns the right n_link value based on the inode type
++ */
++int unionfs_get_nlinks(const struct inode *inode)
++{
++ /* don't bother to do all the work since we're unlinked */
++ if (inode->i_nlink == 0)
++ return 0;
++
++ if (!S_ISDIR(inode->i_mode))
++ return unionfs_lower_inode(inode)->i_nlink;
++
++ /*
++ * For directories, we return 1. The only place that could cares
++ * about links is readdir, and there's d_type there so even that
++ * doesn't matter.
++ */
++ return 1;
++}
++
++/* copy a/m/ctime from the lower branch with the newest times */
++void unionfs_copy_attr_times(struct inode *upper)
++{
++ int bindex;
++ struct inode *lower;
++
++ if (!upper)
++ return;
++ if (ibstart(upper) < 0) {
++#ifdef CONFIG_UNION_FS_DEBUG
++ WARN_ON(ibstart(upper) < 0);
++#endif /* CONFIG_UNION_FS_DEBUG */
++ return;
++ }
++ for (bindex = ibstart(upper); bindex <= ibend(upper); bindex++) {
++ lower = unionfs_lower_inode_idx(upper, bindex);
++ if (!lower)
++ continue; /* not all lower dir objects may exist */
++ if (unlikely(timespec_compare(&upper->i_mtime,
++ &lower->i_mtime) < 0))
++ upper->i_mtime = lower->i_mtime;
++ if (unlikely(timespec_compare(&upper->i_ctime,
++ &lower->i_ctime) < 0))
++ upper->i_ctime = lower->i_ctime;
++ if (unlikely(timespec_compare(&upper->i_atime,
++ &lower->i_atime) < 0))
++ upper->i_atime = lower->i_atime;
++ }
++}
++
++/*
++ * A unionfs/fanout version of fsstack_copy_attr_all. Uses a
++ * unionfs_get_nlinks to properly calcluate the number of links to a file.
++ * Also, copies the max() of all a/m/ctimes for all lower inodes (which is
++ * important if the lower inode is a directory type)
++ */
++void unionfs_copy_attr_all(struct inode *dest,
++ const struct inode *src)
++{
++ dest->i_mode = src->i_mode;
++ dest->i_uid = src->i_uid;
++ dest->i_gid = src->i_gid;
++ dest->i_rdev = src->i_rdev;
++
++ unionfs_copy_attr_times(dest);
++
++ dest->i_blkbits = src->i_blkbits;
++ dest->i_flags = src->i_flags;
++
++ /*
++ * Update the nlinks AFTER updating the above fields, because the
++ * get_links callback may depend on them.
++ */
++ dest->i_nlink = unionfs_get_nlinks(dest);
++}
+diff --git a/fs/unionfs/super.c b/fs/unionfs/super.c
+new file mode 100644
+index 0000000..a8f5571
+--- /dev/null
++++ b/fs/unionfs/super.c
+@@ -0,0 +1,1048 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++/*
++ * The inode cache is used with alloc_inode for both our inode info and the
++ * vfs inode.
++ */
++static struct kmem_cache *unionfs_inode_cachep;
++
++struct inode *unionfs_iget(struct super_block *sb, unsigned long ino)
++{
++ int size;
++ struct unionfs_inode_info *info;
++ struct inode *inode;
++
++ inode = iget_locked(sb, ino);
++ if (!inode)
++ return ERR_PTR(-ENOMEM);
++ if (!(inode->i_state & I_NEW))
++ return inode;
++
++ info = UNIONFS_I(inode);
++ memset(info, 0, offsetof(struct unionfs_inode_info, vfs_inode));
++ info->bstart = -1;
++ info->bend = -1;
++ atomic_set(&info->generation,
++ atomic_read(&UNIONFS_SB(inode->i_sb)->generation));
++ spin_lock_init(&info->rdlock);
++ info->rdcount = 1;
++ info->hashsize = -1;
++ INIT_LIST_HEAD(&info->readdircache);
++
++ size = sbmax(inode->i_sb) * sizeof(struct inode *);
++ info->lower_inodes = kzalloc(size, GFP_KERNEL);
++ if (unlikely(!info->lower_inodes)) {
++ printk(KERN_CRIT "unionfs: no kernel memory when allocating "
++ "lower-pointer array!\n");
++ iget_failed(inode);
++ return ERR_PTR(-ENOMEM);
++ }
++
++ inode->i_version++;
++ inode->i_op = &unionfs_main_iops;
++ inode->i_fop = &unionfs_main_fops;
++
++ inode->i_mapping->a_ops = &unionfs_aops;
++
++ /*
++ * reset times so unionfs_copy_attr_all can keep out time invariants
++ * right (upper inode time being the max of all lower ones).
++ */
++ inode->i_atime.tv_sec = inode->i_atime.tv_nsec = 0;
++ inode->i_mtime.tv_sec = inode->i_mtime.tv_nsec = 0;
++ inode->i_ctime.tv_sec = inode->i_ctime.tv_nsec = 0;
++ unlock_new_inode(inode);
++ return inode;
++}
++
++/*
++ * we now define delete_inode, because there are two VFS paths that may
++ * destroy an inode: one of them calls clear inode before doing everything
++ * else that's needed, and the other is fine. This way we truncate the inode
++ * size (and its pages) and then clear our own inode, which will do an iput
++ * on our and the lower inode.
++ *
++ * No need to lock sb info's rwsem.
++ */
++static void unionfs_delete_inode(struct inode *inode)
++{
++#if BITS_PER_LONG == 32 && defined(CONFIG_SMP)
++ spin_lock(&inode->i_lock);
++#endif
++ i_size_write(inode, 0); /* every f/s seems to do that */
++#if BITS_PER_LONG == 32 && defined(CONFIG_SMP)
++ spin_unlock(&inode->i_lock);
++#endif
++
++ if (inode->i_data.nrpages)
++ truncate_inode_pages(&inode->i_data, 0);
++
++ clear_inode(inode);
++}
++
++/*
++ * final actions when unmounting a file system
++ *
++ * No need to lock rwsem.
++ */
++static void unionfs_put_super(struct super_block *sb)
++{
++ int bindex, bstart, bend;
++ struct unionfs_sb_info *spd;
++ int leaks = 0;
++
++ spd = UNIONFS_SB(sb);
++ if (!spd)
++ return;
++
++ bstart = sbstart(sb);
++ bend = sbend(sb);
++
++ /* Make sure we have no leaks of branchget/branchput. */
++ for (bindex = bstart; bindex <= bend; bindex++)
++ if (unlikely(branch_count(sb, bindex) != 0)) {
++ printk(KERN_CRIT
++ "unionfs: branch %d has %d references left!\n",
++ bindex, branch_count(sb, bindex));
++ leaks = 1;
++ }
++ WARN_ON(leaks != 0);
++
++ /* decrement lower super references */
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ struct super_block *s;
++ s = unionfs_lower_super_idx(sb, bindex);
++ unionfs_set_lower_super_idx(sb, bindex, NULL);
++ atomic_dec(&s->s_active);
++ }
++
++ kfree(spd->dev_name);
++ kfree(spd->data);
++ kfree(spd);
++ sb->s_fs_info = NULL;
++}
++
++/*
++ * Since people use this to answer the "How big of a file can I write?"
++ * question, we report the size of the highest priority branch as the size of
++ * the union.
++ */
++static int unionfs_statfs(struct dentry *dentry, struct kstatfs *buf)
++{
++ int err = 0;
++ struct super_block *sb;
++ struct dentry *lower_dentry;
++ struct dentry *parent;
++ bool valid;
++
++ sb = dentry->d_sb;
++
++ unionfs_read_lock(sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++ unionfs_check_dentry(dentry);
++
++ lower_dentry = unionfs_lower_dentry(sb->s_root);
++ err = vfs_statfs(lower_dentry, buf);
++
++ /* set return buf to our f/s to avoid confusing user-level utils */
++ buf->f_type = UNIONFS_SUPER_MAGIC;
++ /*
++ * Our maximum file name can is shorter by a few bytes because every
++ * file name could potentially be whited-out.
++ *
++ * XXX: this restriction goes away with ODF.
++ */
++ unionfs_set_max_namelen(&buf->f_namelen);
++
++ /*
++ * reset two fields to avoid confusing user-land.
++ * XXX: is this still necessary?
++ */
++ memset(&buf->f_fsid, 0, sizeof(__kernel_fsid_t));
++ memset(&buf->f_spare, 0, sizeof(buf->f_spare));
++
++out:
++ unionfs_check_dentry(dentry);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(sb);
++ return err;
++}
++
++/* handle mode changing during remount */
++static noinline_for_stack int do_remount_mode_option(
++ char *optarg,
++ int cur_branches,
++ struct unionfs_data *new_data,
++ struct path *new_lower_paths)
++{
++ int err = -EINVAL;
++ int perms, idx;
++ char *modename = strchr(optarg, '=');
++ struct nameidata nd;
++
++ /* by now, optarg contains the branch name */
++ if (!*optarg) {
++ printk(KERN_ERR
++ "unionfs: no branch specified for mode change\n");
++ goto out;
++ }
++ if (!modename) {
++ printk(KERN_ERR "unionfs: branch \"%s\" requires a mode\n",
++ optarg);
++ goto out;
++ }
++ *modename++ = '\0';
++ err = parse_branch_mode(modename, &perms);
++ if (err) {
++ printk(KERN_ERR "unionfs: invalid mode \"%s\" for \"%s\"\n",
++ modename, optarg);
++ goto out;
++ }
++
++ /*
++ * Find matching branch index. For now, this assumes that nothing
++ * has been mounted on top of this Unionfs stack. Once we have /odf
++ * and cache-coherency resolved, we'll address the branch-path
++ * uniqueness.
++ */
++ err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
++ if (err) {
++ printk(KERN_ERR "unionfs: error accessing "
++ "lower directory \"%s\" (error %d)\n",
++ optarg, err);
++ goto out;
++ }
++ for (idx = 0; idx < cur_branches; idx++)
++ if (nd.path.mnt == new_lower_paths[idx].mnt &&
++ nd.path.dentry == new_lower_paths[idx].dentry)
++ break;
++ path_put(&nd.path); /* no longer needed */
++ if (idx == cur_branches) {
++ err = -ENOENT; /* err may have been reset above */
++ printk(KERN_ERR "unionfs: branch \"%s\" "
++ "not found\n", optarg);
++ goto out;
++ }
++ /* check/change mode for existing branch */
++ /* we don't warn if perms==branchperms */
++ new_data[idx].branchperms = perms;
++ err = 0;
++out:
++ return err;
++}
++
++/* handle branch deletion during remount */
++static noinline_for_stack int do_remount_del_option(
++ char *optarg, int cur_branches,
++ struct unionfs_data *new_data,
++ struct path *new_lower_paths)
++{
++ int err = -EINVAL;
++ int idx;
++ struct nameidata nd;
++
++ /* optarg contains the branch name to delete */
++
++ /*
++ * Find matching branch index. For now, this assumes that nothing
++ * has been mounted on top of this Unionfs stack. Once we have /odf
++ * and cache-coherency resolved, we'll address the branch-path
++ * uniqueness.
++ */
++ err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
++ if (err) {
++ printk(KERN_ERR "unionfs: error accessing "
++ "lower directory \"%s\" (error %d)\n",
++ optarg, err);
++ goto out;
++ }
++ for (idx = 0; idx < cur_branches; idx++)
++ if (nd.path.mnt == new_lower_paths[idx].mnt &&
++ nd.path.dentry == new_lower_paths[idx].dentry)
++ break;
++ path_put(&nd.path); /* no longer needed */
++ if (idx == cur_branches) {
++ printk(KERN_ERR "unionfs: branch \"%s\" "
++ "not found\n", optarg);
++ err = -ENOENT;
++ goto out;
++ }
++ /* check if there are any open files on the branch to be deleted */
++ if (atomic_read(&new_data[idx].open_files) > 0) {
++ err = -EBUSY;
++ goto out;
++ }
++
++ /*
++ * Now we have to delete the branch. First, release any handles it
++ * has. Then, move the remaining array indexes past "idx" in
++ * new_data and new_lower_paths one to the left. Finally, adjust
++ * cur_branches.
++ */
++ path_put(&new_lower_paths[idx]);
++
++ if (idx < cur_branches - 1) {
++ /* if idx==cur_branches-1, we delete last branch: easy */
++ memmove(&new_data[idx], &new_data[idx+1],
++ (cur_branches - 1 - idx) *
++ sizeof(struct unionfs_data));
++ memmove(&new_lower_paths[idx], &new_lower_paths[idx+1],
++ (cur_branches - 1 - idx) * sizeof(struct path));
++ }
++
++ err = 0;
++out:
++ return err;
++}
++
++/* handle branch insertion during remount */
++static noinline_for_stack int do_remount_add_option(
++ char *optarg, int cur_branches,
++ struct unionfs_data *new_data,
++ struct path *new_lower_paths,
++ int *high_branch_id)
++{
++ int err = -EINVAL;
++ int perms;
++ int idx = 0; /* default: insert at beginning */
++ char *new_branch , *modename = NULL;
++ struct nameidata nd;
++
++ /*
++ * optarg can be of several forms:
++ *
++ * /bar:/foo insert /foo before /bar
++ * /bar:/foo=ro insert /foo in ro mode before /bar
++ * /foo insert /foo in the beginning (prepend)
++ * :/foo insert /foo at the end (append)
++ */
++ if (*optarg == ':') { /* append? */
++ new_branch = optarg + 1; /* skip ':' */
++ idx = cur_branches;
++ goto found_insertion_point;
++ }
++ new_branch = strchr(optarg, ':');
++ if (!new_branch) { /* prepend? */
++ new_branch = optarg;
++ goto found_insertion_point;
++ }
++ *new_branch++ = '\0'; /* holds path+mode of new branch */
++
++ /*
++ * Find matching branch index. For now, this assumes that nothing
++ * has been mounted on top of this Unionfs stack. Once we have /odf
++ * and cache-coherency resolved, we'll address the branch-path
++ * uniqueness.
++ */
++ err = path_lookup(optarg, LOOKUP_FOLLOW, &nd);
++ if (err) {
++ printk(KERN_ERR "unionfs: error accessing "
++ "lower directory \"%s\" (error %d)\n",
++ optarg, err);
++ goto out;
++ }
++ for (idx = 0; idx < cur_branches; idx++)
++ if (nd.path.mnt == new_lower_paths[idx].mnt &&
++ nd.path.dentry == new_lower_paths[idx].dentry)
++ break;
++ path_put(&nd.path); /* no longer needed */
++ if (idx == cur_branches) {
++ printk(KERN_ERR "unionfs: branch \"%s\" "
++ "not found\n", optarg);
++ err = -ENOENT;
++ goto out;
++ }
++
++ /*
++ * At this point idx will hold the index where the new branch should
++ * be inserted before.
++ */
++found_insertion_point:
++ /* find the mode for the new branch */
++ if (new_branch)
++ modename = strchr(new_branch, '=');
++ if (modename)
++ *modename++ = '\0';
++ if (!new_branch || !*new_branch) {
++ printk(KERN_ERR "unionfs: null new branch\n");
++ err = -EINVAL;
++ goto out;
++ }
++ err = parse_branch_mode(modename, &perms);
++ if (err) {
++ printk(KERN_ERR "unionfs: invalid mode \"%s\" for "
++ "branch \"%s\"\n", modename, new_branch);
++ goto out;
++ }
++ err = path_lookup(new_branch, LOOKUP_FOLLOW, &nd);
++ if (err) {
++ printk(KERN_ERR "unionfs: error accessing "
++ "lower directory \"%s\" (error %d)\n",
++ new_branch, err);
++ goto out;
++ }
++ /*
++ * It's probably safe to check_mode the new branch to insert. Note:
++ * we don't allow inserting branches which are unionfs's by
++ * themselves (check_branch returns EINVAL in that case). This is
++ * because this code base doesn't support stacking unionfs: the ODF
++ * code base supports that correctly.
++ */
++ err = check_branch(&nd);
++ if (err) {
++ printk(KERN_ERR "unionfs: lower directory "
++ "\"%s\" is not a valid branch\n", optarg);
++ path_put(&nd.path);
++ goto out;
++ }
++
++ /*
++ * Now we have to insert the new branch. But first, move the bits
++ * to make space for the new branch, if needed. Finally, adjust
++ * cur_branches.
++ * We don't release nd here; it's kept until umount/remount.
++ */
++ if (idx < cur_branches) {
++ /* if idx==cur_branches, we append: easy */
++ memmove(&new_data[idx+1], &new_data[idx],
++ (cur_branches - idx) * sizeof(struct unionfs_data));
++ memmove(&new_lower_paths[idx+1], &new_lower_paths[idx],
++ (cur_branches - idx) * sizeof(struct path));
++ }
++ new_lower_paths[idx].dentry = nd.path.dentry;
++ new_lower_paths[idx].mnt = nd.path.mnt;
++
++ new_data[idx].sb = nd.path.dentry->d_sb;
++ atomic_set(&new_data[idx].open_files, 0);
++ new_data[idx].branchperms = perms;
++ new_data[idx].branch_id = ++*high_branch_id; /* assign new branch ID */
++
++ err = 0;
++out:
++ return err;
++}
++
++
++/*
++ * Support branch management options on remount.
++ *
++ * See Documentation/filesystems/unionfs/ for details.
++ *
++ * @flags: numeric mount options
++ * @options: mount options string
++ *
++ * This function can rearrange a mounted union dynamically, adding and
++ * removing branches, including changing branch modes. Clearly this has to
++ * be done safely and atomically. Luckily, the VFS already calls this
++ * function with lock_super(sb) and lock_kernel() held, preventing
++ * concurrent mixing of new mounts, remounts, and unmounts. Moreover,
++ * do_remount_sb(), our caller function, already called shrink_dcache_sb(sb)
++ * to purge dentries/inodes from our superblock, and also called
++ * fsync_super(sb) to purge any dirty pages. So we're good.
++ *
++ * XXX: however, our remount code may also need to invalidate mapped pages
++ * so as to force them to be re-gotten from the (newly reconfigured) lower
++ * branches. This has to wait for proper mmap and cache coherency support
++ * in the VFS.
++ *
++ */
++static int unionfs_remount_fs(struct super_block *sb, int *flags,
++ char *options)
++{
++ int err = 0;
++ int i;
++ char *optionstmp, *tmp_to_free; /* kstrdup'ed of "options" */
++ char *optname;
++ int cur_branches = 0; /* no. of current branches */
++ int new_branches = 0; /* no. of branches actually left in the end */
++ int add_branches; /* est. no. of branches to add */
++ int del_branches; /* est. no. of branches to del */
++ int max_branches; /* max possible no. of branches */
++ struct unionfs_data *new_data = NULL, *tmp_data = NULL;
++ struct path *new_lower_paths = NULL, *tmp_lower_paths = NULL;
++ struct inode **new_lower_inodes = NULL;
++ int new_high_branch_id; /* new high branch ID */
++ int size; /* memory allocation size, temp var */
++ int old_ibstart, old_ibend;
++
++ unionfs_write_lock(sb);
++
++ /*
++ * The VFS will take care of "ro" and "rw" flags, and we can safely
++ * ignore MS_SILENT, but anything else left over is an error. So we
++ * need to check if any other flags may have been passed (none are
++ * allowed/supported as of now).
++ */
++ if ((*flags & ~(MS_RDONLY | MS_SILENT)) != 0) {
++ printk(KERN_ERR
++ "unionfs: remount flags 0x%x unsupported\n", *flags);
++ err = -EINVAL;
++ goto out_error;
++ }
++
++ /*
++ * If 'options' is NULL, it's probably because the user just changed
++ * the union to a "ro" or "rw" and the VFS took care of it. So
++ * nothing to do and we're done.
++ */
++ if (!options || options[0] == '\0')
++ goto out_error;
++
++ /*
++ * Find out how many branches we will have in the end, counting
++ * "add" and "del" commands. Copy the "options" string because
++ * strsep modifies the string and we need it later.
++ */
++ tmp_to_free = kstrdup(options, GFP_KERNEL);
++ optionstmp = tmp_to_free;
++ if (unlikely(!optionstmp)) {
++ err = -ENOMEM;
++ goto out_free;
++ }
++ cur_branches = sbmax(sb); /* current no. branches */
++ new_branches = sbmax(sb);
++ del_branches = 0;
++ add_branches = 0;
++ new_high_branch_id = sbhbid(sb); /* save current high_branch_id */
++ while ((optname = strsep(&optionstmp, ",")) != NULL) {
++ char *optarg;
++
++ if (!optname || !*optname)
++ continue;
++
++ optarg = strchr(optname, '=');
++ if (optarg)
++ *optarg++ = '\0';
++
++ if (!strcmp("add", optname))
++ add_branches++;
++ else if (!strcmp("del", optname))
++ del_branches++;
++ }
++ kfree(tmp_to_free);
++ /* after all changes, will we have at least one branch left? */
++ if ((new_branches + add_branches - del_branches) < 1) {
++ printk(KERN_ERR
++ "unionfs: no branches left after remount\n");
++ err = -EINVAL;
++ goto out_free;
++ }
++
++ /*
++ * Since we haven't actually parsed all the add/del options, nor
++ * have we checked them for errors, we don't know for sure how many
++ * branches we will have after all changes have taken place. In
++ * fact, the total number of branches left could be less than what
++ * we have now. So we need to allocate space for a temporary
++ * placeholder that is at least as large as the maximum number of
++ * branches we *could* have, which is the current number plus all
++ * the additions. Once we're done with these temp placeholders, we
++ * may have to re-allocate the final size, copy over from the temp,
++ * and then free the temps (done near the end of this function).
++ */
++ max_branches = cur_branches + add_branches;
++ /* allocate space for new pointers to lower dentry */
++ tmp_data = kcalloc(max_branches,
++ sizeof(struct unionfs_data), GFP_KERNEL);
++ if (unlikely(!tmp_data)) {
++ err = -ENOMEM;
++ goto out_free;
++ }
++ /* allocate space for new pointers to lower paths */
++ tmp_lower_paths = kcalloc(max_branches,
++ sizeof(struct path), GFP_KERNEL);
++ if (unlikely(!tmp_lower_paths)) {
++ err = -ENOMEM;
++ goto out_free;
++ }
++ /* copy current info into new placeholders, incrementing refcnts */
++ memcpy(tmp_data, UNIONFS_SB(sb)->data,
++ cur_branches * sizeof(struct unionfs_data));
++ memcpy(tmp_lower_paths, UNIONFS_D(sb->s_root)->lower_paths,
++ cur_branches * sizeof(struct path));
++ for (i = 0; i < cur_branches; i++)
++ path_get(&tmp_lower_paths[i]); /* drop refs at end of fxn */
++
++ /*******************************************************************
++ * For each branch command, do path_lookup on the requested branch,
++ * and apply the change to a temp branch list. To handle errors, we
++ * already dup'ed the old arrays (above), and increased the refcnts
++ * on various f/s objects. So now we can do all the path_lookups
++ * and branch-management commands on the new arrays. If it fail mid
++ * way, we free the tmp arrays and *put all objects. If we succeed,
++ * then we free old arrays and *put its objects, and then replace
++ * the arrays with the new tmp list (we may have to re-allocate the
++ * memory because the temp lists could have been larger than what we
++ * actually needed).
++ *******************************************************************/
++
++ while ((optname = strsep(&options, ",")) != NULL) {
++ char *optarg;
++
++ if (!optname || !*optname)
++ continue;
++ /*
++ * At this stage optname holds a comma-delimited option, but
++ * without the commas. Next, we need to break the string on
++ * the '=' symbol to separate CMD=ARG, where ARG itself can
++ * be KEY=VAL. For example, in mode=/foo=rw, CMD is "mode",
++ * KEY is "/foo", and VAL is "rw".
++ */
++ optarg = strchr(optname, '=');
++ if (optarg)
++ *optarg++ = '\0';
++ /* incgen remount option (instead of old ioctl) */
++ if (!strcmp("incgen", optname)) {
++ err = 0;
++ goto out_no_change;
++ }
++
++ /*
++ * All of our options take an argument now. (Insert ones
++ * that don't above this check.) So at this stage optname
++ * contains the CMD part and optarg contains the ARG part.
++ */
++ if (!optarg || !*optarg) {
++ printk(KERN_ERR "unionfs: all remount options require "
++ "an argument (%s)\n", optname);
++ err = -EINVAL;
++ goto out_release;
++ }
++
++ if (!strcmp("add", optname)) {
++ err = do_remount_add_option(optarg, new_branches,
++ tmp_data,
++ tmp_lower_paths,
++ &new_high_branch_id);
++ if (err)
++ goto out_release;
++ new_branches++;
++ if (new_branches > UNIONFS_MAX_BRANCHES) {
++ printk(KERN_ERR "unionfs: command exceeds "
++ "%d branches\n", UNIONFS_MAX_BRANCHES);
++ err = -E2BIG;
++ goto out_release;
++ }
++ continue;
++ }
++ if (!strcmp("del", optname)) {
++ err = do_remount_del_option(optarg, new_branches,
++ tmp_data,
++ tmp_lower_paths);
++ if (err)
++ goto out_release;
++ new_branches--;
++ continue;
++ }
++ if (!strcmp("mode", optname)) {
++ err = do_remount_mode_option(optarg, new_branches,
++ tmp_data,
++ tmp_lower_paths);
++ if (err)
++ goto out_release;
++ continue;
++ }
++
++ /*
++ * When you use "mount -o remount,ro", mount(8) will
++ * reportedly pass the original dirs= string from
++ * /proc/mounts. So for now, we have to ignore dirs= and
++ * not consider it an error, unless we want to allow users
++ * to pass dirs= in remount. Note that to allow the VFS to
++ * actually process the ro/rw remount options, we have to
++ * return 0 from this function.
++ */
++ if (!strcmp("dirs", optname)) {
++ printk(KERN_WARNING
++ "unionfs: remount ignoring option \"%s\"\n",
++ optname);
++ continue;
++ }
++
++ err = -EINVAL;
++ printk(KERN_ERR
++ "unionfs: unrecognized option \"%s\"\n", optname);
++ goto out_release;
++ }
++
++out_no_change:
++
++ /******************************************************************
++ * WE'RE ALMOST DONE: check if leftmost branch might be read-only,
++ * see if we need to allocate a small-sized new vector, copy the
++ * vectors to their correct place, release the refcnt of the older
++ * ones, and return. Also handle invalidating any pages that will
++ * have to be re-read.
++ *******************************************************************/
++
++ if (!(tmp_data[0].branchperms & MAY_WRITE)) {
++ printk(KERN_ERR "unionfs: leftmost branch cannot be read-only "
++ "(use \"remount,ro\" to create a read-only union)\n");
++ err = -EINVAL;
++ goto out_release;
++ }
++
++ /* (re)allocate space for new pointers to lower dentry */
++ size = new_branches * sizeof(struct unionfs_data);
++ new_data = krealloc(tmp_data, size, GFP_KERNEL);
++ if (unlikely(!new_data)) {
++ err = -ENOMEM;
++ goto out_release;
++ }
++
++ /* allocate space for new pointers to lower paths */
++ size = new_branches * sizeof(struct path);
++ new_lower_paths = krealloc(tmp_lower_paths, size, GFP_KERNEL);
++ if (unlikely(!new_lower_paths)) {
++ err = -ENOMEM;
++ goto out_release;
++ }
++
++ /* allocate space for new pointers to lower inodes */
++ new_lower_inodes = kcalloc(new_branches,
++ sizeof(struct inode *), GFP_KERNEL);
++ if (unlikely(!new_lower_inodes)) {
++ err = -ENOMEM;
++ goto out_release;
++ }
++
++ /*
++ * OK, just before we actually put the new set of branches in place,
++ * we need to ensure that our own f/s has no dirty objects left.
++ * Luckily, do_remount_sb() already calls shrink_dcache_sb(sb) and
++ * fsync_super(sb), taking care of dentries, inodes, and dirty
++ * pages. So all that's left is for us to invalidate any leftover
++ * (non-dirty) pages to ensure that they will be re-read from the
++ * new lower branches (and to support mmap).
++ */
++
++ /*
++ * Once we finish the remounting successfully, our superblock
++ * generation number will have increased. This will be detected by
++ * our dentry-revalidation code upon subsequent f/s operations
++ * through unionfs. The revalidation code will rebuild the union of
++ * lower inodes for a given unionfs inode and invalidate any pages
++ * of such "stale" inodes (by calling our purge_inode_data
++ * function). This revalidation will happen lazily and
++ * incrementally, as users perform operations on cached inodes. We
++ * would like to encourage this revalidation to happen sooner if
++ * possible, so we like to try to invalidate as many other pages in
++ * our superblock as we can. We used to call drop_pagecache_sb() or
++ * a variant thereof, but either method was racy (drop_caches alone
++ * is known to be racy). So now we let the revalidation happen on a
++ * per file basis in ->d_revalidate.
++ */
++
++ /* grab new lower super references; release old ones */
++ for (i = 0; i < new_branches; i++)
++ atomic_inc(&new_data[i].sb->s_active);
++ for (i = 0; i < sbmax(sb); i++)
++ atomic_dec(&UNIONFS_SB(sb)->data[i].sb->s_active);
++
++ /* copy new vectors into their correct place */
++ tmp_data = UNIONFS_SB(sb)->data;
++ UNIONFS_SB(sb)->data = new_data;
++ new_data = NULL; /* so don't free good pointers below */
++ tmp_lower_paths = UNIONFS_D(sb->s_root)->lower_paths;
++ UNIONFS_D(sb->s_root)->lower_paths = new_lower_paths;
++ new_lower_paths = NULL; /* so don't free good pointers below */
++
++ /* update our unionfs_sb_info and root dentry index of last branch */
++ i = sbmax(sb); /* save no. of branches to release at end */
++ sbend(sb) = new_branches - 1;
++ dbend(sb->s_root) = new_branches - 1;
++ old_ibstart = ibstart(sb->s_root->d_inode);
++ old_ibend = ibend(sb->s_root->d_inode);
++ ibend(sb->s_root->d_inode) = new_branches - 1;
++ UNIONFS_D(sb->s_root)->bcount = new_branches;
++ new_branches = i; /* no. of branches to release below */
++
++ /*
++ * Update lower inodes: 3 steps
++ * 1. grab ref on all new lower inodes
++ */
++ for (i = dbstart(sb->s_root); i <= dbend(sb->s_root); i++) {
++ struct dentry *lower_dentry =
++ unionfs_lower_dentry_idx(sb->s_root, i);
++ igrab(lower_dentry->d_inode);
++ new_lower_inodes[i] = lower_dentry->d_inode;
++ }
++ /* 2. release reference on all older lower inodes */
++ iput_lowers(sb->s_root->d_inode, old_ibstart, old_ibend, true);
++ /* 3. update root dentry's inode to new lower_inodes array */
++ UNIONFS_I(sb->s_root->d_inode)->lower_inodes = new_lower_inodes;
++ new_lower_inodes = NULL;
++
++ /* maxbytes may have changed */
++ sb->s_maxbytes = unionfs_lower_super_idx(sb, 0)->s_maxbytes;
++ /* update high branch ID */
++ sbhbid(sb) = new_high_branch_id;
++
++ /* update our sb->generation for revalidating objects */
++ i = atomic_inc_return(&UNIONFS_SB(sb)->generation);
++ atomic_set(&UNIONFS_D(sb->s_root)->generation, i);
++ atomic_set(&UNIONFS_I(sb->s_root->d_inode)->generation, i);
++ if (!(*flags & MS_SILENT))
++ pr_info("unionfs: %s: new generation number %d\n",
++ UNIONFS_SB(sb)->dev_name, i);
++ /* finally, update the root dentry's times */
++ unionfs_copy_attr_times(sb->s_root->d_inode);
++ err = 0; /* reset to success */
++
++ /*
++ * The code above falls through to the next label, and releases the
++ * refcnts of the older ones (stored in tmp_*): if we fell through
++ * here, it means success. However, if we jump directly to this
++ * label from any error above, then an error occurred after we
++ * grabbed various refcnts, and so we have to release the
++ * temporarily constructed structures.
++ */
++out_release:
++ /* no need to cleanup/release anything in tmp_data */
++ if (tmp_lower_paths)
++ for (i = 0; i < new_branches; i++)
++ path_put(&tmp_lower_paths[i]);
++out_free:
++ kfree(tmp_lower_paths);
++ kfree(tmp_data);
++ kfree(new_lower_paths);
++ kfree(new_data);
++ kfree(new_lower_inodes);
++out_error:
++ unionfs_check_dentry(sb->s_root);
++ unionfs_write_unlock(sb);
++ return err;
++}
++
++/*
++ * Called by iput() when the inode reference count reached zero
++ * and the inode is not hashed anywhere. Used to clear anything
++ * that needs to be, before the inode is completely destroyed and put
++ * on the inode free list.
++ *
++ * No need to lock sb info's rwsem.
++ */
++static void unionfs_clear_inode(struct inode *inode)
++{
++ int bindex, bstart, bend;
++ struct inode *lower_inode;
++ struct list_head *pos, *n;
++ struct unionfs_dir_state *rdstate;
++
++ list_for_each_safe(pos, n, &UNIONFS_I(inode)->readdircache) {
++ rdstate = list_entry(pos, struct unionfs_dir_state, cache);
++ list_del(&rdstate->cache);
++ free_rdstate(rdstate);
++ }
++
++ /*
++ * Decrement a reference to a lower_inode, which was incremented
++ * by our read_inode when it was created initially.
++ */
++ bstart = ibstart(inode);
++ bend = ibend(inode);
++ if (bstart >= 0) {
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_inode = unionfs_lower_inode_idx(inode, bindex);
++ if (!lower_inode)
++ continue;
++ unionfs_set_lower_inode_idx(inode, bindex, NULL);
++ /* see Documentation/filesystems/unionfs/issues.txt */
++ lockdep_off();
++ iput(lower_inode);
++ lockdep_on();
++ }
++ }
++
++ kfree(UNIONFS_I(inode)->lower_inodes);
++ UNIONFS_I(inode)->lower_inodes = NULL;
++}
++
++static struct inode *unionfs_alloc_inode(struct super_block *sb)
++{
++ struct unionfs_inode_info *i;
++
++ i = kmem_cache_alloc(unionfs_inode_cachep, GFP_KERNEL);
++ if (unlikely(!i))
++ return NULL;
++
++ /* memset everything up to the inode to 0 */
++ memset(i, 0, offsetof(struct unionfs_inode_info, vfs_inode));
++
++ i->vfs_inode.i_version = 1;
++ return &i->vfs_inode;
++}
++
++static void unionfs_destroy_inode(struct inode *inode)
++{
++ kmem_cache_free(unionfs_inode_cachep, UNIONFS_I(inode));
++}
++
++/* unionfs inode cache constructor */
++static void init_once(void *obj)
++{
++ struct unionfs_inode_info *i = obj;
++
++ inode_init_once(&i->vfs_inode);
++}
++
++int unionfs_init_inode_cache(void)
++{
++ int err = 0;
++
++ unionfs_inode_cachep =
++ kmem_cache_create("unionfs_inode_cache",
++ sizeof(struct unionfs_inode_info), 0,
++ SLAB_RECLAIM_ACCOUNT, init_once);
++ if (unlikely(!unionfs_inode_cachep))
++ err = -ENOMEM;
++ return err;
++}
++
++/* unionfs inode cache destructor */
++void unionfs_destroy_inode_cache(void)
++{
++ if (unionfs_inode_cachep)
++ kmem_cache_destroy(unionfs_inode_cachep);
++}
++
++/*
++ * Called when we have a dirty inode, right here we only throw out
++ * parts of our readdir list that are too old.
++ *
++ * No need to grab sb info's rwsem.
++ */
++static int unionfs_write_inode(struct inode *inode,
++ struct writeback_control *wbc)
++{
++ struct list_head *pos, *n;
++ struct unionfs_dir_state *rdstate;
++
++ spin_lock(&UNIONFS_I(inode)->rdlock);
++ list_for_each_safe(pos, n, &UNIONFS_I(inode)->readdircache) {
++ rdstate = list_entry(pos, struct unionfs_dir_state, cache);
++ /* We keep this list in LRU order. */
++ if ((rdstate->access + RDCACHE_JIFFIES) > jiffies)
++ break;
++ UNIONFS_I(inode)->rdcount--;
++ list_del(&rdstate->cache);
++ free_rdstate(rdstate);
++ }
++ spin_unlock(&UNIONFS_I(inode)->rdlock);
++
++ return 0;
++}
++
++/*
++ * Used only in nfs, to kill any pending RPC tasks, so that subsequent
++ * code can actually succeed and won't leave tasks that need handling.
++ */
++static void unionfs_umount_begin(struct super_block *sb)
++{
++ struct super_block *lower_sb;
++ int bindex, bstart, bend;
++
++ unionfs_read_lock(sb, UNIONFS_SMUTEX_CHILD);
++
++ bstart = sbstart(sb);
++ bend = sbend(sb);
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_sb = unionfs_lower_super_idx(sb, bindex);
++
++ if (lower_sb && lower_sb->s_op &&
++ lower_sb->s_op->umount_begin)
++ lower_sb->s_op->umount_begin(lower_sb);
++ }
++
++ unionfs_read_unlock(sb);
++}
++
++static int unionfs_show_options(struct seq_file *m, struct vfsmount *mnt)
++{
++ struct super_block *sb = mnt->mnt_sb;
++ int ret = 0;
++ char *tmp_page;
++ char *path;
++ int bindex, bstart, bend;
++ int perms;
++
++ unionfs_read_lock(sb, UNIONFS_SMUTEX_CHILD);
++
++ unionfs_lock_dentry(sb->s_root, UNIONFS_DMUTEX_CHILD);
++
++ tmp_page = (char *) __get_free_page(GFP_KERNEL);
++ if (unlikely(!tmp_page)) {
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ bstart = sbstart(sb);
++ bend = sbend(sb);
++
++ seq_printf(m, ",dirs=");
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ struct path p;
++ p.dentry = unionfs_lower_dentry_idx(sb->s_root, bindex);
++ p.mnt = unionfs_lower_mnt_idx(sb->s_root, bindex);
++ path = d_path(&p, tmp_page, PAGE_SIZE);
++ if (IS_ERR(path)) {
++ ret = PTR_ERR(path);
++ goto out;
++ }
++
++ perms = branchperms(sb, bindex);
++
++ seq_printf(m, "%s=%s", path,
++ perms & MAY_WRITE ? "rw" : "ro");
++ if (bindex != bend)
++ seq_printf(m, ":");
++ }
++
++out:
++ free_page((unsigned long) tmp_page);
++
++ unionfs_unlock_dentry(sb->s_root);
++
++ unionfs_read_unlock(sb);
++
++ return ret;
++}
++
++struct super_operations unionfs_sops = {
++ .delete_inode = unionfs_delete_inode,
++ .put_super = unionfs_put_super,
++ .statfs = unionfs_statfs,
++ .remount_fs = unionfs_remount_fs,
++ .clear_inode = unionfs_clear_inode,
++ .umount_begin = unionfs_umount_begin,
++ .show_options = unionfs_show_options,
++ .write_inode = unionfs_write_inode,
++ .alloc_inode = unionfs_alloc_inode,
++ .destroy_inode = unionfs_destroy_inode,
++};
+diff --git a/fs/unionfs/union.h b/fs/unionfs/union.h
+new file mode 100644
+index 0000000..d49c834
+--- /dev/null
++++ b/fs/unionfs/union.h
+@@ -0,0 +1,669 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#ifndef _UNION_H_
++#define _UNION_H_
++
++#include <linux/dcache.h>
++#include <linux/file.h>
++#include <linux/list.h>
++#include <linux/fs.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/mount.h>
++#include <linux/namei.h>
++#include <linux/page-flags.h>
++#include <linux/pagemap.h>
++#include <linux/poll.h>
++#include <linux/security.h>
++#include <linux/seq_file.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <linux/smp_lock.h>
++#include <linux/statfs.h>
++#include <linux/string.h>
++#include <linux/vmalloc.h>
++#include <linux/writeback.h>
++#include <linux/buffer_head.h>
++#include <linux/xattr.h>
++#include <linux/fs_stack.h>
++#include <linux/magic.h>
++#include <linux/log2.h>
++#include <linux/poison.h>
++#include <linux/mman.h>
++#include <linux/backing-dev.h>
++#include <linux/splice.h>
++
++#include <asm/system.h>
++
++#include <linux/union_fs.h>
++
++/* the file system name */
++#define UNIONFS_NAME "unionfs"
++
++/* unionfs root inode number */
++#define UNIONFS_ROOT_INO 1
++
++/* number of times we try to get a unique temporary file name */
++#define GET_TMPNAM_MAX_RETRY 5
++
++/* maximum number of branches we support, to avoid memory blowup */
++#define UNIONFS_MAX_BRANCHES 128
++
++/* minimum time (seconds) required for time-based cache-coherency */
++#define UNIONFS_MIN_CC_TIME 3
++
++/* Operations vectors defined in specific files. */
++extern struct file_operations unionfs_main_fops;
++extern struct file_operations unionfs_dir_fops;
++extern struct inode_operations unionfs_main_iops;
++extern struct inode_operations unionfs_dir_iops;
++extern struct inode_operations unionfs_symlink_iops;
++extern struct super_operations unionfs_sops;
++extern struct dentry_operations unionfs_dops;
++extern struct address_space_operations unionfs_aops, unionfs_dummy_aops;
++extern struct vm_operations_struct unionfs_vm_ops;
++
++/* How long should an entry be allowed to persist */
++#define RDCACHE_JIFFIES (5*HZ)
++
++/* compatibility with Real-Time patches */
++#ifdef CONFIG_PREEMPT_RT
++# define unionfs_rw_semaphore compat_rw_semaphore
++#else /* not CONFIG_PREEMPT_RT */
++# define unionfs_rw_semaphore rw_semaphore
++#endif /* not CONFIG_PREEMPT_RT */
++
++/* file private data. */
++struct unionfs_file_info {
++ int bstart;
++ int bend;
++ atomic_t generation;
++
++ struct unionfs_dir_state *rdstate;
++ struct file **lower_files;
++ int *saved_branch_ids; /* IDs of branches when file was opened */
++ const struct vm_operations_struct *lower_vm_ops;
++ bool wrote_to_file; /* for delayed copyup */
++};
++
++/* unionfs inode data in memory */
++struct unionfs_inode_info {
++ int bstart;
++ int bend;
++ atomic_t generation;
++ /* Stuff for readdir over NFS. */
++ spinlock_t rdlock;
++ struct list_head readdircache;
++ int rdcount;
++ int hashsize;
++ int cookie;
++
++ /* The lower inodes */
++ struct inode **lower_inodes;
++
++ struct inode vfs_inode;
++};
++
++/* unionfs dentry data in memory */
++struct unionfs_dentry_info {
++ /*
++ * The semaphore is used to lock the dentry as soon as we get into a
++ * unionfs function from the VFS. Our lock ordering is that children
++ * go before their parents.
++ */
++ struct mutex lock;
++ int bstart;
++ int bend;
++ int bopaque;
++ int bcount;
++ atomic_t generation;
++ struct path *lower_paths;
++};
++
++/* These are the pointers to our various objects. */
++struct unionfs_data {
++ struct super_block *sb; /* lower super_block */
++ atomic_t open_files; /* number of open files on branch */
++ int branchperms;
++ int branch_id; /* unique branch ID at re/mount time */
++};
++
++/* unionfs super-block data in memory */
++struct unionfs_sb_info {
++ int bend;
++
++ atomic_t generation;
++
++ /*
++ * This rwsem is used to make sure that a branch management
++ * operation...
++ * 1) will not begin before all currently in-flight operations
++ * complete.
++ * 2) any new operations do not execute until the currently
++ * running branch management operation completes.
++ *
++ * The write_lock_owner records the PID of the task which grabbed
++ * the rw_sem for writing. If the same task also tries to grab the
++ * read lock, we allow it. This prevents a self-deadlock when
++ * branch-management is used on a pivot_root'ed union, because we
++ * have to ->lookup paths which belong to the same union.
++ */
++ struct unionfs_rw_semaphore rwsem;
++ pid_t write_lock_owner; /* PID of rw_sem owner (write lock) */
++ int high_branch_id; /* last unique branch ID given */
++ char *dev_name; /* to identify different unions in pr_debug */
++ struct unionfs_data *data;
++};
++
++/*
++ * structure for making the linked list of entries by readdir on left branch
++ * to compare with entries on right branch
++ */
++struct filldir_node {
++ struct list_head file_list; /* list for directory entries */
++ char *name; /* name entry */
++ int hash; /* name hash */
++ int namelen; /* name len since name is not 0 terminated */
++
++ /*
++ * we can check for duplicate whiteouts and files in the same branch
++ * in order to return -EIO.
++ */
++ int bindex;
++
++ /* is this a whiteout entry? */
++ int whiteout;
++
++ /* Inline name, so we don't need to separately kmalloc small ones */
++ char iname[DNAME_INLINE_LEN_MIN];
++};
++
++/* Directory hash table. */
++struct unionfs_dir_state {
++ unsigned int cookie; /* the cookie, based off of rdversion */
++ unsigned int offset; /* The entry we have returned. */
++ int bindex;
++ loff_t dirpos; /* offset within the lower level directory */
++ int size; /* How big is the hash table? */
++ int hashentries; /* How many entries have been inserted? */
++ unsigned long access;
++
++ /* This cache list is used when the inode keeps us around. */
++ struct list_head cache;
++ struct list_head list[0];
++};
++
++/* externs needed for fanout.h or sioq.h */
++extern int unionfs_get_nlinks(const struct inode *inode);
++extern void unionfs_copy_attr_times(struct inode *upper);
++extern void unionfs_copy_attr_all(struct inode *dest, const struct inode *src);
++
++/* include miscellaneous macros */
++#include "fanout.h"
++#include "sioq.h"
++
++/* externs for cache creation/deletion routines */
++extern void unionfs_destroy_filldir_cache(void);
++extern int unionfs_init_filldir_cache(void);
++extern int unionfs_init_inode_cache(void);
++extern void unionfs_destroy_inode_cache(void);
++extern int unionfs_init_dentry_cache(void);
++extern void unionfs_destroy_dentry_cache(void);
++
++/* Initialize and free readdir-specific state. */
++extern int init_rdstate(struct file *file);
++extern struct unionfs_dir_state *alloc_rdstate(struct inode *inode,
++ int bindex);
++extern struct unionfs_dir_state *find_rdstate(struct inode *inode,
++ loff_t fpos);
++extern void free_rdstate(struct unionfs_dir_state *state);
++extern int add_filldir_node(struct unionfs_dir_state *rdstate,
++ const char *name, int namelen, int bindex,
++ int whiteout);
++extern struct filldir_node *find_filldir_node(struct unionfs_dir_state *rdstate,
++ const char *name, int namelen,
++ int is_whiteout);
++
++extern struct dentry **alloc_new_dentries(int objs);
++extern struct unionfs_data *alloc_new_data(int objs);
++
++/* We can only use 32-bits of offset for rdstate --- blech! */
++#define DIREOF (0xfffff)
++#define RDOFFBITS 20 /* This is the number of bits in DIREOF. */
++#define MAXRDCOOKIE (0xfff)
++/* Turn an rdstate into an offset. */
++static inline off_t rdstate2offset(struct unionfs_dir_state *buf)
++{
++ off_t tmp;
++
++ tmp = ((buf->cookie & MAXRDCOOKIE) << RDOFFBITS)
++ | (buf->offset & DIREOF);
++ return tmp;
++}
++
++/* Macros for locking a super_block. */
++enum unionfs_super_lock_class {
++ UNIONFS_SMUTEX_NORMAL,
++ UNIONFS_SMUTEX_PARENT, /* when locking on behalf of file */
++ UNIONFS_SMUTEX_CHILD, /* when locking on behalf of dentry */
++};
++static inline void unionfs_read_lock(struct super_block *sb, int subclass)
++{
++ if (UNIONFS_SB(sb)->write_lock_owner &&
++ UNIONFS_SB(sb)->write_lock_owner == current->pid)
++ return;
++ down_read_nested(&UNIONFS_SB(sb)->rwsem, subclass);
++}
++static inline void unionfs_read_unlock(struct super_block *sb)
++{
++ if (UNIONFS_SB(sb)->write_lock_owner &&
++ UNIONFS_SB(sb)->write_lock_owner == current->pid)
++ return;
++ up_read(&UNIONFS_SB(sb)->rwsem);
++}
++static inline void unionfs_write_lock(struct super_block *sb)
++{
++ down_write(&UNIONFS_SB(sb)->rwsem);
++ UNIONFS_SB(sb)->write_lock_owner = current->pid;
++}
++static inline void unionfs_write_unlock(struct super_block *sb)
++{
++ up_write(&UNIONFS_SB(sb)->rwsem);
++ UNIONFS_SB(sb)->write_lock_owner = 0;
++}
++
++static inline void unionfs_double_lock_dentry(struct dentry *d1,
++ struct dentry *d2)
++{
++ BUG_ON(d1 == d2);
++ if (d1 < d2) {
++ unionfs_lock_dentry(d1, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(d2, UNIONFS_DMUTEX_CHILD);
++ } else {
++ unionfs_lock_dentry(d2, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(d1, UNIONFS_DMUTEX_CHILD);
++ }
++}
++
++static inline void unionfs_double_unlock_dentry(struct dentry *d1,
++ struct dentry *d2)
++{
++ BUG_ON(d1 == d2);
++ if (d1 < d2) { /* unlock in reverse order than double_lock_dentry */
++ unionfs_unlock_dentry(d1);
++ unionfs_unlock_dentry(d2);
++ } else {
++ unionfs_unlock_dentry(d2);
++ unionfs_unlock_dentry(d1);
++ }
++}
++
++static inline void unionfs_double_lock_parents(struct dentry *p1,
++ struct dentry *p2)
++{
++ if (p1 == p2) {
++ unionfs_lock_dentry(p1, UNIONFS_DMUTEX_REVAL_PARENT);
++ return;
++ }
++ if (p1 < p2) {
++ unionfs_lock_dentry(p1, UNIONFS_DMUTEX_REVAL_PARENT);
++ unionfs_lock_dentry(p2, UNIONFS_DMUTEX_REVAL_CHILD);
++ } else {
++ unionfs_lock_dentry(p2, UNIONFS_DMUTEX_REVAL_PARENT);
++ unionfs_lock_dentry(p1, UNIONFS_DMUTEX_REVAL_CHILD);
++ }
++}
++
++static inline void unionfs_double_unlock_parents(struct dentry *p1,
++ struct dentry *p2)
++{
++ if (p1 == p2) {
++ unionfs_unlock_dentry(p1);
++ return;
++ }
++ if (p1 < p2) { /* unlock in reverse order of double_lock_parents */
++ unionfs_unlock_dentry(p1);
++ unionfs_unlock_dentry(p2);
++ } else {
++ unionfs_unlock_dentry(p2);
++ unionfs_unlock_dentry(p1);
++ }
++}
++
++extern int new_dentry_private_data(struct dentry *dentry, int subclass);
++extern int realloc_dentry_private_data(struct dentry *dentry);
++extern void free_dentry_private_data(struct dentry *dentry);
++extern void update_bstart(struct dentry *dentry);
++extern int init_lower_nd(struct nameidata *nd, unsigned int flags);
++extern void release_lower_nd(struct nameidata *nd, int err);
++
++/*
++ * EXTERNALS:
++ */
++
++/* replicates the directory structure up to given dentry in given branch */
++extern struct dentry *create_parents(struct inode *dir, struct dentry *dentry,
++ const char *name, int bindex);
++
++/* partial lookup */
++extern int unionfs_partial_lookup(struct dentry *dentry,
++ struct dentry *parent);
++extern struct dentry *unionfs_lookup_full(struct dentry *dentry,
++ struct dentry *parent,
++ int lookupmode);
++
++/* copies a file from dbstart to newbindex branch */
++extern int copyup_file(struct inode *dir, struct file *file, int bstart,
++ int newbindex, loff_t size);
++extern int copyup_named_file(struct inode *dir, struct file *file,
++ char *name, int bstart, int new_bindex,
++ loff_t len);
++/* copies a dentry from dbstart to newbindex branch */
++extern int copyup_dentry(struct inode *dir, struct dentry *dentry,
++ int bstart, int new_bindex, const char *name,
++ int namelen, struct file **copyup_file, loff_t len);
++/* helper functions for post-copyup actions */
++extern void unionfs_postcopyup_setmnt(struct dentry *dentry);
++extern void unionfs_postcopyup_release(struct dentry *dentry);
++
++/* Is this directory empty: 0 if it is empty, -ENOTEMPTY if not. */
++extern int check_empty(struct dentry *dentry, struct dentry *parent,
++ struct unionfs_dir_state **namelist);
++/* whiteout and opaque directory helpers */
++extern char *alloc_whname(const char *name, int len);
++extern bool is_whiteout_name(char **namep, int *namelenp);
++extern bool is_validname(const char *name);
++extern struct dentry *lookup_whiteout(const char *name,
++ struct dentry *lower_parent);
++extern struct dentry *find_first_whiteout(struct dentry *dentry);
++extern int unlink_whiteout(struct dentry *wh_dentry);
++extern int check_unlink_whiteout(struct dentry *dentry,
++ struct dentry *lower_dentry, int bindex);
++extern int create_whiteout(struct dentry *dentry, int start);
++extern int delete_whiteouts(struct dentry *dentry, int bindex,
++ struct unionfs_dir_state *namelist);
++extern int is_opaque_dir(struct dentry *dentry, int bindex);
++extern int make_dir_opaque(struct dentry *dir, int bindex);
++extern void unionfs_set_max_namelen(long *namelen);
++
++extern void unionfs_reinterpose(struct dentry *this_dentry);
++extern struct super_block *unionfs_duplicate_super(struct super_block *sb);
++
++/* Locking functions. */
++extern int unionfs_setlk(struct file *file, int cmd, struct file_lock *fl);
++extern int unionfs_getlk(struct file *file, struct file_lock *fl);
++
++/* Common file operations. */
++extern int unionfs_file_revalidate(struct file *file, struct dentry *parent,
++ bool willwrite);
++extern int unionfs_open(struct inode *inode, struct file *file);
++extern int unionfs_file_release(struct inode *inode, struct file *file);
++extern int unionfs_flush(struct file *file, fl_owner_t id);
++extern long unionfs_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg);
++extern int unionfs_fsync(struct file *file, int datasync);
++extern int unionfs_fasync(int fd, struct file *file, int flag);
++
++/* Inode operations */
++extern struct inode *unionfs_iget(struct super_block *sb, unsigned long ino);
++extern int unionfs_rename(struct inode *old_dir, struct dentry *old_dentry,
++ struct inode *new_dir, struct dentry *new_dentry);
++extern int unionfs_unlink(struct inode *dir, struct dentry *dentry);
++extern int unionfs_rmdir(struct inode *dir, struct dentry *dentry);
++
++extern bool __unionfs_d_revalidate(struct dentry *dentry,
++ struct dentry *parent, bool willwrite);
++extern bool is_negative_lower(const struct dentry *dentry);
++extern bool is_newer_lower(const struct dentry *dentry);
++extern void purge_sb_data(struct super_block *sb);
++
++/* The values for unionfs_interpose's flag. */
++#define INTERPOSE_DEFAULT 0
++#define INTERPOSE_LOOKUP 1
++#define INTERPOSE_REVAL 2
++#define INTERPOSE_REVAL_NEG 3
++#define INTERPOSE_PARTIAL 4
++
++extern struct dentry *unionfs_interpose(struct dentry *this_dentry,
++ struct super_block *sb, int flag);
++
++#ifdef CONFIG_UNION_FS_XATTR
++/* Extended attribute functions. */
++extern void *unionfs_xattr_alloc(size_t size, size_t limit);
++static inline void unionfs_xattr_kfree(const void *p)
++{
++ kfree(p);
++}
++extern ssize_t unionfs_getxattr(struct dentry *dentry, const char *name,
++ void *value, size_t size);
++extern int unionfs_removexattr(struct dentry *dentry, const char *name);
++extern ssize_t unionfs_listxattr(struct dentry *dentry, char *list,
++ size_t size);
++extern int unionfs_setxattr(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags);
++#endif /* CONFIG_UNION_FS_XATTR */
++
++/* The root directory is unhashed, but isn't deleted. */
++static inline int d_deleted(struct dentry *d)
++{
++ return d_unhashed(d) && (d != d->d_sb->s_root);
++}
++
++/* unionfs_permission, check if we should bypass error to facilitate copyup */
++#define IS_COPYUP_ERR(err) ((err) == -EROFS)
++
++/* unionfs_open, check if we need to copyup the file */
++#define OPEN_WRITE_FLAGS (O_WRONLY | O_RDWR | O_APPEND)
++#define IS_WRITE_FLAG(flag) ((flag) & OPEN_WRITE_FLAGS)
++
++static inline int branchperms(const struct super_block *sb, int index)
++{
++ BUG_ON(index < 0);
++ return UNIONFS_SB(sb)->data[index].branchperms;
++}
++
++static inline int set_branchperms(struct super_block *sb, int index, int perms)
++{
++ BUG_ON(index < 0);
++ UNIONFS_SB(sb)->data[index].branchperms = perms;
++ return perms;
++}
++
++/* check if readonly lower inode, but possibly unlinked (no inode->i_sb) */
++static inline int __is_rdonly(const struct inode *inode)
++{
++ /* if unlinked, can't be readonly (?) */
++ if (!inode->i_sb)
++ return 0;
++ return IS_RDONLY(inode);
++
++}
++/* Is this file on a read-only branch? */
++static inline int is_robranch_super(const struct super_block *sb, int index)
++{
++ int ret;
++
++ ret = (!(branchperms(sb, index) & MAY_WRITE)) ? -EROFS : 0;
++ return ret;
++}
++
++/* Is this file on a read-only branch? */
++static inline int is_robranch_idx(const struct dentry *dentry, int index)
++{
++ struct super_block *lower_sb;
++
++ BUG_ON(index < 0);
++
++ if (!(branchperms(dentry->d_sb, index) & MAY_WRITE))
++ return -EROFS;
++
++ lower_sb = unionfs_lower_super_idx(dentry->d_sb, index);
++ BUG_ON(lower_sb == NULL);
++ /*
++ * test sb flags directly, not IS_RDONLY(lower_inode) because the
++ * lower_dentry could be a negative.
++ */
++ if (lower_sb->s_flags & MS_RDONLY)
++ return -EROFS;
++
++ return 0;
++}
++
++static inline int is_robranch(const struct dentry *dentry)
++{
++ int index;
++
++ index = UNIONFS_D(dentry)->bstart;
++ BUG_ON(index < 0);
++
++ return is_robranch_idx(dentry, index);
++}
++
++/*
++ * EXTERNALS:
++ */
++extern int check_branch(struct nameidata *nd);
++extern int parse_branch_mode(const char *name, int *perms);
++
++/* locking helpers */
++static inline struct dentry *lock_parent(struct dentry *dentry)
++{
++ struct dentry *dir = dget_parent(dentry);
++ mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
++ return dir;
++}
++static inline struct dentry *lock_parent_wh(struct dentry *dentry)
++{
++ struct dentry *dir = dget_parent(dentry);
++
++ mutex_lock_nested(&dir->d_inode->i_mutex, UNIONFS_DMUTEX_WHITEOUT);
++ return dir;
++}
++
++static inline void unlock_dir(struct dentry *dir)
++{
++ mutex_unlock(&dir->d_inode->i_mutex);
++ dput(dir);
++}
++
++/* lock base inode mutex before calling lookup_one_len */
++static inline struct dentry *lookup_lck_len(const char *name,
++ struct dentry *base, int len)
++{
++ struct dentry *d;
++ mutex_lock(&base->d_inode->i_mutex);
++ d = lookup_one_len(name, base, len);
++ mutex_unlock(&base->d_inode->i_mutex);
++ return d;
++}
++
++static inline struct vfsmount *unionfs_mntget(struct dentry *dentry,
++ int bindex)
++{
++ struct vfsmount *mnt;
++
++ BUG_ON(!dentry || bindex < 0);
++
++ mnt = mntget(unionfs_lower_mnt_idx(dentry, bindex));
++#ifdef CONFIG_UNION_FS_DEBUG
++ if (!mnt)
++ pr_debug("unionfs: mntget: mnt=%p bindex=%d\n",
++ mnt, bindex);
++#endif /* CONFIG_UNION_FS_DEBUG */
++
++ return mnt;
++}
++
++static inline void unionfs_mntput(struct dentry *dentry, int bindex)
++{
++ struct vfsmount *mnt;
++
++ if (!dentry && bindex < 0)
++ return;
++ BUG_ON(!dentry || bindex < 0);
++
++ mnt = unionfs_lower_mnt_idx(dentry, bindex);
++#ifdef CONFIG_UNION_FS_DEBUG
++ /*
++ * Directories can have NULL lower objects in between start/end, but
++ * NOT if at the start/end range. We cannot verify that this dentry
++ * is a type=DIR, because it may already be a negative dentry. But
++ * if dbstart is greater than dbend, we know that this couldn't have
++ * been a regular file: it had to have been a directory.
++ */
++ if (!mnt && !(bindex > dbstart(dentry) && bindex < dbend(dentry)))
++ pr_debug("unionfs: mntput: mnt=%p bindex=%d\n", mnt, bindex);
++#endif /* CONFIG_UNION_FS_DEBUG */
++ mntput(mnt);
++}
++
++#ifdef CONFIG_UNION_FS_DEBUG
++
++/* useful for tracking code reachability */
++#define UDBG pr_debug("DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__)
++
++#define unionfs_check_inode(i) __unionfs_check_inode((i), \
++ __FILE__, __func__, __LINE__)
++#define unionfs_check_dentry(d) __unionfs_check_dentry((d), \
++ __FILE__, __func__, __LINE__)
++#define unionfs_check_file(f) __unionfs_check_file((f), \
++ __FILE__, __func__, __LINE__)
++#define unionfs_check_nd(n) __unionfs_check_nd((n), \
++ __FILE__, __func__, __LINE__)
++#define show_branch_counts(sb) __show_branch_counts((sb), \
++ __FILE__, __func__, __LINE__)
++#define show_inode_times(i) __show_inode_times((i), \
++ __FILE__, __func__, __LINE__)
++#define show_dinode_times(d) __show_dinode_times((d), \
++ __FILE__, __func__, __LINE__)
++#define show_inode_counts(i) __show_inode_counts((i), \
++ __FILE__, __func__, __LINE__)
++
++extern void __unionfs_check_inode(const struct inode *inode, const char *fname,
++ const char *fxn, int line);
++extern void __unionfs_check_dentry(const struct dentry *dentry,
++ const char *fname, const char *fxn,
++ int line);
++extern void __unionfs_check_file(const struct file *file,
++ const char *fname, const char *fxn, int line);
++extern void __unionfs_check_nd(const struct nameidata *nd,
++ const char *fname, const char *fxn, int line);
++extern void __show_branch_counts(const struct super_block *sb,
++ const char *file, const char *fxn, int line);
++extern void __show_inode_times(const struct inode *inode,
++ const char *file, const char *fxn, int line);
++extern void __show_dinode_times(const struct dentry *dentry,
++ const char *file, const char *fxn, int line);
++extern void __show_inode_counts(const struct inode *inode,
++ const char *file, const char *fxn, int line);
++
++#else /* not CONFIG_UNION_FS_DEBUG */
++
++/* we leave useful hooks for these check functions throughout the code */
++#define unionfs_check_inode(i) do { } while (0)
++#define unionfs_check_dentry(d) do { } while (0)
++#define unionfs_check_file(f) do { } while (0)
++#define unionfs_check_nd(n) do { } while (0)
++#define show_branch_counts(sb) do { } while (0)
++#define show_inode_times(i) do { } while (0)
++#define show_dinode_times(d) do { } while (0)
++#define show_inode_counts(i) do { } while (0)
++
++#endif /* not CONFIG_UNION_FS_DEBUG */
++
++#endif /* not _UNION_H_ */
+diff --git a/fs/unionfs/unlink.c b/fs/unionfs/unlink.c
+new file mode 100644
+index 0000000..542c513
+--- /dev/null
++++ b/fs/unionfs/unlink.c
+@@ -0,0 +1,278 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++/*
++ * Helper function for Unionfs's unlink operation.
++ *
++ * The main goal of this function is to optimize the unlinking of non-dir
++ * objects in unionfs by deleting all possible lower inode objects from the
++ * underlying branches having same dentry name as the non-dir dentry on
++ * which this unlink operation is called. This way we delete as many lower
++ * inodes as possible, and save space. Whiteouts need to be created in
++ * branch0 only if unlinking fails on any of the lower branch other than
++ * branch0, or if a lower branch is marked read-only.
++ *
++ * Also, while unlinking a file, if we encounter any dir type entry in any
++ * intermediate branch, then we remove the directory by calling vfs_rmdir.
++ * The following special cases are also handled:
++
++ * (1) If an error occurs in branch0 during vfs_unlink, then we return
++ * appropriate error.
++ *
++ * (2) If we get an error during unlink in any of other lower branch other
++ * than branch0, then we create a whiteout in branch0.
++ *
++ * (3) If a whiteout already exists in any intermediate branch, we delete
++ * all possible inodes only up to that branch (this is an "opaqueness"
++ * as as per Documentation/filesystems/unionfs/concepts.txt).
++ *
++ */
++static int unionfs_unlink_whiteout(struct inode *dir, struct dentry *dentry,
++ struct dentry *parent)
++{
++ struct dentry *lower_dentry;
++ struct dentry *lower_dir_dentry;
++ int bindex;
++ int err = 0;
++
++ err = unionfs_partial_lookup(dentry, parent);
++ if (err)
++ goto out;
++
++ /* trying to unlink all possible valid instances */
++ for (bindex = dbstart(dentry); bindex <= dbend(dentry); bindex++) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ if (!lower_dentry || !lower_dentry->d_inode)
++ continue;
++
++ lower_dir_dentry = lock_parent(lower_dentry);
++
++ /* avoid destroying the lower inode if the object is in use */
++ dget(lower_dentry);
++ err = is_robranch_super(dentry->d_sb, bindex);
++ if (!err) {
++ /* see Documentation/filesystems/unionfs/issues.txt */
++ lockdep_off();
++ if (!S_ISDIR(lower_dentry->d_inode->i_mode))
++ err = vfs_unlink(lower_dir_dentry->d_inode,
++ lower_dentry);
++ else
++ err = vfs_rmdir(lower_dir_dentry->d_inode,
++ lower_dentry);
++ lockdep_on();
++ }
++
++ /* if lower object deletion succeeds, update inode's times */
++ if (!err)
++ unionfs_copy_attr_times(dentry->d_inode);
++ dput(lower_dentry);
++ fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
++ unlock_dir(lower_dir_dentry);
++
++ if (err)
++ break;
++ }
++
++ /*
++ * Create the whiteout in branch 0 (highest priority) only if (a)
++ * there was an error in any intermediate branch other than branch 0
++ * due to failure of vfs_unlink/vfs_rmdir or (b) a branch marked or
++ * mounted read-only.
++ */
++ if (err) {
++ if ((bindex == 0) ||
++ ((bindex == dbstart(dentry)) &&
++ (!IS_COPYUP_ERR(err))))
++ goto out;
++ else {
++ if (!IS_COPYUP_ERR(err))
++ pr_debug("unionfs: lower object deletion "
++ "failed in branch:%d\n", bindex);
++ err = create_whiteout(dentry, sbstart(dentry->d_sb));
++ }
++ }
++
++out:
++ if (!err)
++ inode_dec_link_count(dentry->d_inode);
++
++ /* We don't want to leave negative leftover dentries for revalidate. */
++ if (!err && (dbopaque(dentry) != -1))
++ update_bstart(dentry);
++
++ return err;
++}
++
++int unionfs_unlink(struct inode *dir, struct dentry *dentry)
++{
++ int err = 0;
++ struct inode *inode = dentry->d_inode;
++ struct dentry *parent;
++ int valid;
++
++ BUG_ON(S_ISDIR(inode->i_mode));
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++ unionfs_check_dentry(dentry);
++
++ err = unionfs_unlink_whiteout(dir, dentry, parent);
++ /* call d_drop so the system "forgets" about us */
++ if (!err) {
++ unionfs_postcopyup_release(dentry);
++ unionfs_postcopyup_setmnt(parent);
++ if (inode->i_nlink == 0) /* drop lower inodes */
++ iput_lowers_all(inode, false);
++ d_drop(dentry);
++ /*
++ * if unlink/whiteout succeeded, parent dir mtime has
++ * changed
++ */
++ unionfs_copy_attr_times(dir);
++ }
++
++out:
++ if (!err) {
++ unionfs_check_dentry(dentry);
++ unionfs_check_inode(dir);
++ }
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++static int unionfs_rmdir_first(struct inode *dir, struct dentry *dentry,
++ struct unionfs_dir_state *namelist)
++{
++ int err;
++ struct dentry *lower_dentry;
++ struct dentry *lower_dir_dentry = NULL;
++
++ /* Here we need to remove whiteout entries. */
++ err = delete_whiteouts(dentry, dbstart(dentry), namelist);
++ if (err)
++ goto out;
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++
++ lower_dir_dentry = lock_parent(lower_dentry);
++
++ /* avoid destroying the lower inode if the file is in use */
++ dget(lower_dentry);
++ err = is_robranch(dentry);
++ if (!err)
++ err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
++ dput(lower_dentry);
++
++ fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
++ /* propagate number of hard-links */
++ dentry->d_inode->i_nlink = unionfs_get_nlinks(dentry->d_inode);
++
++out:
++ if (lower_dir_dentry)
++ unlock_dir(lower_dir_dentry);
++ return err;
++}
++
++int unionfs_rmdir(struct inode *dir, struct dentry *dentry)
++{
++ int err = 0;
++ struct unionfs_dir_state *namelist = NULL;
++ struct dentry *parent;
++ int dstart, dend;
++ bool valid;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++ unionfs_check_dentry(dentry);
++
++ /* check if this unionfs directory is empty or not */
++ err = check_empty(dentry, parent, &namelist);
++ if (err)
++ goto out;
++
++ err = unionfs_rmdir_first(dir, dentry, namelist);
++ dstart = dbstart(dentry);
++ dend = dbend(dentry);
++ /*
++ * We create a whiteout for the directory if there was an error to
++ * rmdir the first directory entry in the union. Otherwise, we
++ * create a whiteout only if there is no chance that a lower
++ * priority branch might also have the same named directory. IOW,
++ * if there is not another same-named directory at a lower priority
++ * branch, then we don't need to create a whiteout for it.
++ */
++ if (!err) {
++ if (dstart < dend)
++ err = create_whiteout(dentry, dstart);
++ } else {
++ int new_err;
++
++ if (dstart == 0)
++ goto out;
++
++ /* exit if the error returned was NOT -EROFS */
++ if (!IS_COPYUP_ERR(err))
++ goto out;
++
++ new_err = create_whiteout(dentry, dstart - 1);
++ if (new_err != -EEXIST)
++ err = new_err;
++ }
++
++out:
++ /*
++ * Drop references to lower dentry/inode so storage space for them
++ * can be reclaimed. Then, call d_drop so the system "forgets"
++ * about us.
++ */
++ if (!err) {
++ iput_lowers_all(dentry->d_inode, false);
++ dput(unionfs_lower_dentry_idx(dentry, dstart));
++ unionfs_set_lower_dentry_idx(dentry, dstart, NULL);
++ d_drop(dentry);
++ /* update our lower vfsmnts, in case a copyup took place */
++ unionfs_postcopyup_setmnt(dentry);
++ unionfs_check_dentry(dentry);
++ unionfs_check_inode(dir);
++ }
++
++ if (namelist)
++ free_rdstate(namelist);
++
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
+diff --git a/fs/unionfs/whiteout.c b/fs/unionfs/whiteout.c
+new file mode 100644
+index 0000000..405073a
+--- /dev/null
++++ b/fs/unionfs/whiteout.c
+@@ -0,0 +1,584 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++/*
++ * whiteout and opaque directory helpers
++ */
++
++/* What do we use for whiteouts. */
++#define UNIONFS_WHPFX ".wh."
++#define UNIONFS_WHLEN 4
++/*
++ * If a directory contains this file, then it is opaque. We start with the
++ * .wh. flag so that it is blocked by lookup.
++ */
++#define UNIONFS_DIR_OPAQUE_NAME "__dir_opaque"
++#define UNIONFS_DIR_OPAQUE UNIONFS_WHPFX UNIONFS_DIR_OPAQUE_NAME
++
++/* construct whiteout filename */
++char *alloc_whname(const char *name, int len)
++{
++ char *buf;
++
++ buf = kmalloc(len + UNIONFS_WHLEN + 1, GFP_KERNEL);
++ if (unlikely(!buf))
++ return ERR_PTR(-ENOMEM);
++
++ strcpy(buf, UNIONFS_WHPFX);
++ strlcat(buf, name, len + UNIONFS_WHLEN + 1);
++
++ return buf;
++}
++
++/*
++ * XXX: this can be inline or CPP macro, but is here to keep all whiteout
++ * code in one place.
++ */
++void unionfs_set_max_namelen(long *namelen)
++{
++ *namelen -= UNIONFS_WHLEN;
++}
++
++/* check if @namep is a whiteout, update @namep and @namelenp accordingly */
++bool is_whiteout_name(char **namep, int *namelenp)
++{
++ if (*namelenp > UNIONFS_WHLEN &&
++ !strncmp(*namep, UNIONFS_WHPFX, UNIONFS_WHLEN)) {
++ *namep += UNIONFS_WHLEN;
++ *namelenp -= UNIONFS_WHLEN;
++ return true;
++ }
++ return false;
++}
++
++/* is the filename valid == !(whiteout for a file or opaque dir marker) */
++bool is_validname(const char *name)
++{
++ if (!strncmp(name, UNIONFS_WHPFX, UNIONFS_WHLEN))
++ return false;
++ if (!strncmp(name, UNIONFS_DIR_OPAQUE_NAME,
++ sizeof(UNIONFS_DIR_OPAQUE_NAME) - 1))
++ return false;
++ return true;
++}
++
++/*
++ * Look for a whiteout @name in @lower_parent directory. If error, return
++ * ERR_PTR. Caller must dput() the returned dentry if not an error.
++ *
++ * XXX: some callers can reuse the whname allocated buffer to avoid repeated
++ * free then re-malloc calls. Need to provide a different API for those
++ * callers.
++ */
++struct dentry *lookup_whiteout(const char *name, struct dentry *lower_parent)
++{
++ char *whname = NULL;
++ int err = 0, namelen;
++ struct dentry *wh_dentry = NULL;
++
++ namelen = strlen(name);
++ whname = alloc_whname(name, namelen);
++ if (unlikely(IS_ERR(whname))) {
++ err = PTR_ERR(whname);
++ goto out;
++ }
++
++ /* check if whiteout exists in this branch: lookup .wh.foo */
++ wh_dentry = lookup_lck_len(whname, lower_parent, strlen(whname));
++ if (IS_ERR(wh_dentry)) {
++ err = PTR_ERR(wh_dentry);
++ goto out;
++ }
++
++ /* check if negative dentry (ENOENT) */
++ if (!wh_dentry->d_inode)
++ goto out;
++
++ /* whiteout found: check if valid type */
++ if (!S_ISREG(wh_dentry->d_inode->i_mode)) {
++ printk(KERN_ERR "unionfs: invalid whiteout %s entry type %d\n",
++ whname, wh_dentry->d_inode->i_mode);
++ dput(wh_dentry);
++ err = -EIO;
++ goto out;
++ }
++
++out:
++ kfree(whname);
++ if (err)
++ wh_dentry = ERR_PTR(err);
++ return wh_dentry;
++}
++
++/* find and return first whiteout in parent directory, else ENOENT */
++struct dentry *find_first_whiteout(struct dentry *dentry)
++{
++ int bindex, bstart, bend;
++ struct dentry *parent, *lower_parent, *wh_dentry;
++
++ parent = dget_parent(dentry);
++
++ bstart = dbstart(parent);
++ bend = dbend(parent);
++ wh_dentry = ERR_PTR(-ENOENT);
++
++ for (bindex = bstart; bindex <= bend; bindex++) {
++ lower_parent = unionfs_lower_dentry_idx(parent, bindex);
++ if (!lower_parent)
++ continue;
++ wh_dentry = lookup_whiteout(dentry->d_name.name, lower_parent);
++ if (IS_ERR(wh_dentry))
++ continue;
++ if (wh_dentry->d_inode)
++ break;
++ dput(wh_dentry);
++ wh_dentry = ERR_PTR(-ENOENT);
++ }
++
++ dput(parent);
++
++ return wh_dentry;
++}
++
++/*
++ * Unlink a whiteout dentry. Returns 0 or -errno. Caller must hold and
++ * release dentry reference.
++ */
++int unlink_whiteout(struct dentry *wh_dentry)
++{
++ int err;
++ struct dentry *lower_dir_dentry;
++
++ /* dget and lock parent dentry */
++ lower_dir_dentry = lock_parent_wh(wh_dentry);
++
++ /* see Documentation/filesystems/unionfs/issues.txt */
++ lockdep_off();
++ err = vfs_unlink(lower_dir_dentry->d_inode, wh_dentry);
++ lockdep_on();
++ unlock_dir(lower_dir_dentry);
++
++ /*
++ * Whiteouts are special files and should be deleted no matter what
++ * (as if they never existed), in order to allow this create
++ * operation to succeed. This is especially important in sticky
++ * directories: a whiteout may have been created by one user, but
++ * the newly created file may be created by another user.
++ * Therefore, in order to maintain Unix semantics, if the vfs_unlink
++ * above failed, then we have to try to directly unlink the
++ * whiteout. Note: in the ODF version of unionfs, whiteout are
++ * handled much more cleanly.
++ */
++ if (err == -EPERM) {
++ struct inode *inode = lower_dir_dentry->d_inode;
++ err = inode->i_op->unlink(inode, wh_dentry);
++ }
++ if (err)
++ printk(KERN_ERR "unionfs: could not unlink whiteout %s, "
++ "err = %d\n", wh_dentry->d_name.name, err);
++
++ return err;
++
++}
++
++/*
++ * Helper function when creating new objects (create, symlink, mknod, etc.).
++ * Checks to see if there's a whiteout in @lower_dentry's parent directory,
++ * whose name is taken from @dentry. Then tries to remove that whiteout, if
++ * found. If <dentry,bindex> is a branch marked readonly, return -EROFS.
++ * If it finds both a regular file and a whiteout, return -EIO (this should
++ * never happen).
++ *
++ * Return 0 if no whiteout was found. Return 1 if one was found and
++ * successfully removed. Therefore a value >= 0 tells the caller that
++ * @lower_dentry belongs to a good branch to create the new object in).
++ * Return -ERRNO if an error occurred during whiteout lookup or in trying to
++ * unlink the whiteout.
++ */
++int check_unlink_whiteout(struct dentry *dentry, struct dentry *lower_dentry,
++ int bindex)
++{
++ int err;
++ struct dentry *wh_dentry = NULL;
++ struct dentry *lower_dir_dentry = NULL;
++
++ /* look for whiteout dentry first */
++ lower_dir_dentry = dget_parent(lower_dentry);
++ wh_dentry = lookup_whiteout(dentry->d_name.name, lower_dir_dentry);
++ dput(lower_dir_dentry);
++ if (IS_ERR(wh_dentry)) {
++ err = PTR_ERR(wh_dentry);
++ goto out;
++ }
++
++ if (!wh_dentry->d_inode) { /* no whiteout exists*/
++ err = 0;
++ goto out_dput;
++ }
++
++ /* check if regular file and whiteout were both found */
++ if (unlikely(lower_dentry->d_inode)) {
++ err = -EIO;
++ printk(KERN_ERR "unionfs: found both whiteout and regular "
++ "file in directory %s (branch %d)\n",
++ lower_dir_dentry->d_name.name, bindex);
++ goto out_dput;
++ }
++
++ /* check if branch is writeable */
++ err = is_robranch_super(dentry->d_sb, bindex);
++ if (err)
++ goto out_dput;
++
++ /* .wh.foo has been found, so let's unlink it */
++ err = unlink_whiteout(wh_dentry);
++ if (!err)
++ err = 1; /* a whiteout was found and successfully removed */
++out_dput:
++ dput(wh_dentry);
++out:
++ return err;
++}
++
++/*
++ * Pass an unionfs dentry and an index. It will try to create a whiteout
++ * for the filename in dentry, and will try in branch 'index'. On error,
++ * it will proceed to a branch to the left.
++ */
++int create_whiteout(struct dentry *dentry, int start)
++{
++ int bstart, bend, bindex;
++ struct dentry *lower_dir_dentry;
++ struct dentry *lower_dentry;
++ struct dentry *lower_wh_dentry;
++ struct nameidata nd;
++ char *name = NULL;
++ int err = -EINVAL;
++
++ verify_locked(dentry);
++
++ bstart = dbstart(dentry);
++ bend = dbend(dentry);
++
++ /* create dentry's whiteout equivalent */
++ name = alloc_whname(dentry->d_name.name, dentry->d_name.len);
++ if (unlikely(IS_ERR(name))) {
++ err = PTR_ERR(name);
++ goto out;
++ }
++
++ for (bindex = start; bindex >= 0; bindex--) {
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++
++ if (!lower_dentry) {
++ /*
++ * if lower dentry is not present, create the
++ * entire lower dentry directory structure and go
++ * ahead. Since we want to just create whiteout, we
++ * only want the parent dentry, and hence get rid of
++ * this dentry.
++ */
++ lower_dentry = create_parents(dentry->d_inode,
++ dentry,
++ dentry->d_name.name,
++ bindex);
++ if (!lower_dentry || IS_ERR(lower_dentry)) {
++ int ret = PTR_ERR(lower_dentry);
++ if (!IS_COPYUP_ERR(ret))
++ printk(KERN_ERR
++ "unionfs: create_parents for "
++ "whiteout failed: bindex=%d "
++ "err=%d\n", bindex, ret);
++ continue;
++ }
++ }
++
++ lower_wh_dentry =
++ lookup_lck_len(name, lower_dentry->d_parent,
++ dentry->d_name.len + UNIONFS_WHLEN);
++ if (IS_ERR(lower_wh_dentry))
++ continue;
++
++ /*
++ * The whiteout already exists. This used to be impossible,
++ * but now is possible because of opaqueness.
++ */
++ if (lower_wh_dentry->d_inode) {
++ dput(lower_wh_dentry);
++ err = 0;
++ goto out;
++ }
++
++ err = init_lower_nd(&nd, LOOKUP_CREATE);
++ if (unlikely(err < 0))
++ goto out;
++ lower_dir_dentry = lock_parent_wh(lower_wh_dentry);
++ err = is_robranch_super(dentry->d_sb, bindex);
++ if (!err)
++ err = vfs_create(lower_dir_dentry->d_inode,
++ lower_wh_dentry,
++ current_umask() & S_IRUGO,
++ &nd);
++ unlock_dir(lower_dir_dentry);
++ dput(lower_wh_dentry);
++ release_lower_nd(&nd, err);
++
++ if (!err || !IS_COPYUP_ERR(err))
++ break;
++ }
++
++ /* set dbopaque so that lookup will not proceed after this branch */
++ if (!err)
++ dbopaque(dentry) = bindex;
++
++out:
++ kfree(name);
++ return err;
++}
++
++/*
++ * Delete all of the whiteouts in a given directory for rmdir.
++ *
++ * lower directory inode should be locked
++ */
++static int do_delete_whiteouts(struct dentry *dentry, int bindex,
++ struct unionfs_dir_state *namelist)
++{
++ int err = 0;
++ struct dentry *lower_dir_dentry = NULL;
++ struct dentry *lower_dentry;
++ char *name = NULL, *p;
++ struct inode *lower_dir;
++ int i;
++ struct list_head *pos;
++ struct filldir_node *cursor;
++
++ /* Find out lower parent dentry */
++ lower_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ BUG_ON(!S_ISDIR(lower_dir_dentry->d_inode->i_mode));
++ lower_dir = lower_dir_dentry->d_inode;
++ BUG_ON(!S_ISDIR(lower_dir->i_mode));
++
++ err = -ENOMEM;
++ name = __getname();
++ if (unlikely(!name))
++ goto out;
++ strcpy(name, UNIONFS_WHPFX);
++ p = name + UNIONFS_WHLEN;
++
++ err = 0;
++ for (i = 0; !err && i < namelist->size; i++) {
++ list_for_each(pos, &namelist->list[i]) {
++ cursor =
++ list_entry(pos, struct filldir_node,
++ file_list);
++ /* Only operate on whiteouts in this branch. */
++ if (cursor->bindex != bindex)
++ continue;
++ if (!cursor->whiteout)
++ continue;
++
++ strlcpy(p, cursor->name, PATH_MAX - UNIONFS_WHLEN);
++ lower_dentry =
++ lookup_lck_len(name, lower_dir_dentry,
++ cursor->namelen +
++ UNIONFS_WHLEN);
++ if (IS_ERR(lower_dentry)) {
++ err = PTR_ERR(lower_dentry);
++ break;
++ }
++ if (lower_dentry->d_inode)
++ err = vfs_unlink(lower_dir, lower_dentry);
++ dput(lower_dentry);
++ if (err)
++ break;
++ }
++ }
++
++ __putname(name);
++
++ /* After all of the removals, we should copy the attributes once. */
++ fsstack_copy_attr_times(dentry->d_inode, lower_dir_dentry->d_inode);
++
++out:
++ return err;
++}
++
++
++void __delete_whiteouts(struct work_struct *work)
++{
++ struct sioq_args *args = container_of(work, struct sioq_args, work);
++ struct deletewh_args *d = &args->deletewh;
++
++ args->err = do_delete_whiteouts(d->dentry, d->bindex, d->namelist);
++ complete(&args->comp);
++}
++
++/* delete whiteouts in a dir (for rmdir operation) using sioq if necessary */
++int delete_whiteouts(struct dentry *dentry, int bindex,
++ struct unionfs_dir_state *namelist)
++{
++ int err;
++ struct super_block *sb;
++ struct dentry *lower_dir_dentry;
++ struct inode *lower_dir;
++ struct sioq_args args;
++
++ sb = dentry->d_sb;
++
++ BUG_ON(!S_ISDIR(dentry->d_inode->i_mode));
++ BUG_ON(bindex < dbstart(dentry));
++ BUG_ON(bindex > dbend(dentry));
++ err = is_robranch_super(sb, bindex);
++ if (err)
++ goto out;
++
++ lower_dir_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ BUG_ON(!S_ISDIR(lower_dir_dentry->d_inode->i_mode));
++ lower_dir = lower_dir_dentry->d_inode;
++ BUG_ON(!S_ISDIR(lower_dir->i_mode));
++
++ if (!inode_permission(lower_dir, MAY_WRITE | MAY_EXEC)) {
++ err = do_delete_whiteouts(dentry, bindex, namelist);
++ } else {
++ args.deletewh.namelist = namelist;
++ args.deletewh.dentry = dentry;
++ args.deletewh.bindex = bindex;
++ run_sioq(__delete_whiteouts, &args);
++ err = args.err;
++ }
++
++out:
++ return err;
++}
++
++/****************************************************************************
++ * Opaque directory helpers *
++ ****************************************************************************/
++
++/*
++ * is_opaque_dir: returns 0 if it is NOT an opaque dir, 1 if it is, and
++ * -errno if an error occurred trying to figure this out.
++ */
++int is_opaque_dir(struct dentry *dentry, int bindex)
++{
++ int err = 0;
++ struct dentry *lower_dentry;
++ struct dentry *wh_lower_dentry;
++ struct inode *lower_inode;
++ struct sioq_args args;
++
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ lower_inode = lower_dentry->d_inode;
++
++ BUG_ON(!S_ISDIR(lower_inode->i_mode));
++
++ mutex_lock(&lower_inode->i_mutex);
++
++ if (!inode_permission(lower_inode, MAY_EXEC)) {
++ wh_lower_dentry =
++ lookup_one_len(UNIONFS_DIR_OPAQUE, lower_dentry,
++ sizeof(UNIONFS_DIR_OPAQUE) - 1);
++ } else {
++ args.is_opaque.dentry = lower_dentry;
++ run_sioq(__is_opaque_dir, &args);
++ wh_lower_dentry = args.ret;
++ }
++
++ mutex_unlock(&lower_inode->i_mutex);
++
++ if (IS_ERR(wh_lower_dentry)) {
++ err = PTR_ERR(wh_lower_dentry);
++ goto out;
++ }
++
++ /* This is an opaque dir iff wh_lower_dentry is positive */
++ err = !!wh_lower_dentry->d_inode;
++
++ dput(wh_lower_dentry);
++out:
++ return err;
++}
++
++void __is_opaque_dir(struct work_struct *work)
++{
++ struct sioq_args *args = container_of(work, struct sioq_args, work);
++
++ args->ret = lookup_one_len(UNIONFS_DIR_OPAQUE, args->is_opaque.dentry,
++ sizeof(UNIONFS_DIR_OPAQUE) - 1);
++ complete(&args->comp);
++}
++
++int make_dir_opaque(struct dentry *dentry, int bindex)
++{
++ int err = 0;
++ struct dentry *lower_dentry, *diropq;
++ struct inode *lower_dir;
++ struct nameidata nd;
++ const struct cred *old_creds;
++ struct cred *new_creds;
++
++ /*
++ * Opaque directory whiteout markers are special files (like regular
++ * whiteouts), and should appear to the users as if they don't
++ * exist. They should be created/deleted regardless of directory
++ * search/create permissions, but only for the duration of this
++ * creation of the .wh.__dir_opaque: file. Note, this does not
++ * circumvent normal ->permission).
++ */
++ new_creds = prepare_creds();
++ if (unlikely(!new_creds)) {
++ err = -ENOMEM;
++ goto out_err;
++ }
++ cap_raise(new_creds->cap_effective, CAP_DAC_READ_SEARCH);
++ cap_raise(new_creds->cap_effective, CAP_DAC_OVERRIDE);
++ old_creds = override_creds(new_creds);
++
++ lower_dentry = unionfs_lower_dentry_idx(dentry, bindex);
++ lower_dir = lower_dentry->d_inode;
++ BUG_ON(!S_ISDIR(dentry->d_inode->i_mode) ||
++ !S_ISDIR(lower_dir->i_mode));
++
++ mutex_lock(&lower_dir->i_mutex);
++ diropq = lookup_one_len(UNIONFS_DIR_OPAQUE, lower_dentry,
++ sizeof(UNIONFS_DIR_OPAQUE) - 1);
++ if (IS_ERR(diropq)) {
++ err = PTR_ERR(diropq);
++ goto out;
++ }
++
++ err = init_lower_nd(&nd, LOOKUP_CREATE);
++ if (unlikely(err < 0))
++ goto out;
++ if (!diropq->d_inode)
++ err = vfs_create(lower_dir, diropq, S_IRUGO, &nd);
++ if (!err)
++ dbopaque(dentry) = bindex;
++ release_lower_nd(&nd, err);
++
++ dput(diropq);
++
++out:
++ mutex_unlock(&lower_dir->i_mutex);
++ revert_creds(old_creds);
++out_err:
++ return err;
++}
+diff --git a/fs/unionfs/xattr.c b/fs/unionfs/xattr.c
+new file mode 100644
+index 0000000..9002e06
+--- /dev/null
++++ b/fs/unionfs/xattr.c
+@@ -0,0 +1,173 @@
++/*
++ * Copyright (c) 2003-2010 Erez Zadok
++ * Copyright (c) 2003-2006 Charles P. Wright
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2005-2006 Junjiro Okajima
++ * Copyright (c) 2005 Arun M. Krishnakumar
++ * Copyright (c) 2004-2006 David P. Quigley
++ * Copyright (c) 2003-2004 Mohammad Nayyer Zubair
++ * Copyright (c) 2003 Puja Gupta
++ * Copyright (c) 2003 Harikesavan Krishnan
++ * Copyright (c) 2003-2010 Stony Brook University
++ * Copyright (c) 2003-2010 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#include "union.h"
++
++/* This is lifted from fs/xattr.c */
++void *unionfs_xattr_alloc(size_t size, size_t limit)
++{
++ void *ptr;
++
++ if (size > limit)
++ return ERR_PTR(-E2BIG);
++
++ if (!size) /* size request, no buffer is needed */
++ return NULL;
++
++ ptr = kmalloc(size, GFP_KERNEL);
++ if (unlikely(!ptr))
++ return ERR_PTR(-ENOMEM);
++ return ptr;
++}
++
++/*
++ * BKL held by caller.
++ * dentry->d_inode->i_mutex locked
++ */
++ssize_t unionfs_getxattr(struct dentry *dentry, const char *name, void *value,
++ size_t size)
++{
++ struct dentry *lower_dentry = NULL;
++ struct dentry *parent;
++ int err = -EOPNOTSUPP;
++ bool valid;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++
++ err = vfs_getxattr(lower_dentry, (char *) name, value, size);
++
++out:
++ unionfs_check_dentry(dentry);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++/*
++ * BKL held by caller.
++ * dentry->d_inode->i_mutex locked
++ */
++int unionfs_setxattr(struct dentry *dentry, const char *name,
++ const void *value, size_t size, int flags)
++{
++ struct dentry *lower_dentry = NULL;
++ struct dentry *parent;
++ int err = -EOPNOTSUPP;
++ bool valid;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++
++ err = vfs_setxattr(lower_dentry, (char *) name, (void *) value,
++ size, flags);
++
++out:
++ unionfs_check_dentry(dentry);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++/*
++ * BKL held by caller.
++ * dentry->d_inode->i_mutex locked
++ */
++int unionfs_removexattr(struct dentry *dentry, const char *name)
++{
++ struct dentry *lower_dentry = NULL;
++ struct dentry *parent;
++ int err = -EOPNOTSUPP;
++ bool valid;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++
++ err = vfs_removexattr(lower_dentry, (char *) name);
++
++out:
++ unionfs_check_dentry(dentry);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
++
++/*
++ * BKL held by caller.
++ * dentry->d_inode->i_mutex locked
++ */
++ssize_t unionfs_listxattr(struct dentry *dentry, char *list, size_t size)
++{
++ struct dentry *lower_dentry = NULL;
++ struct dentry *parent;
++ int err = -EOPNOTSUPP;
++ char *encoded_list = NULL;
++ bool valid;
++
++ unionfs_read_lock(dentry->d_sb, UNIONFS_SMUTEX_CHILD);
++ parent = unionfs_lock_parent(dentry, UNIONFS_DMUTEX_PARENT);
++ unionfs_lock_dentry(dentry, UNIONFS_DMUTEX_CHILD);
++
++ valid = __unionfs_d_revalidate(dentry, parent, false);
++ if (unlikely(!valid)) {
++ err = -ESTALE;
++ goto out;
++ }
++
++ lower_dentry = unionfs_lower_dentry(dentry);
++
++ encoded_list = list;
++ err = vfs_listxattr(lower_dentry, encoded_list, size);
++
++out:
++ unionfs_check_dentry(dentry);
++ unionfs_unlock_dentry(dentry);
++ unionfs_unlock_parent(dentry, parent);
++ unionfs_read_unlock(dentry->d_sb);
++ return err;
++}
+diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
+index da317c7..64f1ced 100644
+--- a/include/linux/fs_stack.h
++++ b/include/linux/fs_stack.h
+@@ -1,7 +1,19 @@
++/*
++ * Copyright (c) 2006-2009 Erez Zadok
++ * Copyright (c) 2006-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2006-2009 Stony Brook University
++ * Copyright (c) 2006-2009 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
+ #ifndef _LINUX_FS_STACK_H
+ #define _LINUX_FS_STACK_H
+
+-/* This file defines generic functions used primarily by stackable
++/*
++ * This file defines generic functions used primarily by stackable
+ * filesystems; none of these functions require i_mutex to be held.
+ */
+
+diff --git a/include/linux/magic.h b/include/linux/magic.h
+index eb9800f..9770154 100644
+--- a/include/linux/magic.h
++++ b/include/linux/magic.h
+@@ -47,6 +47,8 @@
+ #define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
+ #define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs"
+
++#define UNIONFS_SUPER_MAGIC 0xf15f083d
++
+ #define SMB_SUPER_MAGIC 0x517B
+ #define USBDEVICE_SUPER_MAGIC 0x9fa2
+ #define CGROUP_SUPER_MAGIC 0x27e0eb
+diff --git a/include/linux/namei.h b/include/linux/namei.h
+index 05b441d..dca6f9a 100644
+--- a/include/linux/namei.h
++++ b/include/linux/namei.h
+@@ -72,6 +72,7 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
+
+ extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
+ int (*open)(struct inode *, struct file *));
++extern void release_open_intent(struct nameidata *);
+
+ extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
+
+diff --git a/include/linux/splice.h b/include/linux/splice.h
+index 997c3b4..54f5501 100644
+--- a/include/linux/splice.h
++++ b/include/linux/splice.h
+@@ -81,6 +81,11 @@ extern ssize_t splice_to_pipe(struct pipe_inode_info *,
+ struct splice_pipe_desc *);
+ extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
+ splice_direct_actor *);
++extern long vfs_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags);
++extern long vfs_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags);
+
+ /*
+ * for dynamic pipe sizing
+diff --git a/include/linux/union_fs.h b/include/linux/union_fs.h
+new file mode 100644
+index 0000000..c84d97e
+--- /dev/null
++++ b/include/linux/union_fs.h
+@@ -0,0 +1,22 @@
++/*
++ * Copyright (c) 2003-2009 Erez Zadok
++ * Copyright (c) 2005-2007 Josef 'Jeff' Sipek
++ * Copyright (c) 2003-2009 Stony Brook University
++ * Copyright (c) 2003-2009 The Research Foundation of SUNY
++ *
++ * 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.
++ */
++
++#ifndef _LINUX_UNION_FS_H
++#define _LINUX_UNION_FS_H
++
++/*
++ * DEFINITIONS FOR USER AND KERNEL CODE:
++ */
++# define UNIONFS_IOCTL_INCGEN _IOR(0x15, 11, int)
++# define UNIONFS_IOCTL_QUERYFILE _IOR(0x15, 15, int)
++
++#endif /* _LINUX_UNIONFS_H */
++
+diff --git a/security/security.c b/security/security.c
+index 351942a..69505f7 100644
+--- a/security/security.c
++++ b/security/security.c
+@@ -529,6 +529,7 @@ int security_inode_permission(struct inode *inode, int mask)
+ return 0;
+ return security_ops->inode_permission(inode, mask);
+ }
++EXPORT_SYMBOL(security_inode_permission);
+
+ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
+ {
diff --git a/recipes/linux/linux-ts75xx_2.6.35.bb b/recipes/linux/linux-ts75xx_2.6.35.bb
new file mode 100644
index 0000000..116efea
--- /dev/null
+++ b/recipes/linux/linux-ts75xx_2.6.35.bb
@@ -0,0 +1,141 @@
+DESCRIPTION = "Linux Kernel"
+SECTION = "kernel"
+LICENSE = "GPLv2"
+PR = "r0"
+STABLEV = "11"
+
+inherit kernel siteinfo
+
+# Mark archs/machines that this kernel supports
+DEFAULT_PREFERENCE = "-1"
+DEFAULT_PREFERENCE_ts75xx = "1"
+
+SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/${P}.tar.bz2;name=kernel \
+ ${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/patch-${PV}.${STABLEV}.bz2;apply=yes;name=stablepatch \
+ file://defconfig "
+
+SRC_URI_ts75xx = "\
+ ${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/longterm/v${PV}/linux-${PV}.${STABLEV}.tar.bz2;name=kernel \
+# backported patches
+ file://ts7500-${PV}.${STABLEV}.patch;apply=yes \
+ file://cavium-userspace-irq-${PV}.patch \
+ file://unionfs-2.5.8_for_2.6.35.11.patch \
+ file://defconfig "
+
+SRC_URI[kernel.md5sum] = "4c9ee33801f5ad0f4d5e615fac66d535"
+SRC_URI[kernel.sha256sum] = "43e30da359dc95edb0b927632a318e6dae1f6e78d954c2e35281e808d00352eb"
+
+do_correct_kernel_dir() {
+ mv ${WORKDIR}/linux-${PV}.${STABLEV} ${S}
+}
+
+addtask correct_kernel_dir after do_unpack before do_patch
+
+do_configure_prepend() {
+
+ # Create a blank .config file
+ echo "" > ${S}/.config
+
+ #
+ # oabi / eabi support
+ #
+ echo "CONFIG_AEABI=y" >> ${S}/.config
+ echo "CONFIG_OABI_COMPAT=y" >> ${S}/.config
+
+ #
+ # disable thumb support in the kernel
+ #
+ sed -i -e /CONFIG_ARM_THUMB/d ${WORKDIR}/defconfig
+ echo "CONFIG_ARM_THUMB=n" >> ${S}/.config
+
+ #
+ # endian support
+ #
+ if [ "${SITEINFO_ENDIANNESS}" = "be" ]; then
+ echo "CONFIG_CPU_BIG_ENDIAN=y" >> ${S}/.config
+ fi
+ echo "CONFIG_CMDLINE=\"${CMDLINE}\"" >> ${S}/.config
+
+ # copy the defconfig over to the .config
+ sed -e '/CONFIG_AEABI/d' \
+ -e '/CONFIG_OABI_COMPAT=/d' \
+ -e '/CONFIG_CMDLINE=/d' \
+ -e '/CONFIG_CPU_BIG_ENDIAN/d' \
+ -e '/CONFIG_LOCALVERSION/d' \
+ -e '/CONFIG_LOCALVERSION_AUTO/d' \
+ -e '/CONFIG_MISC_FILESYSTEMS/d' \
+ -e '/CONFIG_UNION_FS/d' \
+ < '${WORKDIR}/defconfig' >>'${S}/.config'
+ echo 'CONFIG_LOCALVERSION="${LOCALVERSION}"' >>${S}/.config
+ echo '# CONFIG_LOCALVERSION_AUTO is not set' >>${S}/.config
+
+ # Add unionfs support
+ echo "CONFIG_MISC_FILESYSTEMS=y" >> ${S}/.config
+ echo "CONFIG_UNION_FS=y" >> ${S}/.config
+
+ # Newer versions of udev mandate that sysfs doesn't have deprecated entries
+ if [ "${UDEV_GE_141}" = "1" ] ; then
+ sed -e /CONFIG_SYSFS_DEPRECATED/d \
+ -e /CONFIG_SYSFS_DEPRECATED_V2/d \
+ -e /CONFIG_HOTPLUG/d \
+ -e /CONFIG_UEVENT_HELPER_PATH/d \
+ -e /CONFIG_UNIX/d \
+ -e /CONFIG_SYSFS/d \
+ -e /CONFIG_PROC_FS/d \
+ -e /CONFIG_TMPFS/d \
+ -e /CONFIG_INOTIFY_USER/d \
+ -e /CONFIG_SIGNALFD/d \
+ -e /CONFIG_TMPFS_POSIX_ACL/d \
+ -e /CONFIG_BLK_DEV_BSG/d \
+ -i '${S}/.config'
+ echo '# CONFIG_SYSFS_DEPRECATED is not set' >> ${S}/.config
+ echo '# CONFIG_SYSFS_DEPRECATED_V2 is not set' >> ${S}/.config
+ echo 'CONFIG_HOTPLUG=y' >> ${S}/.config
+ echo 'CONFIG_UEVENT_HELPER_PATH=""' >> ${S}/.config
+ echo 'CONFIG_UNIX=y' >> ${S}/.config
+ echo 'CONFIG_SYSFS=y' >> ${S}/.config
+ echo 'CONFIG_PROC_FS=y' >> ${S}/.config
+ echo 'CONFIG_TMPFS=y' >> ${S}/.config
+ echo 'CONFIG_INOTIFY_USER=y' >> ${S}/.config
+ echo 'CONFIG_SIGNALFD=y' >> ${S}/.config
+ echo 'CONFIG_TMPFS_POSIX_ACL=y' >> ${S}/.config
+ echo 'CONFIG_BLK_DEV_BSG=y' >> ${S}/.config
+ echo 'CONFIG_DEVTMPFS=y' >> ${S}/.config
+ echo 'CONFIG_DEVTMPFS_MOUNT=y' >> ${S}/.config
+ fi
+
+ # Newer inits like systemd need cgroup support
+ if [ "${KERNEL_ENABLE_CGROUPS}" = "1" ] ; then
+ sed -e /CONFIG_CGROUP_SCHED/d \
+ -e /CONFIG_CGROUPS/d \
+ -i '${S}/.config'
+ echo 'CONFIG_CGROUP_SCHED=y' >> ${S}/.config
+ echo 'CONFIG_CGROUPS=y' >> ${S}/.config
+ echo 'CONFIG_CGROUP_NS=y' >> ${S}/.config
+ echo 'CONFIG_CGROUP_FREEZER=y' >> ${S}/.config
+ echo 'CONFIG_CGROUP_DEVICE=y' >> ${S}/.config
+ echo 'CONFIG_CPUSETS=y' >> ${S}/.config
+ echo 'CONFIG_PROC_PID_CPUSET=y' >> ${S}/.config
+ echo 'CONFIG_CGROUP_CPUACCT=y' >> ${S}/.config
+ echo 'CONFIG_RESOURCE_COUNTERS=y' >> ${S}/.config
+ fi
+ yes '' | oe_runmake oldconfig
+}
+
+do_configure_append() {
+ if test -e scripts/Makefile.fwinst ; then
+ sed -i -e "s:-m0644:-m 0644:g" scripts/Makefile.fwinst
+ fi
+}
+
+do_install_append() {
+ oe_runmake headers_install INSTALL_HDR_PATH=${D}${exec_prefix}/src/linux-${KERNEL_VERSION} ARCH=$ARCH
+}
+
+do_populate_sysroot() {
+ :
+}
+
+PACKAGES =+ "kernel-headers"
+
+FILES_kernel-headers = "${exec_prefix}/src/linux*"
--
1.7.3.4
More information about the Openembedded-devel
mailing list